mirror of
https://github.com/multipleof4/lynchmark.git
synced 2026-01-14 00:27:55 +00:00
Docs: Update benchmark results
This commit is contained in:
@@ -4,4 +4,6 @@ async function hashPassword(p, s) {
|
|||||||
const h = await scrypt(e.encode(p), e.encode(s), 1024, 8, 1, 32)
|
const h = await scrypt(e.encode(p), e.encode(s), 1024, 8, 1, 32)
|
||||||
return [...h].map(b => b.toString(16).padStart(2, '0')).join('')
|
return [...h].map(b => b.toString(16).padStart(2, '0')).join('')
|
||||||
}
|
}
|
||||||
export default hashPassword;
|
export default hashPassword;
|
||||||
|
// Generation time: 2.609s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
async function hashPassword(password, salt) {
|
async function hashPassword(password, salt) {
|
||||||
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm');
|
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/+esm');
|
||||||
const encoder = new TextEncoder();
|
const enc = new TextEncoder();
|
||||||
const hash = await scrypt(
|
const hash = await scrypt(
|
||||||
encoder.encode(password),
|
enc.encode(password),
|
||||||
encoder.encode(salt),
|
enc.encode(salt),
|
||||||
1024,
|
1024,
|
||||||
8,
|
8,
|
||||||
1,
|
1,
|
||||||
@@ -11,4 +11,6 @@ async function hashPassword(password, salt) {
|
|||||||
);
|
);
|
||||||
return Array.from(hash, b => b.toString(16).padStart(2, '0')).join('');
|
return Array.from(hash, b => b.toString(16).padStart(2, '0')).join('');
|
||||||
}
|
}
|
||||||
export default hashPassword;
|
export default hashPassword;
|
||||||
|
// Generation time: 2.743s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
const hashPassword = async (password, salt) => {
|
|
||||||
const { scrypt } = await import('https://esm.sh/scrypt-js@3.0.1');
|
|
||||||
|
|
||||||
const encoder = new TextEncoder();
|
|
||||||
|
|
||||||
const hashBytes = await scrypt(
|
|
||||||
encoder.encode(password),
|
|
||||||
encoder.encode(salt),
|
|
||||||
1024,
|
|
||||||
8,
|
|
||||||
1,
|
|
||||||
32
|
|
||||||
);
|
|
||||||
|
|
||||||
return [...hashBytes]
|
|
||||||
.map(b => b.toString(16).padStart(2, '0'))
|
|
||||||
.join('');
|
|
||||||
};
|
|
||||||
export default hashPassword;
|
|
||||||
@@ -2,6 +2,8 @@ const hashPassword = async (p, s) => {
|
|||||||
const { scrypt } = await import('https://esm.sh/scrypt-js')
|
const { scrypt } = await import('https://esm.sh/scrypt-js')
|
||||||
const e = new TextEncoder()
|
const e = new TextEncoder()
|
||||||
const h = await scrypt(e.encode(p), e.encode(s), 1024, 8, 1, 32)
|
const h = await scrypt(e.encode(p), e.encode(s), 1024, 8, 1, 32)
|
||||||
return [...h].map(b => b.toString(16).padStart(2, '0')).join('')
|
return Array.from(h).map(b => b.toString(16).padStart(2, '0')).join('')
|
||||||
}
|
}
|
||||||
export default hashPassword;
|
export default hashPassword;
|
||||||
|
// Generation time: 18.084s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
async function hashPassword(password, salt) {
|
async function hashPassword(password, salt) {
|
||||||
const { default: scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/index.js');
|
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/dist/scrypt.min.js');
|
||||||
const e = new TextEncoder();
|
const enc = new TextEncoder();
|
||||||
const p = e.encode(password);
|
const buf = await scrypt(enc.encode(password), enc.encode(salt), 1024, 8, 1, 32);
|
||||||
const s = e.encode(salt);
|
return Array.from(buf, b => b.toString(16).padStart(2, '0')).join('');
|
||||||
const h = await scrypt(p, s, 1024, 8, 1, 32);
|
|
||||||
return [...h].map(b => b.toString(16).padStart(2, '0')).join('');
|
|
||||||
}
|
}
|
||||||
export default hashPassword;
|
export default hashPassword;
|
||||||
|
// Generation time: 39.100s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
const e=new TextEncoder
|
|
||||||
const hashPassword=async(p,s)=>{
|
const hashPassword=async(p,s)=>{
|
||||||
const{ scrypt }=await import('https://cdn.skypack.dev/scrypt-js')
|
const {scrypt}=await import('https://cdn.skypack.dev/scrypt-js')
|
||||||
|
const e=new TextEncoder
|
||||||
const h=await scrypt(e.encode(p),e.encode(s),1024,8,1,32)
|
const h=await scrypt(e.encode(p),e.encode(s),1024,8,1,32)
|
||||||
return Array.from(h,x=>(x+256).toString(16).slice(-2)).join('')
|
return [...h].map(b=>b.toString(16).padStart(2,'0')).join('')
|
||||||
}
|
}
|
||||||
export default hashPassword;
|
export default hashPassword;
|
||||||
|
// Generation time: 8.405s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
const hashPassword = async (password, salt) => {
|
|
||||||
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/scrypt.min.js')
|
|
||||||
const encoder = new TextEncoder()
|
|
||||||
const passwordBytes = encoder.encode(password)
|
|
||||||
const saltBytes = encoder.encode(salt)
|
|
||||||
|
|
||||||
const hashBytes = await scrypt(passwordBytes, saltBytes, 1024, 8, 1, 32)
|
|
||||||
return Array.from(hashBytes)
|
|
||||||
.map(b => b.toString(16).padStart(2, '0'))
|
|
||||||
.join('')
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
async function hashPassword(password, salt) {
|
|
||||||
const { scrypt } = await import('https://cdn.skypack.dev/scrypt-js');
|
|
||||||
const e = new TextEncoder();
|
|
||||||
const pw = e.encode(password);
|
|
||||||
const s = e.encode(salt);
|
|
||||||
const h = await scrypt(pw, s, 1024, 8, 1, 32);
|
|
||||||
return Array.from(h).map(b=>b.toString(16).padStart(2,'0')).join('');
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
async function hashPassword(password, salt) {
|
|
||||||
const { scrypt } = await import('https://cdn.skypack.dev/scrypt-js');
|
|
||||||
const encoder = new TextEncoder();
|
|
||||||
const pwBuf = encoder.encode(password);
|
|
||||||
const saltBuf = encoder.encode(salt);
|
|
||||||
const hashBuf = await scrypt(pwBuf, saltBuf, 1024, 8, 1, 32);
|
|
||||||
return Array.from(hashBuf).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
||||||
}
|
|
||||||
export default hashPassword;
|
|
||||||
11
tests/10_scrypt_hash/outputs/x-ai_grok-4.js
Normal file
11
tests/10_scrypt_hash/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
async function hashPassword(password, salt) {
|
||||||
|
const { scrypt } = await import('https://cdn.jsdelivr.net/npm/scrypt-js@3.0.1/index.js');
|
||||||
|
const encoder = new TextEncoder();
|
||||||
|
const passwordBytes = encoder.encode(password);
|
||||||
|
const saltBytes = encoder.encode(salt);
|
||||||
|
const hashBytes = await scrypt(passwordBytes, saltBytes, 1024, 8, 1, 32);
|
||||||
|
return Array.from(hashBytes, byte => byte.toString(16).padStart(2, '0')).join('').toLowerCase();
|
||||||
|
}
|
||||||
|
export default hashPassword;
|
||||||
|
// Generation time: 12.779s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
async function analyzeGPS(readings, boundary) {
|
async function analyzeGPS(readings, boundary) {
|
||||||
const turf = await import('https://cdn.jsdelivr.net/npm/@turf/turf@7/+esm');
|
const turf = await import("https://esm.sh/@turf/turf");
|
||||||
|
|
||||||
const valid = readings
|
const valid = readings
|
||||||
.filter(r => turf.booleanPointInPolygon(turf.point(r.loc), boundary, { ignoreBoundary: true }))
|
.filter(r => turf.booleanPointInPolygon(turf.point(r.loc), boundary, { ignoreBoundary: true }))
|
||||||
.sort((a, b) => a.ts - b.ts);
|
.sort((a, b) => a.ts - b.ts);
|
||||||
|
|
||||||
if (valid.length < 2) return 0;
|
if (valid.length < 2) return 0;
|
||||||
|
|
||||||
const line = turf.lineString(valid.map(r => r.loc));
|
const line = turf.lineString(valid.map(r => r.loc));
|
||||||
const len = turf.length(line, { units: 'kilometers' });
|
return Math.round(turf.length(line, { units: "kilometers" }) * 100) / 100;
|
||||||
|
|
||||||
return Math.round(len * 100) / 100;
|
|
||||||
}
|
}
|
||||||
export default analyzeGPS;
|
export default analyzeGPS;
|
||||||
|
// Generation time: 3.155s
|
||||||
|
// Result: PASS
|
||||||
@@ -11,4 +11,6 @@ async function analyzeGPS(readings, boundary) {
|
|||||||
|
|
||||||
return Math.round(turf.length(line) * 100) / 100;
|
return Math.round(turf.length(line) * 100) / 100;
|
||||||
}
|
}
|
||||||
export default analyzeGPS;
|
export default analyzeGPS;
|
||||||
|
// Generation time: 2.827s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
const analyzeGPS = async (readings, boundary) => {
|
|
||||||
const { booleanPointInPolygon, lineString, length } = await import('https://cdn.jsdelivr.net/npm/@turf/turf/+esm');
|
|
||||||
|
|
||||||
const sortedCoords = readings
|
|
||||||
.filter(({ loc }) => booleanPointInPolygon(loc, boundary, { ignoreBoundary: true }))
|
|
||||||
.sort((a, b) => a.ts - b.ts)
|
|
||||||
.map(({ loc }) => loc);
|
|
||||||
|
|
||||||
if (sortedCoords.length < 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const path = lineString(sortedCoords);
|
|
||||||
const dist = length(path, { units: 'kilometers' });
|
|
||||||
|
|
||||||
return Math.round(dist * 1e2) / 1e2;
|
|
||||||
};
|
|
||||||
export default analyzeGPS;
|
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
const analyzeGPS = async (readings, boundary) => {
|
const analyzeGPS = async (readings, boundary) => {
|
||||||
const turf = await import('https://cdn.jsdelivr.net/npm/@turf/turf/+esm');
|
const t = await import('https://cdn.jsdelivr.net/npm/@turf/turf/+esm');
|
||||||
|
|
||||||
const pts = readings
|
const pts = readings
|
||||||
.filter(({ loc }) => turf.booleanPointInPolygon(turf.point(loc), boundary))
|
.filter(r => t.booleanPointInPolygon(t.point(r.loc), boundary, { ignoreBoundary: true }))
|
||||||
.sort((a, b) => a.ts - b.ts)
|
.sort((a, b) => a.ts - b.ts)
|
||||||
.map(r => r.loc);
|
.map(r => r.loc);
|
||||||
|
|
||||||
return pts.length < 2 ? 0 :
|
return pts.length < 2 ? 0
|
||||||
+turf.length(turf.lineString(pts), { units: 'kilometers' }).toFixed(2);
|
: +t.length(t.lineString(pts), { units: 'kilometers' }).toFixed(2);
|
||||||
};
|
};
|
||||||
export default analyzeGPS;
|
export default analyzeGPS;
|
||||||
|
// Generation time: 41.986s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,11 +1,18 @@
|
|||||||
export async function analyzeGPS(readings, boundary) {
|
async function analyzeGPS(readings, boundary) {
|
||||||
const { booleanPointInPolygon, lineString, length } = await import('https://cdn.skypack.dev/@turf/turf');
|
const isValid = r => r?.ts != null && Array.isArray(r?.loc) && r.loc.length === 2;
|
||||||
|
const valid = readings?.filter(isValid) || [];
|
||||||
|
if (valid.length < 2) return 0;
|
||||||
|
|
||||||
const pts = readings
|
const turf = await import('https://cdn.skypack.dev/@turf/turf').catch(() => null);
|
||||||
.filter(r => booleanPointInPolygon(r.loc, boundary))
|
if (!turf) return 0;
|
||||||
|
|
||||||
|
const points = valid
|
||||||
|
.filter(r => turf.booleanPointInPolygon(r.loc, boundary))
|
||||||
.sort((a, b) => a.ts - b.ts)
|
.sort((a, b) => a.ts - b.ts)
|
||||||
.map(r => r.loc);
|
.map(r => r.loc);
|
||||||
|
|
||||||
return pts.length < 2 ? 0 : +length(lineString(pts)).toFixed(2);
|
return points.length < 2 ? 0 : Math.round(turf.length(turf.lineString(points), {units: 'kilometers'}) * 100) / 100;
|
||||||
}
|
}
|
||||||
export default analyzeGPS;
|
export default analyzeGPS;
|
||||||
|
// Generation time: 48.580s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
let turf$;
|
let turfReady
|
||||||
const useTurf = () => turf$ ??= import('https://cdn.skypack.dev/@turf/turf?min');
|
const loadTurf=()=>turfReady||(turfReady=import('https://cdn.jsdelivr.net/npm/@turf/turf@6.5.0/+esm'))
|
||||||
|
async function analyzeGPS(readings,boundary){
|
||||||
async function analyzeGPS(readings, boundary) {
|
const {point,lineString,length,booleanPointInPolygon}=await loadTurf()
|
||||||
const t = await useTurf();
|
const inBounds=readings.filter(r=>booleanPointInPolygon(point(r.loc),boundary,{ignoreBoundary:true})).sort((a,b)=>a.ts-b.ts)
|
||||||
const pts = readings
|
if(inBounds.length<2)return 0
|
||||||
.filter(r => t.booleanPointInPolygon(t.point(r.loc), boundary))
|
const km=length(lineString(inBounds.map(r=>r.loc)),{units:'kilometers'})
|
||||||
.sort((a, b) => a.ts - b.ts);
|
return +km.toFixed(2)
|
||||||
if (pts.length < 2) return 0;
|
|
||||||
const km = t.length(t.lineString(pts.map(r => r.loc)), { units: 'kilometers' });
|
|
||||||
return Math.round(km * 100) / 100;
|
|
||||||
}
|
}
|
||||||
export default analyzeGPS;
|
export default analyzeGPS;
|
||||||
|
// Generation time: 8.791s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
export const analyzeGPS = async (readings, boundary) => {
|
|
||||||
const { default: turf } = await import('https://unpkg.com/@turf/turf@6/turf.min.js')
|
|
||||||
|
|
||||||
const inside = readings.filter(({ loc }) =>
|
|
||||||
turf.booleanPointInPolygon(turf.point(loc), boundary, { ignoreBoundary: false })
|
|
||||||
)
|
|
||||||
|
|
||||||
if (inside.length < 2) return 0
|
|
||||||
|
|
||||||
const sorted = inside.sort((a, b) => a.ts - b.ts)
|
|
||||||
const line = turf.lineString(sorted.map(({ loc }) => loc))
|
|
||||||
const length = turf.length(line, { units: 'kilometers' })
|
|
||||||
|
|
||||||
return Math.round(length * 100) / 100
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
async function analyzeGPS(readings,boundary){
|
|
||||||
const{booleanPointInPolygon,lineString,length}=await import('https://cdn.skypack.dev/@turf/turf');
|
|
||||||
const valid=readings
|
|
||||||
.filter(r=>booleanPointInPolygon({type:'Point',coordinates:r.loc},boundary,{ignoreBoundary:true}))
|
|
||||||
.sort((a,b)=>a.ts-b.ts);
|
|
||||||
return valid.length<2?0:+length(lineString(valid.map(r=>r.loc)),{units:'kilometers'}).toFixed(2);
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
async function analyzeGPS(readings, boundary) {
|
|
||||||
const { point: p, booleanPointInPolygon: i, lineString: s, length: l } = await import('https://esm.sh/@turf/turf@6');
|
|
||||||
const v = readings.filter(r => i(p(r.loc), boundary)).sort((a, b) => a.ts - b.ts);
|
|
||||||
return v.length < 2 ? 0 : +l(s(v.map(r => r.loc))).toFixed(2);
|
|
||||||
}
|
|
||||||
export default analyzeGPS;
|
|
||||||
13
tests/11_geospatial/outputs/x-ai_grok-4.js
Normal file
13
tests/11_geospatial/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
async function analyzeGPS(readings, boundary) {
|
||||||
|
const turf = await import('https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js');
|
||||||
|
const valid = readings
|
||||||
|
.filter(r => turf.booleanPointInPolygon(turf.point(r.loc), boundary))
|
||||||
|
.sort((a, b) => a.ts - b.ts);
|
||||||
|
if (valid.length < 2) return 0;
|
||||||
|
const line = { type: 'LineString', coordinates: valid.map(r => r.loc) };
|
||||||
|
const length = turf.length(line, { units: 'kilometers' });
|
||||||
|
return Math.round(length * 100) / 100;
|
||||||
|
}
|
||||||
|
export default analyzeGPS;
|
||||||
|
// Generation time: 17.976s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
async function findShortestPath(graph, start, end) {
|
async function findShortestPath(graph, start, end) {
|
||||||
const { default: PriorityQueue } = await import("https://esm.run/js-priority-queue");
|
const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.4.1/+esm');
|
||||||
|
|
||||||
const dist = {}, visited = new Set();
|
|
||||||
|
|
||||||
for (let n in graph) dist[n] = Infinity;
|
|
||||||
dist[start] = 0;
|
|
||||||
|
|
||||||
|
const dist = { [start]: 0 };
|
||||||
|
const visited = new Set();
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] });
|
const pq = new PriorityQueue({ comparator: (a, b) => a[1] - b[1] });
|
||||||
|
|
||||||
pq.queue([start, 0]);
|
pq.queue([start, 0]);
|
||||||
|
|
||||||
while (pq.length) {
|
while (pq.length) {
|
||||||
@@ -17,16 +15,17 @@ async function findShortestPath(graph, start, end) {
|
|||||||
|
|
||||||
if (node === end) return d;
|
if (node === end) return d;
|
||||||
|
|
||||||
for (let neighbor in graph[node] || {}) {
|
for (const [neighbor, weight] of Object.entries(graph[node] || {})) {
|
||||||
if (visited.has(neighbor)) continue;
|
const newDist = d + weight;
|
||||||
const newDist = d + graph[node][neighbor];
|
if (newDist < (dist[neighbor] ?? Infinity)) {
|
||||||
if (newDist < dist[neighbor]) {
|
|
||||||
dist[neighbor] = newDist;
|
dist[neighbor] = newDist;
|
||||||
pq.queue([neighbor, newDist]);
|
pq.queue([neighbor, newDist]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dist[end] ?? Infinity;
|
return Infinity;
|
||||||
}
|
}
|
||||||
export default findShortestPath;
|
export default findShortestPath;
|
||||||
|
// Generation time: 4.850s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,31 +1,35 @@
|
|||||||
async function findShortestPath(graph, start, end) {
|
async function findShortestPath(graph, start, end) {
|
||||||
const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm');
|
const { default: PriorityQueue } = await import('https://cdn.skypack.dev/js-priority-queue');
|
||||||
|
|
||||||
const distances = Object.keys(graph).reduce((acc, node) => ({ ...acc, [node]: Infinity }), {});
|
|
||||||
distances[start] = 0;
|
|
||||||
|
|
||||||
|
const distances = {};
|
||||||
|
const visited = new Set();
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a.dist - b.dist });
|
const pq = new PriorityQueue({ comparator: (a, b) => a.dist - b.dist });
|
||||||
|
|
||||||
|
for (const node in graph) distances[node] = Infinity;
|
||||||
|
distances[start] = 0;
|
||||||
pq.queue({ node: start, dist: 0 });
|
pq.queue({ node: start, dist: 0 });
|
||||||
|
|
||||||
const visited = new Set();
|
while (pq.length > 0) {
|
||||||
|
|
||||||
while (pq.length) {
|
|
||||||
const { node, dist } = pq.dequeue();
|
const { node, dist } = pq.dequeue();
|
||||||
|
|
||||||
if (visited.has(node)) continue;
|
if (visited.has(node)) continue;
|
||||||
visited.add(node);
|
|
||||||
|
|
||||||
if (node === end) return dist;
|
if (node === end) return dist;
|
||||||
|
|
||||||
for (const [neighbor, weight] of Object.entries(graph[node] || {})) {
|
visited.add(node);
|
||||||
const newDist = dist + weight;
|
|
||||||
if (newDist < distances[neighbor]) {
|
for (const neighbor in graph[node]) {
|
||||||
distances[neighbor] = newDist;
|
if (!visited.has(neighbor)) {
|
||||||
pq.queue({ node: neighbor, dist: newDist });
|
const newDist = dist + graph[node][neighbor];
|
||||||
|
if (newDist < distances[neighbor]) {
|
||||||
|
distances[neighbor] = newDist;
|
||||||
|
pq.queue({ node: neighbor, dist: newDist });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return distances[end];
|
return Infinity;
|
||||||
}
|
}
|
||||||
export default findShortestPath;
|
export default findShortestPath;
|
||||||
|
// Generation time: 4.029s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
async function findShortestPath(graph, startNode, endNode) {
|
|
||||||
const { default: PriorityQueue } = await import(
|
|
||||||
'https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/priority-queue.min.js'
|
|
||||||
);
|
|
||||||
|
|
||||||
const distances = {};
|
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a.priority - b.priority });
|
|
||||||
|
|
||||||
for (const node in graph) {
|
|
||||||
distances[node] = Infinity;
|
|
||||||
}
|
|
||||||
distances[startNode] = 0;
|
|
||||||
|
|
||||||
pq.queue({ node: startNode, priority: 0 });
|
|
||||||
|
|
||||||
while (pq.length) {
|
|
||||||
const { node: currentNode, priority: currentPriority } = pq.dequeue();
|
|
||||||
|
|
||||||
if (currentPriority > distances[currentNode]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentNode === endNode) {
|
|
||||||
return currentPriority;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const neighbor in graph[currentNode]) {
|
|
||||||
const weight = graph[currentNode][neighbor];
|
|
||||||
const newDistance = currentPriority + weight;
|
|
||||||
|
|
||||||
if (newDistance < distances[neighbor]) {
|
|
||||||
distances[neighbor] = newDistance;
|
|
||||||
pq.queue({ node: neighbor, priority: newDistance });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
const findShortestPath = async (g, s, e) => {
|
const findShortestPath = async (g, s, e) => {
|
||||||
const { default: Q } = await import('https://esm.sh/js-priority-queue')
|
const { default: PQ } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/+esm')
|
||||||
const q = new Q({ comparator: (a, b) => a.w - b.w })
|
const q = new PQ({ comparator: (a, b) => a.w - b.w })
|
||||||
const d = { [s]: 0 }
|
const d = { [s]: 0 }
|
||||||
|
|
||||||
q.queue({ n: s, w: 0 })
|
q.queue({ n: s, w: 0 })
|
||||||
|
|
||||||
while (q.length) {
|
while (q.length) {
|
||||||
@@ -9,14 +10,17 @@ const findShortestPath = async (g, s, e) => {
|
|||||||
if (n === e) return w
|
if (n === e) return w
|
||||||
if (w > (d[n] ?? Infinity)) continue
|
if (w > (d[n] ?? Infinity)) continue
|
||||||
|
|
||||||
for (const v in g[n]) {
|
for (const k in g[n] || {}) {
|
||||||
const k = w + g[n][v]
|
const t = w + g[n][k]
|
||||||
if (k < (d[v] ?? Infinity)) {
|
if (t < (d[k] ?? Infinity)) {
|
||||||
d[v] = k
|
d[k] = t
|
||||||
q.queue({ n: v, w: k })
|
q.queue({ n: k, w: t })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Infinity
|
return Infinity
|
||||||
}
|
}
|
||||||
export default findShortestPath;
|
export default findShortestPath;
|
||||||
|
// Generation time: 30.290s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,28 +1,27 @@
|
|||||||
export async function findShortestPath(graph, start, end) {
|
let PQ;
|
||||||
const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@0.1.5/index.min.js');
|
export async function findShortestPath(g, s, e) {
|
||||||
|
if (!(s in g) || !(e in g)) return Infinity;
|
||||||
if (!graph[start] || !graph[end]) return Infinity;
|
if (!PQ) ({ default: PQ } = await import('https://cdn.skypack.dev/js-priority-queue@0.1.5'));
|
||||||
if (start === end) return 0;
|
const d = new Map([[s, 0]]);
|
||||||
|
const q = new PQ({ comparator: (a, b) => a[1] - b[1] });
|
||||||
const dist = { [start]: 0 };
|
const v = new Set();
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a[0] - b[0] });
|
q.queue([s, 0]);
|
||||||
pq.queue([0, start]);
|
while (q.length) {
|
||||||
|
const [n, c] = q.dequeue();
|
||||||
while (pq.length) {
|
if (n === e) return c;
|
||||||
const [d, node] = pq.dequeue();
|
if (v.has(n)) continue;
|
||||||
|
v.add(n);
|
||||||
if (node === end) return d;
|
if (c > (d.get(n) ?? Infinity)) continue;
|
||||||
if (d > (dist[node] ?? Infinity)) continue;
|
for (const [p, w] of Object.entries(g[n] || {})) {
|
||||||
|
const t = c + w;
|
||||||
for (const [n, w] of Object.entries(graph[node] || {})) {
|
if (t < (d.get(p) ?? Infinity)) {
|
||||||
const nd = d + w;
|
d.set(p, t);
|
||||||
if (nd < (dist[n] ?? Infinity)) {
|
q.queue([p, t]);
|
||||||
dist[n] = nd;
|
|
||||||
pq.queue([nd, n]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return d.get(e) ?? Infinity;
|
||||||
return Infinity;
|
|
||||||
}
|
}
|
||||||
export default findShortestPath;
|
export default findShortestPath;
|
||||||
|
// Generation time: 95.484s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,30 +1,24 @@
|
|||||||
let pqPromise
|
export const findShortestPath=async(g,s,e)=>{
|
||||||
const getPQ=()=>pqPromise??=import('https://cdn.jsdelivr.net/npm/js-priority-queue@latest/+esm')
|
const{default:Q}=await import('https://esm.sh/js-priority-queue')
|
||||||
|
const d={},v=new Set(),q=new Q({comparator:(a,b)=>a[1]-b[1]})
|
||||||
async function findShortestPath(g,s,t){
|
for(const k in g)d[k]=Infinity
|
||||||
if(!g||!(s in g)||!(t in g)) return Infinity
|
d[s]=0
|
||||||
if(s===t) return 0
|
q.queue([s,0])
|
||||||
const {default:PriorityQueue}=await getPQ()
|
while(q.length){
|
||||||
const d={[s]:0}
|
const[n,w]=q.dequeue()
|
||||||
const seen=new Set
|
if(v.has(n))continue
|
||||||
const q=new PriorityQueue({comparator:(a,b)=>a[0]-b[0]})
|
if(n===e)return w
|
||||||
q.queue([0,s])
|
v.add(n)
|
||||||
while(q.length){
|
for(const[nb,c]of Object.entries(g[n]||{})){
|
||||||
const [w,n]=q.dequeue()
|
const nw=w+c
|
||||||
if(seen.has(n)) continue
|
if(nw<d[nb]){
|
||||||
seen.add(n)
|
d[nb]=nw
|
||||||
if(n===t) return w
|
q.queue([nb,nw])
|
||||||
const edges=g[n]
|
}
|
||||||
if(!edges) continue
|
}
|
||||||
for(const k in edges){
|
}
|
||||||
if(seen.has(k)) continue
|
return Infinity
|
||||||
const nw=w+edges[k]
|
|
||||||
if(nw<(d[k]??Infinity)){
|
|
||||||
d[k]=nw
|
|
||||||
q.queue([nw,k])
|
|
||||||
}
|
}
|
||||||
}
|
export default findShortestPath;
|
||||||
}
|
// Generation time: 9.436s
|
||||||
return Infinity
|
// Result: PASS
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
const findShortestPath = async (graph, start, end) => {
|
|
||||||
const { default: PriorityQueue } = await import('https://cdn.jsdelivr.net/npm/js-priority-queue@1.0.0/+esm')
|
|
||||||
|
|
||||||
if (!graph[start] || !graph[end]) return Infinity
|
|
||||||
|
|
||||||
const distances = Object.keys(graph).reduce((acc, node) => {
|
|
||||||
acc[node] = node === start ? 0 : Infinity
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a.distance - b.distance })
|
|
||||||
pq.queue({ node: start, distance: 0 })
|
|
||||||
|
|
||||||
const visited = new Set()
|
|
||||||
|
|
||||||
while (pq.length) {
|
|
||||||
const { node, distance } = pq.dequeue()
|
|
||||||
|
|
||||||
if (node === end) return distance
|
|
||||||
if (visited.has(node)) continue
|
|
||||||
|
|
||||||
visited.add(node)
|
|
||||||
|
|
||||||
Object.entries(graph[node]).forEach(([neighbor, weight]) => {
|
|
||||||
if (visited.has(neighbor)) return
|
|
||||||
|
|
||||||
const newDistance = distance + weight
|
|
||||||
if (newDistance < distances[neighbor]) {
|
|
||||||
distances[neighbor] = newDistance
|
|
||||||
pq.queue({ node: neighbor, distance: newDistance })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return Infinity
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
async function findShortestPath(graph,start,end){
|
|
||||||
const {PriorityQueue}=await import('https://cdn.skypack.dev/js-priority-queue');
|
|
||||||
if(start===end)return 0;
|
|
||||||
const dist={};
|
|
||||||
dist[start]=0;
|
|
||||||
const pq=new PriorityQueue({comparator:(a,b)=>a.dist-b.dist});
|
|
||||||
pq.queue({node:start,dist:0});
|
|
||||||
while(!pq.isEmpty()){
|
|
||||||
const u=pq.dequeue();
|
|
||||||
if(u.dist>dist[u.node])continue;
|
|
||||||
const neighbors=graph[u.node];
|
|
||||||
if(!neighbors)continue;
|
|
||||||
for(const v in neighbors){
|
|
||||||
const w=neighbors[v];
|
|
||||||
const alt=dist[u.node]+w;
|
|
||||||
if(alt<(dist[v]??Infinity)){
|
|
||||||
dist[v]=alt;
|
|
||||||
pq.queue({node:v,dist:alt});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dist[end]??Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
async function findShortestPath(graph, start, end) {
|
|
||||||
const { PriorityQueue } = await import('https://cdn.skypack.dev/js-priority-queue');
|
|
||||||
const pq = new PriorityQueue({ comparator: (a, b) => a.d - b.d });
|
|
||||||
const dist = {};
|
|
||||||
dist[start] = 0;
|
|
||||||
pq.queue({ node: start, d: 0 });
|
|
||||||
while (!pq.isEmpty()) {
|
|
||||||
const { node, d } = pq.dequeue();
|
|
||||||
if (d > dist[node]) continue;
|
|
||||||
if (node === end) return d;
|
|
||||||
for (const [nei, w] of Object.entries(graph[node] || {})) {
|
|
||||||
const alt = d + w;
|
|
||||||
if (alt < (dist[nei] ?? Infinity)) {
|
|
||||||
dist[nei] = alt;
|
|
||||||
pq.queue({ node: nei, d: alt });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
export default findShortestPath;
|
|
||||||
22
tests/1_dijkstra/outputs/x-ai_grok-4.js
Normal file
22
tests/1_dijkstra/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
async function findShortestPath(graph, start, end) {
|
||||||
|
const PQ = (await import('https://unpkg.com/js-priority-queue@0.1.5')).default;
|
||||||
|
const D = {};
|
||||||
|
D[start] = 0;
|
||||||
|
const q = new PQ({comparator: (a, b) => a.d - b.d});
|
||||||
|
q.queue({n: start, d: 0});
|
||||||
|
while (q.length) {
|
||||||
|
let {n: u, d} = q.dequeue();
|
||||||
|
if (d > D[u]) continue;
|
||||||
|
for (let v in graph[u]) {
|
||||||
|
let a = d + graph[u][v];
|
||||||
|
if (a < (D[v] ?? Infinity)) {
|
||||||
|
D[v] = a;
|
||||||
|
q.queue({n: v, d: a});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return D[end] ?? Infinity;
|
||||||
|
}
|
||||||
|
export default findShortestPath;
|
||||||
|
// Generation time: 82.003s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
const findConvexHull = async (points) => {
|
async function findConvexHull(points) {
|
||||||
const _ = (await import("https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js")).default;
|
const _ = (await import("https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js")).default;
|
||||||
|
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
||||||
@@ -22,6 +22,11 @@ const findConvexHull = async (points) => {
|
|||||||
upper.push(p);
|
upper.push(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...lower.slice(0, -1), ...upper.slice(0, -1)];
|
lower.pop();
|
||||||
};
|
upper.pop();
|
||||||
export default findConvexHull;
|
|
||||||
|
return [...lower, ...upper];
|
||||||
|
}
|
||||||
|
export default findConvexHull;
|
||||||
|
// Generation time: 5.506s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,34 +1,28 @@
|
|||||||
async function findConvexHull(points) {
|
const findConvexHull = async (points) => {
|
||||||
const { sortBy, uniqWith } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js');
|
const { sortBy, uniqWith, isEqual } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js');
|
||||||
|
|
||||||
if (points.length < 3) return points;
|
if (points.length < 3) return points;
|
||||||
|
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
const sorted = sortBy(uniqWith(points, isEqual), ['x', 'y']);
|
||||||
|
|
||||||
const sorted = sortBy(uniqWith(points, (a, b) => a.x === b.x && a.y === b.y), ['x', 'y']);
|
|
||||||
|
|
||||||
if (sorted.length < 3) return sorted;
|
if (sorted.length < 3) return sorted;
|
||||||
|
|
||||||
const lower = [];
|
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
||||||
for (const p of sorted) {
|
|
||||||
while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) {
|
const buildHalf = (pts) => {
|
||||||
lower.pop();
|
const hull = [];
|
||||||
|
for (const p of pts) {
|
||||||
|
while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
|
||||||
|
hull.pop();
|
||||||
|
}
|
||||||
|
hull.push(p);
|
||||||
}
|
}
|
||||||
lower.push(p);
|
hull.pop();
|
||||||
}
|
return hull;
|
||||||
|
};
|
||||||
|
|
||||||
const upper = [];
|
return [...buildHalf(sorted), ...buildHalf([...sorted].reverse())];
|
||||||
for (let i = sorted.length - 1; i >= 0; i--) {
|
};
|
||||||
const p = sorted[i];
|
export default findConvexHull;
|
||||||
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) {
|
// Generation time: 4.808s
|
||||||
upper.pop();
|
// Result: PASS
|
||||||
}
|
|
||||||
upper.push(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
lower.pop();
|
|
||||||
upper.pop();
|
|
||||||
|
|
||||||
return lower.concat(upper);
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
async const findConvexHull = async (points) => {
|
|
||||||
const { sortBy, uniqWith, isEqual } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js');
|
|
||||||
|
|
||||||
const cross = (p1, p2, p3) =>
|
|
||||||
(p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
|
|
||||||
|
|
||||||
const sortedPoints = sortBy(uniqWith(points, isEqual), ['x', 'y']);
|
|
||||||
|
|
||||||
if (sortedPoints.length <= 3) {
|
|
||||||
return sortedPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildHull = (pointSet) => {
|
|
||||||
const hull = [];
|
|
||||||
for (const p of pointSet) {
|
|
||||||
while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
|
|
||||||
hull.pop();
|
|
||||||
}
|
|
||||||
hull.push(p);
|
|
||||||
}
|
|
||||||
return hull;
|
|
||||||
};
|
|
||||||
|
|
||||||
const lower = buildHull(sortedPoints);
|
|
||||||
const upper = buildHull([...sortedPoints].reverse());
|
|
||||||
|
|
||||||
return [...lower.slice(0, -1), ...upper.slice(0, -1)];
|
|
||||||
};
|
|
||||||
export default findConvexHull;
|
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
const findConvexHull = async (pts) => {
|
const findConvexHull = async (pts) => {
|
||||||
const { sortBy: S, uniqWith: U, isEqual: E } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm')
|
const { default: _ } = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm')
|
||||||
const p = S(U(pts, E), ['x', 'y'])
|
const s = _.sortBy(_.uniqWith(pts, _.isEqual), ['x', 'y'])
|
||||||
if (p.length < 3) return p
|
if (s.length < 3) return s
|
||||||
const X = (a, b, o) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x)
|
|
||||||
const B = (list) => {
|
const cp = (a, b, c) => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
|
||||||
const h = []
|
const walk = (h, p) => {
|
||||||
for (const pt of list) {
|
while (h.length >= 2 && cp(h[h.length - 2], h[h.length - 1], p) <= 0) h.pop()
|
||||||
while (h.length >= 2 && X(h[h.length - 1], pt, h[h.length - 2]) <= 0) h.pop()
|
h.push(p)
|
||||||
h.push(pt)
|
|
||||||
}
|
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
const l = B(p)
|
|
||||||
const u = B(p.reverse())
|
const l = s.reduce(walk, [])
|
||||||
l.pop()
|
const u = s.reduceRight(walk, [])
|
||||||
u.pop()
|
|
||||||
return l.concat(u)
|
return [...l.slice(0, -1), ...u.slice(0, -1)]
|
||||||
}
|
}
|
||||||
export default findConvexHull;
|
export default findConvexHull;
|
||||||
|
// Generation time: 33.416s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,18 +1,23 @@
|
|||||||
async function findConvexHull(pts) {
|
async function findConvexHull(p) {
|
||||||
if (!Array.isArray(pts)) return [];
|
const { default: _ } = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js'),
|
||||||
const { default: _ } = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js');
|
u = _.uniqWith(_.sortBy(p, 'x', 'y'), (a, b) => a.x === b.x && a.y === b.y);
|
||||||
const points = _.sortBy(_.uniqWith(pts, (a, b) => a.x === b.x && a.y === b.y), ['x', 'y']);
|
if (u.length < 3) return u;
|
||||||
if (points.length < 3) return points;
|
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x),
|
||||||
const build = (h, p) => {
|
build = (pts) => {
|
||||||
while (h.length >= 2 && cross(h[h.length - 2], h[h.length - 1], p) <= 0) h.pop();
|
const h = [];
|
||||||
h.push(p);
|
for (const q of pts) {
|
||||||
};
|
while (h.length > 1 && cross(h[h.length - 2], h[h.length - 1], q) <= 0) h.pop();
|
||||||
const lower = [], upper = [];
|
h.push(q);
|
||||||
for (const p of points) build(lower, p);
|
}
|
||||||
for (let i = points.length; i--; ) build(upper, points[i]);
|
return h;
|
||||||
lower.pop();
|
};
|
||||||
upper.pop();
|
|
||||||
return lower.concat(upper);
|
const l = build(u),
|
||||||
|
r = build([...u].reverse());
|
||||||
|
|
||||||
|
return [...l.slice(0, -1), ...r.slice(0, -1)];
|
||||||
}
|
}
|
||||||
export default findConvexHull;
|
export default findConvexHull;
|
||||||
|
// Generation time: 147.393s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
async function findConvexHull(points) {
|
export async function findConvexHull(pts){
|
||||||
const { uniqWith, isEqual, sortBy } = await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js')
|
const {default:_}=await import('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js');
|
||||||
const pts = sortBy(uniqWith(points, isEqual), ['x', 'y'])
|
const p=_.orderBy(_.uniqWith(pts,(a,b)=>a.x===b.x&&a.y===b.y),['x','y']);
|
||||||
if (pts.length < 3) return pts
|
if(p.length<3)return p;
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x)
|
const c=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
|
||||||
const scan = (src, acc = []) => {
|
const l=[],u=[];
|
||||||
src.forEach(p => {
|
for(const v of p){
|
||||||
while (acc.length > 1 && cross(acc.at(-2), acc.at(-1), p) <= 0) acc.pop()
|
while(l.length>1&&c(l[l.length-2],l[l.length-1],v)<=0)l.pop();
|
||||||
acc.push(p)
|
l.push(v);
|
||||||
})
|
|
||||||
return acc
|
|
||||||
}
|
}
|
||||||
const lower = scan(pts)
|
for(const v of [...p].reverse()){
|
||||||
const upper = scan([...pts].reverse())
|
while(u.length>1&&c(u[u.length-2],u[u.length-1],v)<=0)u.pop();
|
||||||
lower.pop()
|
u.push(v);
|
||||||
upper.pop()
|
}
|
||||||
return lower.concat(upper)
|
return l.slice(0,-1).concat(u.slice(0,-1));
|
||||||
}
|
}
|
||||||
export default findConvexHull;
|
export default findConvexHull;
|
||||||
|
// Generation time: 10.565s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
const findConvexHull = async points => {
|
|
||||||
const { sortBy, uniqWith, isEqual } = await import('https://cdn.skypack.dev/lodash')
|
|
||||||
|
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x)
|
|
||||||
|
|
||||||
const preparePoints = pts => {
|
|
||||||
const unique = uniqWith(pts, isEqual)
|
|
||||||
return sortBy(unique, ['x', 'y'])
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildHull = pts => {
|
|
||||||
const hull = []
|
|
||||||
|
|
||||||
for (const p of pts) {
|
|
||||||
while (hull.length >= 2 && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
|
|
||||||
hull.pop()
|
|
||||||
}
|
|
||||||
hull.push(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
const lowerHullSize = hull.length + 1
|
|
||||||
for (let i = pts.length - 1; i >= 0; i--) {
|
|
||||||
const p = pts[i]
|
|
||||||
while (hull.length >= lowerHullSize && cross(hull[hull.length - 2], hull[hull.length - 1], p) <= 0) {
|
|
||||||
hull.pop()
|
|
||||||
}
|
|
||||||
hull.push(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
hull.pop()
|
|
||||||
return hull
|
|
||||||
}
|
|
||||||
|
|
||||||
if (points.length < 3) return [...points]
|
|
||||||
const prepared = preparePoints(points)
|
|
||||||
return buildHull(prepared)
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
async function findConvexHull(pts){
|
|
||||||
const{ sortBy:s,uniqBy:u }=await import('https://cdn.skypack.dev/lodash');
|
|
||||||
if(!pts?.length)return[];
|
|
||||||
const p=u(s(pts,['x','y']),t=>`${t.x},${t.y}`);
|
|
||||||
if(p.length<2)return p;
|
|
||||||
const c=(o,a,b)=>(a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
|
|
||||||
let l=[];for(let t of p){while(l.length>1&&c(l[l.length-2],l[l.length-1],t)<=0)l.pop();l.push(t)}
|
|
||||||
let r=[];for(let i=p.length-1;i>=0;i--){const t=p[i];while(r.length>1&&c(r[r.length-2],r[r.length-1],t)<=0)r.pop();r.push(t)}
|
|
||||||
l.pop();r.pop();
|
|
||||||
return[...l,...r];
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
async function findConvexHull(pts) {
|
|
||||||
const { sortBy, uniqBy } = await import('https://cdn.skypack.dev/lodash-es');
|
|
||||||
const ps = uniqBy(pts, p => `${p.x},${p.y}`);
|
|
||||||
if (ps.length < 2) return ps;
|
|
||||||
const sorted = sortBy(ps, ['x', 'y']);
|
|
||||||
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
|
||||||
const build = (pnts) => {
|
|
||||||
const h = [];
|
|
||||||
for (let p of pnts) {
|
|
||||||
while (h.length > 1 && cross(h[h.length - 2], h.at(-1), p) <= 0) h.pop();
|
|
||||||
h.push(p);
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
};
|
|
||||||
const lower = build(sorted);
|
|
||||||
const upper = build([...sorted].reverse());
|
|
||||||
return [...lower.slice(0, -1), ...upper.slice(0, -1)];
|
|
||||||
}
|
|
||||||
export default findConvexHull;
|
|
||||||
28
tests/2_convex_hull/outputs/x-ai_grok-4.js
Normal file
28
tests/2_convex_hull/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
async function findConvexHull(points) {
|
||||||
|
const _ = await import('https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js');
|
||||||
|
if (points.length <= 1) return points.slice();
|
||||||
|
let pts = _.sortBy(_.uniqWith(points, (a, b) => a.x === b.x && a.y === b.y), ['x', 'y']);
|
||||||
|
if (pts.length <= 1) return pts;
|
||||||
|
const cross = (o, a, b) => (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
|
||||||
|
let lower = [];
|
||||||
|
for (let p of pts) {
|
||||||
|
while (lower.length >= 2 && cross(lower[lower.length - 2], lower[lower.length - 1], p) <= 0) {
|
||||||
|
lower.pop();
|
||||||
|
}
|
||||||
|
lower.push(p);
|
||||||
|
}
|
||||||
|
let upper = [];
|
||||||
|
for (let i = pts.length - 1; i >= 0; i--) {
|
||||||
|
let p = pts[i];
|
||||||
|
while (upper.length >= 2 && cross(upper[upper.length - 2], upper[upper.length - 1], p) <= 0) {
|
||||||
|
upper.pop();
|
||||||
|
}
|
||||||
|
upper.push(p);
|
||||||
|
}
|
||||||
|
lower.pop();
|
||||||
|
upper.pop();
|
||||||
|
return lower.concat(upper);
|
||||||
|
}
|
||||||
|
export default findConvexHull;
|
||||||
|
// Generation time: 60.720s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
async function findLISLength(a) {
|
async function findLISLength(nums) {
|
||||||
if (!a?.length) return 0;
|
if (!nums?.length) return 0;
|
||||||
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
|
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
|
||||||
const t = [];
|
const tails = [];
|
||||||
for (const n of a) {
|
for (const n of nums) {
|
||||||
const i = bisectLeft(t, n);
|
const i = bisectLeft(tails, n);
|
||||||
i < t.length ? t[i] = n : t.push(n);
|
i < tails.length ? tails[i] = n : tails.push(n);
|
||||||
}
|
}
|
||||||
return t.length;
|
return tails.length;
|
||||||
}
|
}
|
||||||
export default findLISLength;
|
export default findLISLength;
|
||||||
|
// Generation time: 3.101s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
const findLISLength = async (arr) => {
|
async function findLISLength(arr) {
|
||||||
const { bisectLeft } = await import('https://cdn.skypack.dev/d3-array');
|
const { bisectLeft } = await import('https://cdn.skypack.dev/d3-array');
|
||||||
|
|
||||||
if (!arr?.length) return 0;
|
if (!arr?.length) return 0;
|
||||||
@@ -11,5 +11,7 @@ const findLISLength = async (arr) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return tails.length;
|
return tails.length;
|
||||||
};
|
}
|
||||||
export default findLISLength;
|
export default findLISLength;
|
||||||
|
// Generation time: 2.177s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
const findLISLength = async (nums) => {
|
|
||||||
if (!nums?.length) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array/+esm');
|
|
||||||
|
|
||||||
const tails = [];
|
|
||||||
|
|
||||||
nums.forEach((num) => {
|
|
||||||
tails[bisectLeft(tails, num)] = num;
|
|
||||||
});
|
|
||||||
|
|
||||||
return tails.length;
|
|
||||||
};
|
|
||||||
export default findLISLength;
|
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
const findLISLength = async (nums) => {
|
const findLISLength = async nums => {
|
||||||
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
|
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array/+esm')
|
||||||
const tails = [];
|
const tails = []
|
||||||
|
|
||||||
for (const n of nums) {
|
for (const n of nums) {
|
||||||
tails[bisectLeft(tails, n)] = n;
|
tails[bisectLeft(tails, n)] = n
|
||||||
}
|
}
|
||||||
return tails.length;
|
|
||||||
};
|
return tails.length
|
||||||
export default findLISLength;
|
}
|
||||||
|
export default findLISLength;
|
||||||
|
// Generation time: 25.399s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
export async function findLISLength(nums) {
|
export async function findLISLength(a){
|
||||||
if (!Array.isArray(nums) || nums.length === 0) return 0;
|
const{bisectLeft}=await import('https://esm.sh/d3-array');
|
||||||
|
if(!Array.isArray(a))return 0;
|
||||||
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
|
const t=[];
|
||||||
const tails = [];
|
for(const v of a){const i=bisectLeft(t,v);i===t.length?t.push(v):t[i]=v;}
|
||||||
|
return t.length;
|
||||||
for (const num of nums) {
|
|
||||||
const idx = bisectLeft(tails, num);
|
|
||||||
idx === tails.length ? tails.push(num) : tails[idx] = num;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tails.length;
|
|
||||||
}
|
}
|
||||||
export default findLISLength;
|
export default findLISLength;
|
||||||
|
// Generation time: 39.477s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
async function findLISLength(a) {
|
async function findLISLength(a){
|
||||||
const {bisectLeft} = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm')
|
const{bisectLeft}=await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm')
|
||||||
const t=[]
|
const t=[]
|
||||||
for (const x of a||[]) {
|
for(const x of a){
|
||||||
const i = bisectLeft(t,x)
|
const i=bisectLeft(t,x)
|
||||||
t[i]=x
|
t[i]=x
|
||||||
}
|
}
|
||||||
return t.length
|
return t.length
|
||||||
}
|
}
|
||||||
export default findLISLength;
|
export default findLISLength;
|
||||||
|
// Generation time: 6.704s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
const findLISLength = async (nums) => {
|
|
||||||
if (!nums.length) return 0
|
|
||||||
|
|
||||||
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm')
|
|
||||||
const tails = []
|
|
||||||
|
|
||||||
for (const num of nums) {
|
|
||||||
const i = bisectLeft(tails, num)
|
|
||||||
tails[i] = num
|
|
||||||
}
|
|
||||||
|
|
||||||
return tails.length
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
async function findLISLength(a){const{bisectLeft}=await import('https://cdn.skypack.dev/d3-array');let t=[];for(let n of a){let i=bisectLeft(t,n);i===t.length?t.push(n):t[i]=n}return t.length}
|
|
||||||
export default findLISLength;
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
async function findLISLength(arr) {
|
|
||||||
const {bisectLeft} = await import('https://cdn.jsdelivr.net/npm/d3-array@3/+esm');
|
|
||||||
let tails = [];
|
|
||||||
for (let num of arr) {
|
|
||||||
let i = bisectLeft(tails, num);
|
|
||||||
if (i === tails.length) tails.push(num);
|
|
||||||
else tails[i] = num;
|
|
||||||
}
|
|
||||||
return tails.length;
|
|
||||||
}
|
|
||||||
export default findLISLength;
|
|
||||||
16
tests/3_lis/outputs/x-ai_grok-4.js
Normal file
16
tests/3_lis/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
async function findLISLength(arr) {
|
||||||
|
const { bisectLeft } = await import('https://cdn.jsdelivr.net/npm/d3-array@3');
|
||||||
|
let tails = [];
|
||||||
|
for (let num of arr) {
|
||||||
|
let pos = bisectLeft(tails, num);
|
||||||
|
if (pos === tails.length) {
|
||||||
|
tails.push(num);
|
||||||
|
} else {
|
||||||
|
tails[pos] = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tails.length;
|
||||||
|
}
|
||||||
|
export default findLISLength;
|
||||||
|
// Generation time: 47.415s
|
||||||
|
// Result: FAIL
|
||||||
@@ -2,4 +2,6 @@ async function renderTemplate(template, data) {
|
|||||||
const { default: Handlebars } = await import('https://esm.sh/handlebars');
|
const { default: Handlebars } = await import('https://esm.sh/handlebars');
|
||||||
return Handlebars.compile(template)(data);
|
return Handlebars.compile(template)(data);
|
||||||
}
|
}
|
||||||
export default renderTemplate;
|
export default renderTemplate;
|
||||||
|
// Generation time: 2.930s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
async function renderTemplate(templateString, data) {
|
async function renderTemplate(template, data) {
|
||||||
const { default: Handlebars } = await import(
|
const { default: Handlebars } = await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js');
|
||||||
'https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js'
|
return Handlebars.compile(template)(data);
|
||||||
);
|
|
||||||
|
|
||||||
const template = Handlebars.compile(templateString);
|
|
||||||
return template(data);
|
|
||||||
}
|
}
|
||||||
export default renderTemplate;
|
export default renderTemplate;
|
||||||
|
// Generation time: 2.224s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
const renderTemplate = async (templateString, data) => {
|
|
||||||
const { default: Handlebars } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.min.js');
|
|
||||||
return Handlebars.compile(templateString)(data);
|
|
||||||
};
|
|
||||||
export default renderTemplate;
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
const renderTemplate = async (tmpl, data) => {
|
const renderTemplate = async (t, d) =>
|
||||||
const { default: H } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/+esm')
|
(await import('https://esm.sh/handlebars'))
|
||||||
return H.compile(tmpl)(data)
|
.default.compile(t)(d)
|
||||||
}
|
export default renderTemplate;
|
||||||
export default renderTemplate;
|
// Generation time: 29.656s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
let h, c = new Map();
|
let hb;
|
||||||
const renderTemplate = async (t, d) => {
|
export const renderTemplate=async(t,d)=>{
|
||||||
h ||= (await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js')).default;
|
try{
|
||||||
c.has(t) || c.set(t, h.compile(t));
|
hb??=(await import('https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.mjs')).default;
|
||||||
return c.get(t)(d);
|
return hb.compile(t)(d);
|
||||||
|
}catch(e){
|
||||||
|
throw new Error(`Render failed: ${e.message}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
export default renderTemplate;
|
export default renderTemplate;
|
||||||
|
// Generation time: 50.722s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
async function renderTemplate(t,d){
|
async function renderTemplate(tpl, data) {
|
||||||
const {default:h}=await import('https://cdn.jsdelivr.net/npm/handlebars@latest/+esm')
|
const { default: h } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.esm.js')
|
||||||
return h.compile(t)(d)
|
return h.compile(tpl)(data)
|
||||||
}
|
}
|
||||||
export default renderTemplate;
|
export default renderTemplate;
|
||||||
|
// Generation time: 2.868s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
const renderTemplate = async (template, data) => {
|
|
||||||
const { default: Handlebars } = await import('https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.min.js')
|
|
||||||
const compiled = Handlebars.compile(template)
|
|
||||||
return compiled(data)
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
const getHandlebars=(async()=>(await import('https://esm.sh/handlebars@4.7.8')).default)();
|
|
||||||
|
|
||||||
async function renderTemplate(template,data){
|
|
||||||
const Handlebars=await getHandlebars;
|
|
||||||
const fn=Handlebars.compile(template);
|
|
||||||
return fn(data);
|
|
||||||
}
|
|
||||||
export default renderTemplate;
|
|
||||||
8
tests/4_transpiler/outputs/x-ai_grok-4.js
Normal file
8
tests/4_transpiler/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
async function renderTemplate(template, data) {
|
||||||
|
const { default: Handlebars } = await import('https://esm.sh/handlebars');
|
||||||
|
const compiled = Handlebars.compile(template);
|
||||||
|
return compiled(data);
|
||||||
|
}
|
||||||
|
export default renderTemplate;
|
||||||
|
// Generation time: 22.419s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
async function parseMarkdown(t) {
|
async function parseMarkdown(md) {
|
||||||
const { marked } = await import("https://esm.sh/marked@12.0.0");
|
const { marked } = await import('https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js');
|
||||||
return marked.parse(t);
|
return marked.parse(md);
|
||||||
}
|
}
|
||||||
export default parseMarkdown;
|
export default parseMarkdown;
|
||||||
|
// Generation time: 2.905s
|
||||||
|
// Result: PASS
|
||||||
@@ -2,4 +2,6 @@ async function parseMarkdown(md) {
|
|||||||
const { marked } = await import('https://cdn.jsdelivr.net/npm/marked@11.1.1/+esm');
|
const { marked } = await import('https://cdn.jsdelivr.net/npm/marked@11.1.1/+esm');
|
||||||
return marked.parse(md);
|
return marked.parse(md);
|
||||||
}
|
}
|
||||||
export default parseMarkdown;
|
export default parseMarkdown;
|
||||||
|
// Generation time: 1.766s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
const parseMarkdown = async (md) => {
|
|
||||||
try {
|
|
||||||
const [
|
|
||||||
{ marked },
|
|
||||||
{ default: DOMPurify }
|
|
||||||
] = await Promise.all([
|
|
||||||
import('https://cdn.jsdelivr.net/npm/marked@13.0.0/lib/marked.esm.js'),
|
|
||||||
import('https://cdn.jsdelivr.net/npm/dompurify@3.1.5/dist/purify.es.mjs')
|
|
||||||
]);
|
|
||||||
|
|
||||||
const rawHtml = marked.parse(md || '', {
|
|
||||||
gfm: true,
|
|
||||||
breaks: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return DOMPurify.sanitize(rawHtml);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Failed to parse markdown:', err);
|
|
||||||
const el = document.createElement('div');
|
|
||||||
el.textContent = md || '';
|
|
||||||
return el.innerHTML;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default parseMarkdown;
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
const parseMarkdown = async text => {
|
const parseMarkdown = async (md) => {
|
||||||
const { parse } = await import('https://esm.sh/marked')
|
const { parse } = await import('https://esm.sh/marked@12.0.0')
|
||||||
return parse(text)
|
return parse(String(md || ''))
|
||||||
}
|
}
|
||||||
export default parseMarkdown;
|
export default parseMarkdown;
|
||||||
|
// Generation time: 42.618s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
async function parseMarkdown(md) {
|
let p;
|
||||||
if (!md?.trim()) return '';
|
|
||||||
try {
|
export const parseMarkdown = async (s) => {
|
||||||
const [{ marked }, { default: DOMPurify }] = await Promise.all([
|
p ||= Promise.all([
|
||||||
import('https://esm.sh/marked@9'),
|
import('https://esm.sh/marked@7.0.4').then(r => r.marked),
|
||||||
import('https://esm.sh/dompurify@3')
|
import('https://esm.sh/dompurify@3.0.5').then(r => r.default)
|
||||||
]);
|
]);
|
||||||
marked.setOptions({ gfm: true, breaks: true });
|
const [m, d] = await p;
|
||||||
return DOMPurify.sanitize(marked.parse(md));
|
return d.sanitize(m.parse(s));
|
||||||
} catch (e) {
|
};
|
||||||
console.error('Markdown parse error:', e);
|
export default parseMarkdown;
|
||||||
return '';
|
// Generation time: 550.549s
|
||||||
}
|
// Result: PASS
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
@@ -1,12 +1,17 @@
|
|||||||
const parseMarkdown=(()=>{
|
const loadLibs=(()=>{let cache;return async()=>cache||(cache=Promise.all([
|
||||||
let m,r
|
import('https://cdn.jsdelivr.net/npm/marked@11.1.0/lib/marked.esm.js'),
|
||||||
return async t=>{
|
import('https://cdn.jsdelivr.net/npm/dompurify@3.0.6/dist/purify.es.mjs')
|
||||||
if(!r){
|
]).then(([{marked},purifyMod])=>{
|
||||||
({marked:m}=await import('https://cdn.jsdelivr.net/npm/marked@11.1.1/+esm'))
|
const purify=(purifyMod.default||purifyMod)(window);
|
||||||
m.setOptions({gfm:1,mangle:0,headerIds:0})
|
marked.setOptions({gfm:true,headerIds:true,mangle:false});
|
||||||
r=1
|
return {marked,purify};
|
||||||
}
|
}));})();
|
||||||
return m.parse(t)
|
|
||||||
}
|
const parseMarkdown=async input=>{
|
||||||
})()
|
const {marked,purify}=await loadLibs();
|
||||||
export default parseMarkdown;
|
const html=marked.parse(typeof input==='string'?input:`${input??''}`);
|
||||||
|
return purify.sanitize(html,{USE_PROFILES:{html:true}});
|
||||||
|
};
|
||||||
|
export default parseMarkdown;
|
||||||
|
// Generation time: 15.618s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
const parseMarkdown = async (markdown) => {
|
|
||||||
const { default: marked } = await import('https://cdn.jsdelivr.net/npm/marked@4.0.12/lib/marked.esm.js')
|
|
||||||
const { default: DOMPurify } = await import('https://cdn.jsdelivr.net/npm/dompurify@3.0.5/dist/purify.es.mjs')
|
|
||||||
|
|
||||||
marked.setOptions({
|
|
||||||
gfm: true,
|
|
||||||
breaks: true,
|
|
||||||
headerIds: false,
|
|
||||||
mangle: false
|
|
||||||
})
|
|
||||||
|
|
||||||
const html = marked.parse(markdown)
|
|
||||||
return DOMPurify.sanitize(html)
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
async function parseMarkdown(md){
|
|
||||||
const{marked}=await import('https://esm.sh/marked');
|
|
||||||
const{DOMPurify}=await import('https://esm.sh/dompurify');
|
|
||||||
return DOMPurify.sanitize(marked.parse(md));
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
async function parseMarkdown(md) {
|
|
||||||
const { marked } = await import('https://cdn.skypack.dev/marked');
|
|
||||||
return marked.parse(md);
|
|
||||||
}
|
|
||||||
export default parseMarkdown;
|
|
||||||
7
tests/5_markdown_parser/outputs/x-ai_grok-4.js
Normal file
7
tests/5_markdown_parser/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
async function parseMarkdown(markdown) {
|
||||||
|
const { marked } = await import('https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js');
|
||||||
|
return marked(markdown);
|
||||||
|
}
|
||||||
|
export default parseMarkdown;
|
||||||
|
// Generation time: 16.386s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,32 +1,24 @@
|
|||||||
async function processCSV(csv, config) {
|
async function processCSV(csv, config) {
|
||||||
|
const { parse } = await import('https://cdn.jsdelivr.net/npm/papaparse@5/+esm');
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
|
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
|
||||||
|
|
||||||
const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/papaparse@5/+esm');
|
const { data } = parse(csv, { header: true, skipEmptyLines: true });
|
||||||
|
|
||||||
const { data } = Papa.parse(csv, { header: true, skipEmptyLines: true });
|
|
||||||
|
|
||||||
const filtered = data.filter(row => row[filterColumn] == filterValue);
|
const filtered = data.filter(row => row[filterColumn] == filterValue);
|
||||||
|
|
||||||
const groups = {};
|
const groups = {};
|
||||||
for (const row of filtered) {
|
for (const row of filtered) {
|
||||||
const key = row[groupBy];
|
const key = row[groupBy];
|
||||||
(groups[key] ??= []).push(row);
|
(groups[key] ??= []).push(+row[aggregateColumn] || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const toNum = v => {
|
return Object.entries(groups).map(([key, vals]) => ({
|
||||||
const n = Number(v);
|
[groupBy]: key,
|
||||||
return isNaN(n) ? 0 : n;
|
result: operation === 'count' ? vals.length :
|
||||||
};
|
operation === 'sum' ? vals.reduce((a, b) => a + b, 0) :
|
||||||
|
vals.reduce((a, b) => a + b, 0) / vals.length
|
||||||
const ops = {
|
|
||||||
sum: rows => rows.reduce((s, r) => s + toNum(r[aggregateColumn]), 0),
|
|
||||||
avg: rows => rows.length ? ops.sum(rows) / rows.length : 0,
|
|
||||||
count: rows => rows.length
|
|
||||||
};
|
|
||||||
|
|
||||||
return Object.entries(groups).map(([k, v]) => ({
|
|
||||||
[groupBy]: k,
|
|
||||||
result: ops[operation](v)
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
export default processCSV;
|
export default processCSV;
|
||||||
|
// Generation time: 4.406s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
const processCSV = async (csv, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => {
|
async function processCSV(csv, config) {
|
||||||
const [{ default: Papa }] = await Promise.all([
|
const { parse } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm');
|
||||||
import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm')
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { data } = Papa.parse(csv, { header: true, skipEmptyLines: true });
|
|
||||||
|
|
||||||
const filtered = data.filter(row => row[filterColumn] == filterValue);
|
const { data } = parse(csv, { header: true, skipEmptyLines: true });
|
||||||
|
|
||||||
|
const filtered = data.filter(row => row[config.filterColumn] == config.filterValue);
|
||||||
|
|
||||||
const groups = filtered.reduce((acc, row) => {
|
const groups = filtered.reduce((acc, row) => {
|
||||||
const key = row[groupBy];
|
const key = row[config.groupBy];
|
||||||
if (!acc[key]) acc[key] = [];
|
(acc[key] ??= []).push(row);
|
||||||
acc[key].push(row);
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return Object.entries(groups).map(([key, rows]) => {
|
return Object.entries(groups).map(([key, rows]) => {
|
||||||
const values = rows.map(r => Number(r[aggregateColumn]) || 0);
|
const values = rows.map(r => Number(r[config.aggregateColumn]) || 0);
|
||||||
const sum = values.reduce((a, b) => a + b, 0);
|
const sum = values.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[groupBy]: key,
|
[config.groupBy]: key,
|
||||||
result: operation === 'sum' ? sum : operation === 'avg' ? sum / values.length : values.length
|
result: config.operation === 'sum' ? sum :
|
||||||
|
config.operation === 'avg' ? sum / values.length :
|
||||||
|
values.length
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
export default processCSV;
|
export default processCSV;
|
||||||
|
// Generation time: 4.238s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
async function processCSV(csvString, config) {
|
|
||||||
const {
|
|
||||||
filterColumn: fc,
|
|
||||||
filterValue: fv,
|
|
||||||
groupBy: gb,
|
|
||||||
aggregateColumn: ac,
|
|
||||||
operation: op
|
|
||||||
} = config;
|
|
||||||
|
|
||||||
const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.3.2/papaparse.min.js');
|
|
||||||
|
|
||||||
const { data } = Papa.parse(csvString, {
|
|
||||||
header: true,
|
|
||||||
skipEmptyLines: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const groups = data.reduce((acc, row) => {
|
|
||||||
if (row[fc] == fv) {
|
|
||||||
const key = row[gb];
|
|
||||||
const val = Number(row[ac]) || 0;
|
|
||||||
|
|
||||||
acc[key] = acc[key] || { sum: 0, count: 0 };
|
|
||||||
acc[key].sum += val;
|
|
||||||
acc[key].count++;
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
return Object.entries(groups).map(([key, { sum, count }]) => ({
|
|
||||||
[gb]: key,
|
|
||||||
result: op === 'avg' ? sum / count : op === 'sum' ? sum : count,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
@@ -1,19 +1,16 @@
|
|||||||
export const processCSV = async (csvString, { filterColumn, filterValue, groupBy, aggregateColumn, operation }) => {
|
const processCSV = async (str, { filterColumn: fc, filterValue: fv, groupBy: gb, aggregateColumn: ac, operation: op }) => {
|
||||||
const [{ csvParse }, { rollup, sum, mean }] = await Promise.all([
|
const { csvParse, rollups, sum } = await import('https://esm.sh/d3@7');
|
||||||
import('https://esm.sh/d3-dsv'),
|
const num = v => +v || 0;
|
||||||
import('https://esm.sh/d3-array')
|
return rollups(
|
||||||
]);
|
csvParse(str).filter(d => d[fc] == fv),
|
||||||
|
g => {
|
||||||
const getValue = d => +(d[aggregateColumn]) || 0;
|
if (op === 'count') return g.length;
|
||||||
|
const t = sum(g, d => num(d[ac]));
|
||||||
const grouped = rollup(
|
return op === 'sum' ? t : t / g.length;
|
||||||
csvParse(csvString).filter(row => row[filterColumn] == filterValue),
|
},
|
||||||
group => operation === 'count'
|
d => d[gb]
|
||||||
? group.length
|
).map(([k, v]) => ({ [gb]: k, result: v }));
|
||||||
: (operation === 'sum' ? sum : mean)(group, getValue),
|
|
||||||
row => row[groupBy]
|
|
||||||
);
|
|
||||||
|
|
||||||
return Array.from(grouped, ([key, result]) => ({ [groupBy]: key, result }));
|
|
||||||
};
|
};
|
||||||
export default processCSV;
|
export default processCSV;
|
||||||
|
// Generation time: 40.784s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,2 +1,17 @@
|
|||||||
async function processCSV(csv,{filterColumn:f,filterValue:v,groupBy:g,aggregateColumn:a,operation:o}){const{default:P}=await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm');const{data}=P.parse(csv,{header:true});const grouped=data.filter(r=>r[f]==v).reduce((c,r)=>{const k=r[g],n=Number(r[a])||0;c[k]||=(c[k]={s:0,c:0});c[k].s+=n;c[k].c++;return c},{});return Object.entries(grouped).map(([k,{s,c}])=>({[g]:k,result:o=='sum'?s:o=='avg'?s/c:c}))}
|
async function processCSV(csv, { filterColumn: fc, filterValue: fv, groupBy: gb, aggregateColumn: ac, operation: op }) {
|
||||||
export default processCSV;
|
const { default: Papa } = await import('https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm');
|
||||||
|
const groups = {};
|
||||||
|
|
||||||
|
Papa.parse(csv, { header: true }).data
|
||||||
|
.filter(r => r[fc] == fv)
|
||||||
|
.forEach(r => {
|
||||||
|
const key = r[gb], g = groups[key] || (groups[key] = { c: 0, s: 0 });
|
||||||
|
g.c++;
|
||||||
|
g.s += +r[ac] || 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.entries(groups).map(([k, { c, s }]) => ({ [gb]: k, result: op === 'count' ? c : op === 'avg' ? s / c : s }));
|
||||||
|
}
|
||||||
|
export default processCSV;
|
||||||
|
// Generation time: 66.769s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,21 +1,16 @@
|
|||||||
const libCache={},load=u=>libCache[u]??=import(u);
|
const store={},load=u=>store[u]??=import(u),csvLib='https://cdn.jsdelivr.net/npm/papaparse@5.4.1/+esm',dataLib='https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm',toNum=v=>{const n=Number(v);return Number.isFinite(n)?n:0};
|
||||||
|
|
||||||
async function processCSV(csv,cfg){
|
async function processCSV(csv,opt){
|
||||||
const [{csvParse},{groupBy}]=await Promise.all([
|
const [{Papa},{groupBy:gb}] = await Promise.all([load(csvLib),load(dataLib)]);
|
||||||
load('https://cdn.jsdelivr.net/npm/d3-dsv@3.0.1/+esm'),
|
const {filterColumn:f,filterValue:v,groupBy:g,aggregateColumn:a,operation:o}=opt;
|
||||||
load('https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm')
|
const rows=Papa.parse(csv,{header:true,skipEmptyLines:true}).data.filter(r=>r&&r[f]==v);
|
||||||
]);
|
const grouped=gb(rows,r=>r[g]);
|
||||||
const {filterColumn:f,filterValue:v,groupBy:k,aggregateColumn:a,operation:o}=cfg;
|
return Object.entries(grouped).map(([k,items])=>{
|
||||||
const rows=csvParse(csv).filter(r=>r[f]==v);
|
const total=items.reduce((s,r)=>s+toNum(r[a]),0);
|
||||||
const grouped=groupBy(rows,r=>r[k]);
|
const result=o==='count'?items.length:o==='sum'?total:items.length?total/items.length:0;
|
||||||
return Object.entries(grouped).map(([g,list])=>{
|
return {[g]:k,result};
|
||||||
const nums=list.map(r=>{
|
|
||||||
const n=+r[a];
|
|
||||||
return Number.isFinite(n)?n:0;
|
|
||||||
});
|
|
||||||
const sum=nums.reduce((s,n)=>s+n,0);
|
|
||||||
const result=o==='count'?list.length:o==='sum'?sum:list.length?sum/list.length:0;
|
|
||||||
return {[k]:g,result};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export default processCSV;
|
export default processCSV;
|
||||||
|
// Generation time: 29.916s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
const processCSV = async (csvData, config) => {
|
|
||||||
const { parse } = await import('https://cdn.skypack.dev/papaparse@5.3.0')
|
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config
|
|
||||||
const { data } = parse(csvData, { header: true })
|
|
||||||
|
|
||||||
const filtered = data.filter(row => row[filterColumn] == filterValue)
|
|
||||||
const groups = filtered.reduce((acc, row) => {
|
|
||||||
const key = row[groupBy]
|
|
||||||
if (!acc[key]) acc[key] = []
|
|
||||||
acc[key].push(row)
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
return Object.entries(groups).map(([groupValue, rows]) => {
|
|
||||||
const numbers = rows.map(row => +row[aggregateColumn] || 0)
|
|
||||||
let result
|
|
||||||
|
|
||||||
if (operation === 'sum') result = numbers.reduce((a, b) => a + b, 0)
|
|
||||||
if (operation === 'avg') result = numbers.reduce((a, b) => a + b, 0) / numbers.length
|
|
||||||
if (operation === 'count') result = numbers.length
|
|
||||||
|
|
||||||
return { [groupBy]: groupValue, result }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
async function processCSV(csv,config){
|
|
||||||
const Papa=(await import('https://cdn.skypack.dev/papaparse')).default;
|
|
||||||
const parsed=Papa.parse(csv,{header:!0}).data;
|
|
||||||
const{filterColumn:fc,filterValue:fv,groupBy:gb,aggregateColumn:ac,operation:op}=config;
|
|
||||||
const filtered=parsed.filter(r=>r[fc]==fv);
|
|
||||||
const groups=new Map;
|
|
||||||
for(const r of filtered){
|
|
||||||
const gv=r[gb];
|
|
||||||
const v=Number(r[ac])||0;
|
|
||||||
const g=groups.get(gv)||{sum:0,count:0};
|
|
||||||
g.sum+=v;
|
|
||||||
g.count++;
|
|
||||||
groups.set(gv,g);
|
|
||||||
}
|
|
||||||
return Array.from(groups,(g,gv)=>(({[gb]:gv,result:op==='sum'?g.sum:op==='count'?g.count:g.sum/g.count})));
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
async function processCSV(csv, config) {
|
|
||||||
const [{ default: Papa }, { aq, sum, mean, count }] = await Promise.all([
|
|
||||||
import('https://cdn.skypack.dev/papaparse'),
|
|
||||||
import('https://cdn.skypack.dev/arquero')
|
|
||||||
]);
|
|
||||||
const data = Papa.parse(csv, { header: true, skipEmptyLines: true }).data;
|
|
||||||
const { filterColumn, filterValue, groupBy, aggregateColumn, operation } = config;
|
|
||||||
let table = aq.from(data).filter(d => d[filterColumn] == filterValue);
|
|
||||||
if (operation !== 'count') {
|
|
||||||
table = table.derive({ [aggregateColumn]: d => Number(d[aggregateColumn]) || 0 });
|
|
||||||
}
|
|
||||||
const makeAgg = operation === 'count' ? count() : { sum: sum, avg: mean }[operation](aggregateColumn);
|
|
||||||
return table.groupby(groupBy).rollup({ result: makeAgg }).objects();
|
|
||||||
}
|
|
||||||
export default processCSV;
|
|
||||||
20
tests/6_csv_processor/outputs/x-ai_grok-4.js
Normal file
20
tests/6_csv_processor/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
async function processCSV(csvString, config) {
|
||||||
|
const d3 = await import('https://unpkg.com/d3?module');
|
||||||
|
const data = d3.csvParse(csvString);
|
||||||
|
const filtered = data.filter(row => row[config.filterColumn] == config.filterValue);
|
||||||
|
const grouped = d3.group(filtered, d => d[config.groupBy]);
|
||||||
|
return [...grouped].map(([key, group]) => {
|
||||||
|
const col = config.aggregateColumn;
|
||||||
|
const vals = group.map(r => Number(r[col]) || 0);
|
||||||
|
let result;
|
||||||
|
switch (config.operation) {
|
||||||
|
case 'sum': result = vals.reduce((a, b) => a + b, 0); break;
|
||||||
|
case 'avg': result = vals.reduce((a, b) => a + b, 0) / vals.length; break;
|
||||||
|
case 'count': result = group.length; break;
|
||||||
|
}
|
||||||
|
return { [config.groupBy]: key, result };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export default processCSV;
|
||||||
|
// Generation time: 34.010s
|
||||||
|
// Result: PASS
|
||||||
@@ -7,71 +7,70 @@ async function findAvailableSlots(calendar1, calendar2, constraints) {
|
|||||||
const [whStartH, whStartM] = workHours.start.split(':').map(Number);
|
const [whStartH, whStartM] = workHours.start.split(':').map(Number);
|
||||||
const [whEndH, whEndM] = workHours.end.split(':').map(Number);
|
const [whEndH, whEndM] = workHours.end.split(':').map(Number);
|
||||||
|
|
||||||
const busyIntervals = [...calendar1, ...calendar2]
|
const allBusy = [...calendar1, ...calendar2]
|
||||||
.map(b => Interval.fromDateTimes(
|
.map(b => ({
|
||||||
DateTime.fromISO(b.start, { zone: 'utc' }),
|
start: DateTime.fromISO(b.start, { zone: 'utc' }),
|
||||||
DateTime.fromISO(b.end, { zone: 'utc' })
|
end: DateTime.fromISO(b.end, { zone: 'utc' })
|
||||||
))
|
}))
|
||||||
.filter(i => i.isValid)
|
.filter(b => b.end > rangeStart && b.start < rangeEnd)
|
||||||
.sort((a, b) => a.start - b.start);
|
.sort((a, b) => a.start - b.start);
|
||||||
|
|
||||||
const merged = [];
|
const merged = [];
|
||||||
for (const interval of busyIntervals) {
|
for (const b of allBusy) {
|
||||||
if (!merged.length || merged[merged.length - 1].end < interval.start) {
|
if (!merged.length || b.start > merged[merged.length - 1].end) {
|
||||||
merged.push(interval);
|
merged.push({ start: b.start, end: b.end });
|
||||||
} else {
|
} else {
|
||||||
const last = merged.pop();
|
merged[merged.length - 1].end = DateTime.max(merged[merged.length - 1].end, b.end);
|
||||||
merged.push(Interval.fromDateTimes(
|
|
||||||
last.start,
|
|
||||||
last.end > interval.end ? last.end : interval.end
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const freeIntervals = [];
|
const free = [];
|
||||||
let cursor = rangeStart;
|
let cursor = rangeStart;
|
||||||
for (const busy of merged) {
|
for (const b of merged) {
|
||||||
if (busy.start > cursor && busy.start <= rangeEnd) {
|
if (b.start > cursor) {
|
||||||
freeIntervals.push(Interval.fromDateTimes(cursor, busy.start < rangeEnd ? busy.start : rangeEnd));
|
free.push({ start: cursor, end: b.start });
|
||||||
}
|
}
|
||||||
cursor = busy.end > cursor ? busy.end : cursor;
|
cursor = DateTime.max(cursor, b.end);
|
||||||
}
|
}
|
||||||
if (cursor < rangeEnd) {
|
if (cursor < rangeEnd) {
|
||||||
freeIntervals.push(Interval.fromDateTimes(cursor, rangeEnd));
|
free.push({ start: cursor, end: rangeEnd });
|
||||||
}
|
}
|
||||||
|
|
||||||
const getWorkInterval = day => {
|
const getWorkWindow = (day) => {
|
||||||
const start = day.set({ hour: whStartH, minute: whStartM, second: 0, millisecond: 0 });
|
const ws = day.set({ hour: whStartH, minute: whStartM, second: 0, millisecond: 0 });
|
||||||
const end = day.set({ hour: whEndH, minute: whEndM, second: 0, millisecond: 0 });
|
const we = day.set({ hour: whEndH, minute: whEndM, second: 0, millisecond: 0 });
|
||||||
return start < end ? Interval.fromDateTimes(start, end) : null;
|
return { start: ws, end: we };
|
||||||
};
|
};
|
||||||
|
|
||||||
const slots = [];
|
const slots = [];
|
||||||
|
|
||||||
for (const free of freeIntervals) {
|
for (const f of free) {
|
||||||
let day = free.start.startOf('day');
|
let day = f.start.startOf('day');
|
||||||
const endDay = free.end.startOf('day');
|
const lastDay = f.end.startOf('day');
|
||||||
|
|
||||||
while (day <= endDay) {
|
while (day <= lastDay) {
|
||||||
const workInt = getWorkInterval(day);
|
const ww = getWorkWindow(day);
|
||||||
if (workInt) {
|
const effStart = DateTime.max(f.start, ww.start, rangeStart);
|
||||||
const intersection = free.intersection(workInt);
|
const effEnd = DateTime.min(f.end, ww.end, rangeEnd);
|
||||||
if (intersection && intersection.length('minutes') >= durationMinutes) {
|
|
||||||
let slotStart = intersection.start;
|
if (effStart < effEnd) {
|
||||||
while (slotStart.plus({ minutes: durationMinutes }) <= intersection.end) {
|
let slotStart = effStart;
|
||||||
const slotEnd = slotStart.plus({ minutes: durationMinutes });
|
while (true) {
|
||||||
slots.push({
|
const slotEnd = slotStart.plus({ minutes: durationMinutes });
|
||||||
start: slotStart.toISO({ suppressMilliseconds: true }),
|
if (slotEnd > effEnd) break;
|
||||||
end: slotEnd.toISO({ suppressMilliseconds: true })
|
slots.push({
|
||||||
});
|
start: slotStart.toISO(),
|
||||||
slotStart = slotEnd;
|
end: slotEnd.toISO()
|
||||||
}
|
});
|
||||||
|
slotStart = slotEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
day = day.plus({ days: 1 });
|
day = day.plus({ days: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return slots.sort((a, b) => a.start.localeCompare(b.start));
|
return slots;
|
||||||
}
|
}
|
||||||
export default findAvailableSlots;
|
export default findAvailableSlots;
|
||||||
|
// Generation time: 12.726s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,69 +1,103 @@
|
|||||||
const findAvailableSlots = async (calendar1, calendar2, constraints) => {
|
const findAvailableSlots = async (calendar1, calendar2, constraints) => {
|
||||||
const { startOfDay, addMinutes, parseISO, formatISO } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.0.0/+esm');
|
const { parseISO, addMinutes, isWithinInterval, isBefore, isAfter, isEqual } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.0.0/+esm');
|
||||||
|
|
||||||
const { durationMinutes, searchRange, workHours } = constraints;
|
const { durationMinutes, searchRange, workHours } = constraints;
|
||||||
const searchStart = parseISO(searchRange.start);
|
const searchStart = parseISO(searchRange.start);
|
||||||
const searchEnd = parseISO(searchRange.end);
|
const searchEnd = parseISO(searchRange.end);
|
||||||
|
|
||||||
const [workStartHour, workStartMin] = workHours.start.split(':').map(Number);
|
const parseTime = (timeStr) => {
|
||||||
const [workEndHour, workEndMin] = workHours.end.split(':').map(Number);
|
const [h, m] = timeStr.split(':').map(Number);
|
||||||
const workStartMs = (workStartHour * 60 + workStartMin) * 60000;
|
return h * 60 + m;
|
||||||
const workEndMs = (workEndHour * 60 + workEndMin) * 60000;
|
};
|
||||||
|
|
||||||
|
const workStartMinutes = parseTime(workHours.start);
|
||||||
|
const workEndMinutes = parseTime(workHours.end);
|
||||||
|
|
||||||
|
const getUTCMinutes = (date) => date.getUTCHours() * 60 + date.getUTCMinutes();
|
||||||
|
|
||||||
|
const isInWorkHours = (date) => {
|
||||||
|
const minutes = getUTCMinutes(date);
|
||||||
|
return minutes >= workStartMinutes && minutes < workEndMinutes;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setUTCTime = (date, minutes) => {
|
||||||
|
const d = new Date(date);
|
||||||
|
d.setUTCHours(Math.floor(minutes / 60), minutes % 60, 0, 0);
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
const allBusy = [...calendar1, ...calendar2]
|
const allBusy = [...calendar1, ...calendar2]
|
||||||
.map(({ start, end }) => ({ start: parseISO(start), end: parseISO(end) }))
|
.map(slot => ({ start: parseISO(slot.start), end: parseISO(slot.end) }))
|
||||||
.sort((a, b) => a.start - b.start);
|
.sort((a, b) => a.start - b.start);
|
||||||
|
|
||||||
const merged = [];
|
const merged = [];
|
||||||
for (const slot of allBusy) {
|
for (const slot of allBusy) {
|
||||||
if (merged.length && slot.start <= merged[merged.length - 1].end) {
|
if (merged.length === 0) {
|
||||||
merged[merged.length - 1].end = new Date(Math.max(merged[merged.length - 1].end, slot.end));
|
merged.push({ ...slot });
|
||||||
} else {
|
} else {
|
||||||
merged.push({ start: slot.start, end: slot.end });
|
const last = merged[merged.length - 1];
|
||||||
|
if (isBefore(slot.start, last.end) || isEqual(slot.start, last.end)) {
|
||||||
|
last.end = isAfter(slot.end, last.end) ? slot.end : last.end;
|
||||||
|
} else {
|
||||||
|
merged.push({ ...slot });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const free = [];
|
const freePeriods = [];
|
||||||
let current = searchStart;
|
let currentStart = searchStart;
|
||||||
|
|
||||||
for (const busy of merged) {
|
for (const busy of merged) {
|
||||||
if (current < busy.start) {
|
if (isBefore(currentStart, busy.start)) {
|
||||||
free.push({ start: current, end: busy.start });
|
freePeriods.push({ start: currentStart, end: busy.start });
|
||||||
}
|
}
|
||||||
current = new Date(Math.max(current, busy.end));
|
currentStart = isAfter(busy.end, currentStart) ? busy.end : currentStart;
|
||||||
}
|
}
|
||||||
if (current < searchEnd) {
|
|
||||||
free.push({ start: current, end: searchEnd });
|
if (isBefore(currentStart, searchEnd)) {
|
||||||
|
freePeriods.push({ start: currentStart, end: searchEnd });
|
||||||
}
|
}
|
||||||
|
|
||||||
const slots = [];
|
const slots = [];
|
||||||
for (const period of free) {
|
|
||||||
let slotStart = period.start;
|
for (const period of freePeriods) {
|
||||||
|
let current = new Date(period.start);
|
||||||
|
const periodEnd = period.end;
|
||||||
|
|
||||||
while (slotStart < period.end) {
|
while (isBefore(current, periodEnd)) {
|
||||||
const dayStart = startOfDay(slotStart);
|
const currentDay = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate()));
|
||||||
const slotStartMs = slotStart - dayStart;
|
const workStart = setUTCTime(currentDay, workStartMinutes);
|
||||||
const slotEnd = addMinutes(slotStart, durationMinutes);
|
const workEnd = setUTCTime(currentDay, workEndMinutes);
|
||||||
const slotEndMs = slotEnd - dayStart;
|
|
||||||
|
|
||||||
if (slotEnd > period.end) break;
|
let slotStart = isAfter(current, workStart) ? current : workStart;
|
||||||
|
|
||||||
const endsNextDay = slotEnd - startOfDay(slotEnd) < slotEndMs % 86400000;
|
if (!isBefore(slotStart, workEnd) || !isBefore(slotStart, periodEnd)) {
|
||||||
|
const nextDay = new Date(currentDay);
|
||||||
if (!endsNextDay &&
|
nextDay.setUTCDate(nextDay.getUTCDate() + 1);
|
||||||
slotStartMs >= workStartMs &&
|
current = nextDay;
|
||||||
slotEndMs <= workEndMs &&
|
continue;
|
||||||
slotStart >= searchStart &&
|
|
||||||
slotEnd <= searchEnd) {
|
|
||||||
slots.push({
|
|
||||||
start: formatISO(slotStart),
|
|
||||||
end: formatISO(slotEnd)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
slotStart = slotEnd;
|
const slotEnd = addMinutes(slotStart, durationMinutes);
|
||||||
|
|
||||||
|
if ((isInWorkHours(slotStart) && isInWorkHours(new Date(slotEnd.getTime() - 1))) &&
|
||||||
|
(isBefore(slotEnd, periodEnd) || isEqual(slotEnd, periodEnd)) &&
|
||||||
|
(isBefore(slotEnd, workEnd) || isEqual(slotEnd, workEnd))) {
|
||||||
|
slots.push({
|
||||||
|
start: slotStart.toISOString(),
|
||||||
|
end: slotEnd.toISOString()
|
||||||
|
});
|
||||||
|
current = slotEnd;
|
||||||
|
} else {
|
||||||
|
const nextDay = new Date(currentDay);
|
||||||
|
nextDay.setUTCDate(nextDay.getUTCDate() + 1);
|
||||||
|
current = nextDay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return slots;
|
return slots;
|
||||||
};
|
};
|
||||||
export default findAvailableSlots;
|
export default findAvailableSlots;
|
||||||
|
// Generation time: 14.710s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
async function findAvailableSlots(calendar1, calendar2, constraints) {
|
|
||||||
const {
|
|
||||||
parseISO, addMinutes, addDays, max, isBefore, isAfter, startOfDay,
|
|
||||||
} = await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/esm/index.js');
|
|
||||||
|
|
||||||
const { durationMinutes, searchRange, workHours } = constraints;
|
|
||||||
const searchStart = parseISO(searchRange.start);
|
|
||||||
const searchEnd = parseISO(searchRange.end);
|
|
||||||
const [workStartH, workStartM] = workHours.start.split(':').map(Number);
|
|
||||||
const [workEndH, workEndM] = workHours.end.split(':').map(Number);
|
|
||||||
|
|
||||||
const busySlots = [...calendar1, ...calendar2]
|
|
||||||
.map(slot => ({ start: parseISO(slot.start), end: parseISO(slot.end) }))
|
|
||||||
.sort((a, b) => a.start - b.start);
|
|
||||||
|
|
||||||
const mergedBusy = busySlots.reduce((acc, current) => {
|
|
||||||
const last = acc.at(-1);
|
|
||||||
if (last && isBefore(current.start, last.end)) {
|
|
||||||
last.end = max([last.end, current.end]);
|
|
||||||
} else {
|
|
||||||
acc.push({ ...current });
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const freeIntervals = [];
|
|
||||||
let cursor = searchStart;
|
|
||||||
|
|
||||||
mergedBusy.forEach(busy => {
|
|
||||||
if (isBefore(cursor, busy.start)) {
|
|
||||||
freeIntervals.push({ start: cursor, end: busy.start });
|
|
||||||
}
|
|
||||||
cursor = max([cursor, busy.end]);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isBefore(cursor, searchEnd)) {
|
|
||||||
freeIntervals.push({ start: cursor, end: searchEnd });
|
|
||||||
}
|
|
||||||
|
|
||||||
const availableSlots = freeIntervals.flatMap(gap => {
|
|
||||||
const slotsInGap = [];
|
|
||||||
let slotCursor = gap.start;
|
|
||||||
|
|
||||||
while (isBefore(slotCursor, gap.end)) {
|
|
||||||
const day = startOfDay(slotCursor);
|
|
||||||
const workDayStart = new Date(day);
|
|
||||||
workDayStart.setUTCHours(workStartH, workStartM, 0, 0);
|
|
||||||
|
|
||||||
const workDayEnd = new Date(day);
|
|
||||||
workDayEnd.setUTCHours(workEndH, workEndM, 0, 0);
|
|
||||||
|
|
||||||
const slotStart = max([slotCursor, workDayStart]);
|
|
||||||
const slotEnd = addMinutes(slotStart, durationMinutes);
|
|
||||||
|
|
||||||
const canFit = !isAfter(slotEnd, workDayEnd) && !isAfter(slotEnd, gap.end);
|
|
||||||
|
|
||||||
if (canFit) {
|
|
||||||
slotsInGap.push({ start: slotStart, end: slotEnd });
|
|
||||||
slotCursor = slotEnd;
|
|
||||||
} else {
|
|
||||||
const nextDayStart = addDays(day, 1);
|
|
||||||
nextDayStart.setUTCHours(workStartH, workStartM, 0, 0);
|
|
||||||
slotCursor = nextDayStart;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return slotsInGap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return availableSlots.map(slot => ({
|
|
||||||
start: slot.start.toISOString(),
|
|
||||||
end: slot.end.toISOString(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
@@ -1,52 +1,65 @@
|
|||||||
const findAvailableSlots = async (cal1, cal2, { durationMinutes: dur, searchRange: range, workHours: work }) => {
|
const findAvailableSlots = async (calA, calB, { durationMinutes, searchRange, workHours }) => {
|
||||||
const { parseISO } = await import('https://cdn.jsdelivr.net/npm/date-fns@3.6.0/+esm');
|
const { addMinutes, parseISO, formatISO } = await import('https://esm.sh/date-fns@2.30.0');
|
||||||
|
|
||||||
|
const getMins = (t) => { const [h, m] = t.split(':'); return (+h * 60) + +m; };
|
||||||
|
const [workStart, workEnd] = [workHours.start, workHours.end].map(getMins);
|
||||||
|
const rangeEnd = parseISO(searchRange.end).getTime();
|
||||||
|
|
||||||
|
const busy = [...calA, ...calB]
|
||||||
|
.map(s => ({ s: parseISO(s.start).getTime(), e: parseISO(s.end).getTime() }))
|
||||||
|
.sort((a, b) => a.s - b.s)
|
||||||
|
.reduce((acc, c) => {
|
||||||
|
const last = acc[acc.length - 1];
|
||||||
|
if (last && c.s <= last.e) last.e = Math.max(last.e, c.e);
|
||||||
|
else acc.push(c);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
let current = parseISO(searchRange.start).getTime();
|
||||||
|
const slots = [];
|
||||||
|
|
||||||
|
while (current + durationMinutes * 60000 <= rangeEnd) {
|
||||||
|
const d = new Date(current);
|
||||||
|
const curMins = d.getUTCHours() * 60 + d.getUTCMinutes();
|
||||||
|
|
||||||
|
if (curMins >= workEnd) {
|
||||||
|
d.setUTCDate(d.getUTCDate() + 1);
|
||||||
|
d.setUTCHours(0, 0, 0, 0);
|
||||||
|
current = addMinutes(d, workStart).getTime();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curMins < workStart) {
|
||||||
|
d.setUTCHours(0, 0, 0, 0);
|
||||||
|
current = addMinutes(d, workStart).getTime();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const end = addMinutes(current, durationMinutes).getTime();
|
||||||
|
const endD = new Date(end);
|
||||||
|
const endMins = endD.getUTCHours() * 60 + endD.getUTCMinutes();
|
||||||
|
|
||||||
|
if (end > rangeEnd) break;
|
||||||
|
|
||||||
|
if (endD.getUTCDate() !== d.getUTCDate() || endMins > workEnd) {
|
||||||
|
d.setUTCDate(d.getUTCDate() + 1);
|
||||||
|
d.setUTCHours(0, 0, 0, 0);
|
||||||
|
current = addMinutes(d, workStart).getTime();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const conflict = busy.find(b => current < b.e && end > b.s);
|
||||||
|
|
||||||
const toMs = (d) => parseISO(d).getTime();
|
if (conflict) {
|
||||||
const [wsH, wsM] = work.start.split(':').map(Number);
|
current = conflict.e;
|
||||||
const [weH, weM] = work.end.split(':').map(Number);
|
} else {
|
||||||
const rangeStart = toMs(range.start);
|
slots.push({ start: formatISO(current), end: formatISO(end) });
|
||||||
const rangeEnd = toMs(range.end);
|
current = end;
|
||||||
const durMs = dur * 60000;
|
|
||||||
|
|
||||||
const busy = [...cal1, ...cal2]
|
|
||||||
.map(x => ({ s: toMs(x.start), e: toMs(x.end) }))
|
|
||||||
.sort((a, b) => a.s - b.s);
|
|
||||||
|
|
||||||
const merged = [];
|
|
||||||
for (const b of busy) {
|
|
||||||
const last = merged[merged.length - 1];
|
|
||||||
if (last && b.s < last.e) last.e = Math.max(last.e, b.e);
|
|
||||||
else merged.push(b);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const slots = [];
|
return slots;
|
||||||
let currDate = parseISO(range.start);
|
|
||||||
currDate.setUTCHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
while (currDate.getTime() < rangeEnd) {
|
|
||||||
const wStart = new Date(currDate).setUTCHours(wsH, wsM, 0, 0);
|
|
||||||
const wEnd = new Date(currDate).setUTCHours(weH, weM, 0, 0);
|
|
||||||
|
|
||||||
let t = Math.max(wStart, rangeStart);
|
|
||||||
const limit = Math.min(wEnd, rangeEnd);
|
|
||||||
|
|
||||||
while (t + durMs <= limit) {
|
|
||||||
const tEnd = t + durMs;
|
|
||||||
const clash = merged.find(b => t < b.e && tEnd > b.s);
|
|
||||||
|
|
||||||
if (clash) {
|
|
||||||
t = clash.e;
|
|
||||||
} else {
|
|
||||||
slots.push({
|
|
||||||
start: new Date(t).toISOString(),
|
|
||||||
end: new Date(tEnd).toISOString()
|
|
||||||
});
|
|
||||||
t += durMs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currDate.setUTCDate(currDate.getUTCDate() + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return slots;
|
|
||||||
};
|
};
|
||||||
export default findAvailableSlots;
|
export default findAvailableSlots;
|
||||||
|
// Generation time: 47.831s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,11 +1,56 @@
|
|||||||
async function findAvailableSlots(a,b,{durationMinutes:d,searchRange:r,workHours:w}){
|
export async function findAvailableSlots(cal1, cal2, { durationMinutes, searchRange, workHours }) {
|
||||||
const{parseISO:p,formatISO:f,addMinutes:m,min:n,max:x,startOfDay:s}=await import('https://esm.sh/date-fns');
|
const { parseISO, compareAsc, addMinutes } = await import('https://cdn.skypack.dev/date-fns');
|
||||||
const busy=[...a,...b].map(({start:S,end:E})=>({s:p(S),e:p(E)})).sort((q,y)=>q.s-y.s).reduce((c,{s:S,e:E})=>{
|
|
||||||
const l=c[c.length-1];if(!l||S>l.e)c.push({s:S,e:E});else l.e=x([l.e,E]);return c;
|
const s = parseISO(searchRange.start);
|
||||||
},[]);
|
const e = parseISO(searchRange.end);
|
||||||
const rs=p(r.start),re=p(r.end),[ws,we]=[w.start,w.end].map(t=>{const[h,m]=t.split(':').map(Number);return h*60+m;});
|
|
||||||
const free=[];let cur=rs;for(const{s:S,e:E}of busy){S>cur&&free.push({s:cur,e:n([S,re])});cur=x([cur,E]);if(cur>=re)break;}
|
const [whS, whE] = [workHours.start, workHours.end].map(t => {
|
||||||
cur<re&&free.push({s:cur,e:re});const slots=[];for(const{s:fs,e:fe}of free){let st=fs;while(m(st,d)<=fe){const en=m(st,d);const minutes=(st-s(st))/6e4;if(minutes>=ws&&minutes+d<=we)slots.push({start:f(st),end:f(en)});st=en;}}
|
const [h, m] = t.split(':').map(Number);
|
||||||
return slots;
|
return h * 60 + m;
|
||||||
|
});
|
||||||
|
|
||||||
|
const inWH = (d, de) => {
|
||||||
|
const g = t => t.getUTCHours() * 60 + t.getUTCMinutes();
|
||||||
|
return g(d) >= whS && g(de) <= whE;
|
||||||
|
};
|
||||||
|
|
||||||
|
const busy = [...cal1, ...cal2]
|
||||||
|
.map(({ start, end }) => ({ s: parseISO(start), e: parseISO(end) }))
|
||||||
|
.filter(({ s: bs, e: be }) => compareAsc(be, s) > 0 && compareAsc(bs, e) < 0)
|
||||||
|
.map(({ s: bs, e: be }) => ({
|
||||||
|
s: compareAsc(bs, s) < 0 ? s : bs,
|
||||||
|
e: compareAsc(be, e) > 0 ? e : be
|
||||||
|
}))
|
||||||
|
.sort((a, b) => compareAsc(a.s, b.s));
|
||||||
|
|
||||||
|
const merged = [];
|
||||||
|
for (const { s: bs, e: be } of busy) {
|
||||||
|
const last = merged[merged.length - 1];
|
||||||
|
if (!last || compareAsc(bs, last.e) >= 0) merged.push({ s: bs, e: be });
|
||||||
|
else if (compareAsc(be, last.e) > 0) last.e = be;
|
||||||
|
}
|
||||||
|
|
||||||
|
const free = [];
|
||||||
|
let cur = s;
|
||||||
|
for (const { s: ms, e: me } of merged) {
|
||||||
|
if (compareAsc(cur, ms) < 0) free.push({ s: cur, e: ms });
|
||||||
|
cur = compareAsc(me, cur) > 0 ? me : cur;
|
||||||
|
}
|
||||||
|
if (compareAsc(cur, e) < 0) free.push({ s: cur, e });
|
||||||
|
|
||||||
|
const slots = [];
|
||||||
|
for (const { s: fs, e: fe } of free) {
|
||||||
|
let cs = fs;
|
||||||
|
while (true) {
|
||||||
|
const ce = addMinutes(cs, durationMinutes);
|
||||||
|
if (compareAsc(ce, fe) > 0) break;
|
||||||
|
if (inWH(cs, ce)) slots.push({ start: cs.toISOString(), end: ce.toISOString() });
|
||||||
|
cs = addMinutes(cs, durationMinutes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return slots;
|
||||||
}
|
}
|
||||||
export default findAvailableSlots;
|
export default findAvailableSlots;
|
||||||
|
// Generation time: 289.823s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,66 +1,93 @@
|
|||||||
const useDayjs=(()=>{
|
const loadDay = (() => {
|
||||||
let p
|
let memo
|
||||||
return()=>p||(p=(async()=>{
|
return () => memo ?? (memo = (async () => {
|
||||||
const [{default:d},{default:u}]=await Promise.all([
|
const [core, utc] = await Promise.all([
|
||||||
import('https://cdn.jsdelivr.net/npm/dayjs@1/esm/index.js'),
|
import('https://esm.sh/dayjs@1.11.13?target=esnext'),
|
||||||
import('https://cdn.jsdelivr.net/npm/dayjs@1/esm/plugin/utc/index.js')
|
import('https://esm.sh/dayjs@1.11.13/plugin/utc?target=esnext')
|
||||||
])
|
])
|
||||||
d.extend(u)
|
const d = core.default
|
||||||
return d
|
d.extend(utc.default)
|
||||||
})())
|
return d
|
||||||
|
})())
|
||||||
})()
|
})()
|
||||||
|
|
||||||
async function findAvailableSlots(c1=[],c2=[],cfg={}){
|
const findAvailableSlots = async (c1 = [], c2 = [], cfg = {}) => {
|
||||||
const d=await useDayjs()
|
const d = await loadDay()
|
||||||
const {durationMinutes:dur,searchRange:r={},workHours:w={}}=cfg
|
const u = v => d.utc(v)
|
||||||
const {start:rs,end:re}=r
|
const {
|
||||||
const {start:ws,end:we}=w
|
durationMinutes: dm,
|
||||||
if(!dur||dur<=0||!rs||!re||!ws||!we)return []
|
searchRange: sr = {},
|
||||||
const s=d.utc(rs),e=d.utc(re)
|
workHours: wh = {}
|
||||||
if(!s.isValid()||!e.isValid()||e.valueOf()<=s.valueOf())return []
|
} = cfg
|
||||||
const rangeStart=s.valueOf(),rangeEnd=e.valueOf(),min=60000
|
const dur = Number(dm)
|
||||||
const clip=v=>{
|
if(!Number.isFinite(dur) || dur <= 0 || !sr.start || !sr.end || !wh.start || !wh.end) return []
|
||||||
if(!v||!v.start||!v.end)return 0
|
const s = u(sr.start)
|
||||||
const a=d.utc(v.start),b=d.utc(v.end)
|
const e = u(sr.end)
|
||||||
if(!a.isValid()||!b.isValid())return 0
|
if(!s.isValid() || !e.isValid() || !s.isBefore(e)) return []
|
||||||
const st=Math.max(rangeStart,a.valueOf()),en=Math.min(rangeEnd,b.valueOf())
|
const toMin = v => {
|
||||||
return en>st?{start:st,end:en}:0
|
const [h, m = 0] = String(v).split(':').map(Number)
|
||||||
}
|
if(!Number.isFinite(h) || !Number.isFinite(m)) return null
|
||||||
const busy=[...c1,...c2].map(clip).filter(Boolean).sort((x,y)=>x.start-y.start)
|
if(h < 0 || h > 24 || m < 0 || m > 59) return null
|
||||||
const merged=[]
|
if(h === 24 && m > 0) return null
|
||||||
for(const slot of busy){
|
return h * 60 + m
|
||||||
const last=merged[merged.length-1]
|
|
||||||
if(!last||slot.start>last.end)merged.push({...slot})
|
|
||||||
else if(slot.end>last.end)last.end=slot.end
|
|
||||||
}
|
|
||||||
const free=[]
|
|
||||||
let cur=rangeStart
|
|
||||||
for(const slot of merged){
|
|
||||||
if(slot.start>cur)free.push({start:cur,end:slot.start})
|
|
||||||
cur=Math.max(cur,slot.end)
|
|
||||||
}
|
|
||||||
if(cur<rangeEnd)free.push({start:cur,end:rangeEnd})
|
|
||||||
const minutes=t=>{const [h,m]=t.split(':').map(Number);return h*60+m}
|
|
||||||
const workStart=minutes(ws),workEnd=minutes(we)
|
|
||||||
if(workStart>=workEnd)return []
|
|
||||||
const out=[]
|
|
||||||
for(const span of free){
|
|
||||||
let day=d.utc(span.start).startOf('day')
|
|
||||||
while(day.valueOf()<span.end){
|
|
||||||
const dayStart=day.add(workStart,'minute'),dayEnd=day.add(workEnd,'minute')
|
|
||||||
const winStart=Math.max(dayStart.valueOf(),span.start),winEnd=Math.min(dayEnd.valueOf(),span.end)
|
|
||||||
if(winEnd-winStart>=dur*min){
|
|
||||||
let slotStart=d.utc(winStart)
|
|
||||||
while(true){
|
|
||||||
const slotEnd=slotStart.add(dur,'minute')
|
|
||||||
if(slotEnd.valueOf()>winEnd)break
|
|
||||||
out.push({start:slotStart.toISOString(),end:slotEnd.toISOString()})
|
|
||||||
slotStart=slotEnd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
day=day.add(1,'day')
|
|
||||||
}
|
}
|
||||||
}
|
const ws = toMin(wh.start)
|
||||||
return out
|
const we = toMin(wh.end)
|
||||||
|
if(ws == null || we == null || ws >= we) return []
|
||||||
|
const list = [
|
||||||
|
...(Array.isArray(c1) ? c1 : []),
|
||||||
|
...(Array.isArray(c2) ? c2 : [])
|
||||||
|
]
|
||||||
|
const busy = list.map(v => {
|
||||||
|
if(!v?.start || !v?.end) return null
|
||||||
|
const st = u(v.start)
|
||||||
|
const en = u(v.end)
|
||||||
|
if(!st.isValid() || !en.isValid() || !st.isBefore(en)) return null
|
||||||
|
if(!en.isAfter(s) || !st.isBefore(e)) return null
|
||||||
|
return {
|
||||||
|
start: st.isBefore(s) ? s : st,
|
||||||
|
end: en.isAfter(e) ? e : en
|
||||||
|
}
|
||||||
|
}).filter(Boolean).sort((a, b) => a.start.valueOf() - b.start.valueOf())
|
||||||
|
const merged = []
|
||||||
|
for(const slot of busy){
|
||||||
|
if(!merged.length){
|
||||||
|
merged.push({...slot})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const last = merged[merged.length - 1]
|
||||||
|
if(slot.start.isAfter(last.end)) merged.push({...slot})
|
||||||
|
else if(slot.end.isAfter(last.end)) last.end = slot.end
|
||||||
|
}
|
||||||
|
const free = []
|
||||||
|
let cur = s
|
||||||
|
for(const slot of merged){
|
||||||
|
if(slot.start.isAfter(cur)) free.push({start: cur, end: slot.start})
|
||||||
|
if(slot.end.isAfter(cur)) cur = slot.end
|
||||||
|
}
|
||||||
|
if(cur.isBefore(e)) free.push({start: cur, end: e})
|
||||||
|
if(!free.length) return []
|
||||||
|
const step = dur * 60000
|
||||||
|
if(!Number.isFinite(step) || step <= 0) return []
|
||||||
|
const out = []
|
||||||
|
for(const seg of free){
|
||||||
|
for(let day = seg.start.startOf('day'); day.isBefore(seg.end); day = day.add(1, 'day')){
|
||||||
|
const wsStart = day.add(ws, 'minute')
|
||||||
|
const wsEnd = day.add(we, 'minute')
|
||||||
|
const start = wsStart.isAfter(seg.start) ? wsStart : seg.start
|
||||||
|
const end = wsEnd.isBefore(seg.end) ? wsEnd : seg.end
|
||||||
|
if(!start.isBefore(end)) continue
|
||||||
|
const limit = end.valueOf()
|
||||||
|
for(let t = start.valueOf(); t + step <= limit; t += step){
|
||||||
|
out.push({
|
||||||
|
start: d.utc(t).toISOString(),
|
||||||
|
end: d.utc(t + step).toISOString()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
export default findAvailableSlots;
|
export default findAvailableSlots;
|
||||||
|
// Generation time: 211.798s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const findAvailableSlots = async (calendar1, calendar2, constraints) => {
|
|
||||||
const { DateTime, Interval } = await import('https://cdn.skypack.dev/luxon@3.0.1')
|
|
||||||
|
|
||||||
const { durationMinutes, searchRange, workHours } = constraints
|
|
||||||
const workStart = DateTime.fromISO(`${searchRange.start.split('T')[0]}T${workHours.start}:00Z`)
|
|
||||||
const workEnd = DateTime.fromISO(`${searchRange.start.split('T')[0]}T${workHours.end}:00Z`)
|
|
||||||
const searchStart = DateTime.fromISO(searchRange.start)
|
|
||||||
const searchEnd = DateTime.fromISO(searchRange.end)
|
|
||||||
|
|
||||||
const mergeCalendars = (cal1, cal2) => {
|
|
||||||
const allSlots = [...cal1, ...cal2].map(slot => ({
|
|
||||||
start: DateTime.fromISO(slot.start),
|
|
||||||
end: DateTime.fromISO(slot.end)
|
|
||||||
})).sort((a, b) => a.start - b.start)
|
|
||||||
|
|
||||||
return allSlots.reduce((merged, current) => {
|
|
||||||
if (merged.length === 0) return [current]
|
|
||||||
|
|
||||||
const last = merged[merged.length - 1]
|
|
||||||
if (current.start <= last.end) {
|
|
||||||
last.end = current.end > last.end ? current.end : last.end
|
|
||||||
return merged
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...merged, current]
|
|
||||||
}, [])
|
|
||||||
}
|
|
||||||
|
|
||||||
const mergedBusy = mergeCalendars(calendar1, calendar2)
|
|
||||||
const freeIntervals = []
|
|
||||||
|
|
||||||
let currentStart = searchStart
|
|
||||||
for (const busy of mergedBusy) {
|
|
||||||
if (busy.start > currentStart) {
|
|
||||||
freeIntervals.push(Interval.fromDateTimes(currentStart, busy.start))
|
|
||||||
}
|
|
||||||
currentStart = busy.end > currentStart ? busy.end : currentStart
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentStart < searchEnd) {
|
|
||||||
freeIntervals.push(Interval.fromDateTimes(currentStart, searchEnd))
|
|
||||||
}
|
|
||||||
|
|
||||||
const availableSlots = freeIntervals.flatMap(interval => {
|
|
||||||
const slots = []
|
|
||||||
let slotStart = interval.start
|
|
||||||
|
|
||||||
while (slotStart.plus({ minutes: durationMinutes }) <= interval.end) {
|
|
||||||
const slotEnd = slotStart.plus({ minutes: durationMinutes })
|
|
||||||
const slotInterval = Interval.fromDateTimes(slotStart, slotEnd)
|
|
||||||
|
|
||||||
if (slotInterval.engulfs(workStart) && slotInterval.engulfs(workEnd)) {
|
|
||||||
slots.push({
|
|
||||||
start: slotStart.toISO(),
|
|
||||||
end: slotEnd.toISO()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
slotStart = slotEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
return slots
|
|
||||||
})
|
|
||||||
|
|
||||||
return availableSlots.filter(slot => {
|
|
||||||
const slotStart = DateTime.fromISO(slot.start)
|
|
||||||
const slotEnd = DateTime.fromISO(slot.end)
|
|
||||||
return slotStart >= workStart && slotEnd <= workEnd
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
async function findAvailableSlots(cal1, cal2, {durationMinutes:dm, searchRange, workHours}) {
|
|
||||||
const {DateTime:DT, Interval, Duration} = await import('https://cdn.skypack.dev/luxon');
|
|
||||||
const dur=Duration.fromObject({minutes:dm});
|
|
||||||
const srS=DT.fromISO(searchRange.start).toUTC();
|
|
||||||
const srE=DT.fromISO(searchRange.end).toUTC();
|
|
||||||
const srI=Interval.fromDateTimes(srS,srE);
|
|
||||||
let busies=[...cal1,...cal2].map(s=>{
|
|
||||||
const a=DT.fromISO(s.start).toUTC(),b=DT.fromISO(s.end).toUTC();
|
|
||||||
return a<b?Interval.fromDateTimes(a,b).intersection(srI):null;
|
|
||||||
}).filter(Boolean);
|
|
||||||
const [ws,we]=[workHours.start,workHours.end];
|
|
||||||
const hms=+ws.slice(0,2),mms=+ws.slice(3,5),hme=+we.slice(0,2),mme=+we.slice(3,5);
|
|
||||||
let cur=srS.startOf('day');
|
|
||||||
while(cur<srE){
|
|
||||||
const dayE=cur.plus({days:1});
|
|
||||||
const dayI=Interval.fromDateTimes(cur,dayE).intersection(srI);
|
|
||||||
if(dayI.isEmpty) {cur=cur.plus({days:1});continue;}
|
|
||||||
const wsT=cur.set({hour:hms,minute:mms,second:0,millisecond:0});
|
|
||||||
const weT=cur.set({hour:hme,minute:mme,second:0,millisecond:0});
|
|
||||||
const workI=Interval.fromDateTimes(wsT,weT).intersection(dayI);
|
|
||||||
if(!workI?.isValid||workI.isEmpty){
|
|
||||||
busies.push(dayI);
|
|
||||||
}else{
|
|
||||||
if(dayI.start<workI.start)busies.push(Interval.fromDateTimes(dayI.start,workI.start));
|
|
||||||
if(workI.end<dayI.end)busies.push(Interval.fromDateTimes(workI.end,dayI.end));
|
|
||||||
}
|
|
||||||
cur=cur.plus({days:1});
|
|
||||||
}
|
|
||||||
busies.sort((a,b)=>a.start.toMillis()-b.start.toMillis());
|
|
||||||
const merged=[];
|
|
||||||
for(let iv of busies){
|
|
||||||
if(!iv?.isValid||iv.isEmpty)continue;
|
|
||||||
if(merged.length===0||merged.at(-1).end<iv.start){
|
|
||||||
merged.push(iv);
|
|
||||||
}else{
|
|
||||||
const last=merged[merged.length-1];
|
|
||||||
merged[merged.length-1]=Interval.fromDateTimes(last.start,iv.end>last.end?iv.end:last.end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const frees=[];
|
|
||||||
let prev=srS;
|
|
||||||
for(let b of merged){
|
|
||||||
if(prev<b.start)frees.push(Interval.fromDateTimes(prev,b.start));
|
|
||||||
prev=b.end>prev?b.end:prev;
|
|
||||||
}
|
|
||||||
if(prev<srE)frees.push(Interval.fromDateTimes(prev,srE));
|
|
||||||
const slots=[];
|
|
||||||
for(let f of frees){
|
|
||||||
let c=f.start;
|
|
||||||
while(c.plus(dur)<=f.end){
|
|
||||||
slots.push({start:c.toISO(),end:c.plus(dur).toISO()});
|
|
||||||
c=c.plus(dur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return slots;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
async function findAvailableSlots(cal1, cal2, constraints) {
|
|
||||||
const { DateTime, Interval } = await import('https://esm.sh/luxon@3');
|
|
||||||
const busySlots = [...cal1, ...cal2].map(slot => {
|
|
||||||
const s = DateTime.fromISO(slot.start, { zone: 'utc' });
|
|
||||||
const e = DateTime.fromISO(slot.end, { zone: 'utc' });
|
|
||||||
return s.isValid && e.isValid && s < e ? Interval.fromDateTimes(s, e) : null;
|
|
||||||
}).filter(Boolean);
|
|
||||||
const mergedBusies = Interval.union(busySlots);
|
|
||||||
const rangeStart = DateTime.fromISO(constraints.searchRange.start, { zone: 'utc' });
|
|
||||||
const rangeEnd = DateTime.fromISO(constraints.searchRange.end, { zone: 'utc' });
|
|
||||||
const searchInt = Interval.fromDateTimes(rangeStart, rangeEnd);
|
|
||||||
let covered = mergedBusies
|
|
||||||
.filter(b => searchInt.overlaps(b))
|
|
||||||
.map(b => searchInt.intersection(b))
|
|
||||||
.filter(i => i.isValid);
|
|
||||||
covered.sort((a, b) => a.start.toMillis() - b.start.toMillis());
|
|
||||||
const frees = [];
|
|
||||||
let current = rangeStart;
|
|
||||||
for (const busy of covered) {
|
|
||||||
if (current < busy.start) {
|
|
||||||
frees.push(Interval.fromDateTimes(current, busy.start));
|
|
||||||
}
|
|
||||||
current = DateTime.max(current, busy.end);
|
|
||||||
}
|
|
||||||
if (current < rangeEnd) {
|
|
||||||
frees.push(Interval.fromDateTimes(current, rangeEnd));
|
|
||||||
}
|
|
||||||
const [wsH, wsM] = constraints.workHours.start.split(':').map(Number);
|
|
||||||
const [weH, weM] = constraints.workHours.end.split(':').map(Number);
|
|
||||||
const durMin = constraints.durationMinutes;
|
|
||||||
let workInts = [];
|
|
||||||
let curDay = rangeStart.startOf('day');
|
|
||||||
const endDayStart = rangeEnd.startOf('day');
|
|
||||||
while (curDay <= endDayStart) {
|
|
||||||
const dayWorkS = curDay.set({ hour: wsH, minute: wsM });
|
|
||||||
const dayWorkE = curDay.set({ hour: weH, minute: weM });
|
|
||||||
if (dayWorkS < dayWorkE) {
|
|
||||||
workInts.push(Interval.fromDateTimes(dayWorkS, dayWorkE));
|
|
||||||
}
|
|
||||||
curDay = curDay.plus({ days: 1 });
|
|
||||||
}
|
|
||||||
const allowables = [];
|
|
||||||
for (const free of frees) {
|
|
||||||
for (const work of workInts) {
|
|
||||||
const inter = free.intersection(work);
|
|
||||||
if (inter.isValid) allowables.push(inter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const mergedAllows = Interval.union(allowables);
|
|
||||||
const availableSlots = [];
|
|
||||||
for (const allow of mergedAllows) {
|
|
||||||
let slotStart = allow.start;
|
|
||||||
while (allow.contains(slotStart.plus({ minutes: durMin }))) {
|
|
||||||
const slotEnd = slotStart.plus({ minutes: durMin });
|
|
||||||
availableSlots.push({
|
|
||||||
start: slotStart.toISO(),
|
|
||||||
end: slotEnd.toISO()
|
|
||||||
});
|
|
||||||
slotStart = slotEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return availableSlots;
|
|
||||||
}
|
|
||||||
export default findAvailableSlots;
|
|
||||||
48
tests/7_scheduler/outputs/x-ai_grok-4.js
Normal file
48
tests/7_scheduler/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
async function findAvailableSlots(c1, c2, con) {
|
||||||
|
const {DateTime, Interval} = await import('https://cdn.jsdelivr.net/npm/luxon@3.4.4/+esm');
|
||||||
|
const st = DateTime.fromISO(con.searchRange.start, {zone:'utc'});
|
||||||
|
const ed = DateTime.fromISO(con.searchRange.end, {zone:'utc'});
|
||||||
|
const sr = Interval.fromDateTimes(st, ed);
|
||||||
|
let bs = [...c1, ...c2].map(({start, end}) => Interval.fromDateTimes(
|
||||||
|
DateTime.fromISO(start, {zone:'utc'}),
|
||||||
|
DateTime.fromISO(end, {zone:'utc'})
|
||||||
|
));
|
||||||
|
let cur = st.startOf('day');
|
||||||
|
const [wh, wm] = con.workHours.start.split(':').map(Number);
|
||||||
|
const [eh, em] = con.workHours.end.split(':').map(Number);
|
||||||
|
while (cur <= ed) {
|
||||||
|
const ws = cur.set({hour: wh, minute: wm});
|
||||||
|
const we = cur.set({hour: eh, minute: em});
|
||||||
|
if (cur < ws) bs.push(Interval.fromDateTimes(cur, ws));
|
||||||
|
const eod = cur.endOf('day');
|
||||||
|
if (we < eod) bs.push(Interval.fromDateTimes(we, eod));
|
||||||
|
cur = cur.plus({days:1}).startOf('day');
|
||||||
|
}
|
||||||
|
let mb = Interval.merge(bs).sort((a,b) => a.start.toMillis() - b.start.toMillis());
|
||||||
|
let rb = mb.filter(i => i.overlaps(sr));
|
||||||
|
let free = [];
|
||||||
|
if (rb.length === 0) {
|
||||||
|
free.push(sr);
|
||||||
|
} else {
|
||||||
|
if (sr.start < rb[0].start) free.push(Interval.fromDateTimes(sr.start, rb[0].start));
|
||||||
|
for (let i = 0; i < rb.length - 1; i++) {
|
||||||
|
free.push(Interval.fromDateTimes(rb[i].end, rb[i + 1].start));
|
||||||
|
}
|
||||||
|
if (rb[rb.length - 1].end < sr.end) free.push(Interval.fromDateTimes(rb[rb.length - 1].end, sr.end));
|
||||||
|
}
|
||||||
|
const dur = con.durationMinutes;
|
||||||
|
let av = [];
|
||||||
|
for (let f of free) {
|
||||||
|
let cs = f.start;
|
||||||
|
while (true) {
|
||||||
|
let ce = cs.plus({minutes: dur});
|
||||||
|
if (ce > f.end) break;
|
||||||
|
av.push({start: cs.toISO(), end: ce.toISO()});
|
||||||
|
cs = ce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return av;
|
||||||
|
}
|
||||||
|
export default findAvailableSlots;
|
||||||
|
// Generation time: 201.779s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,18 +1,43 @@
|
|||||||
async function validateJSON(jsonObject, jsonSchema) {
|
async function validateJSON(jsonObject, jsonSchema) {
|
||||||
const { default: Ajv } = await import("https://esm.sh/ajv@8");
|
try {
|
||||||
const { default: addFormats } = await import("https://esm.sh/ajv-formats@3");
|
const Ajv = (await import('https://cdn.jsdelivr.net/npm/ajv@8/dist/ajv.min.js')).default
|
||||||
|
|| (await import('https://esm.sh/ajv@8')).default;
|
||||||
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
||||||
addFormats(ajv);
|
const ajv = new Ajv({ allErrors: true, verbose: true });
|
||||||
|
const validate = ajv.compile(jsonSchema);
|
||||||
const validate = ajv.compile(jsonSchema);
|
const valid = validate(jsonObject);
|
||||||
const valid = validate(jsonObject);
|
|
||||||
|
return {
|
||||||
return {
|
valid,
|
||||||
valid,
|
errors: valid ? [] : validate.errors.map(e =>
|
||||||
errors: valid ? [] : validate.errors.map(e =>
|
e.instancePath
|
||||||
e.instancePath ? `${e.instancePath} ${e.message}` : e.message
|
? `${e.instancePath} ${e.message}`
|
||||||
)
|
: e.message
|
||||||
};
|
)
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
const { default: Ajv } = await import('https://esm.sh/ajv@8');
|
||||||
|
const ajv = new Ajv({ allErrors: true, verbose: true });
|
||||||
|
const validate = ajv.compile(jsonSchema);
|
||||||
|
const valid = validate(jsonObject);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid,
|
||||||
|
errors: valid ? [] : validate.errors.map(e =>
|
||||||
|
e.instancePath
|
||||||
|
? `${e.instancePath} ${e.message}`
|
||||||
|
: e.message
|
||||||
|
)
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
errors: [`Schema validation failed: ${err.message}`]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export default validateJSON;
|
export default validateJSON;
|
||||||
|
// Generation time: 5.496s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,11 +1,18 @@
|
|||||||
const validateJSON = async (data, schema) => {
|
const validateJSON = async (data, schema) => {
|
||||||
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8/dist/2020.min.js');
|
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/dist/2020.min.js');
|
||||||
const ajv = new Ajv({ allErrors: true, strict: false });
|
const ajv = new Ajv({ allErrors: true, verbose: true });
|
||||||
const validate = ajv.compile(schema);
|
const validate = ajv.compile(schema);
|
||||||
const valid = validate(data);
|
const valid = validate(data);
|
||||||
return {
|
return {
|
||||||
valid,
|
valid,
|
||||||
errors: valid ? [] : validate.errors.map(e => `${e.instancePath || '/'} ${e.message}`)
|
errors: valid ? [] : validate.errors.map(e => ({
|
||||||
|
path: e.instancePath || '/',
|
||||||
|
message: e.message,
|
||||||
|
keyword: e.keyword,
|
||||||
|
params: e.params
|
||||||
|
}))
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
export default validateJSON;
|
export default validateJSON;
|
||||||
|
// Generation time: 3.111s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
const validateJSON = async (json, schema) => {
|
|
||||||
let ajv;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.17.1/+esm');
|
|
||||||
ajv = new Ajv({ allErrors: true });
|
|
||||||
} catch (e) {
|
|
||||||
return { valid: false, errors: ["Failed to load validator: " + e.message] };
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const validate = ajv.compile(schema);
|
|
||||||
const valid = validate(json);
|
|
||||||
|
|
||||||
const errors = validate.errors?.map(
|
|
||||||
e => `${e.instancePath || 'root'} ${e.message}`.trim()
|
|
||||||
) ?? [];
|
|
||||||
|
|
||||||
return { valid, errors };
|
|
||||||
} catch (e) {
|
|
||||||
return { valid: false, errors: ["Invalid schema: " + e.message] };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
export default validateJSON;
|
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
const validateJSON = async (d, s) => {
|
const validateJSON = async (data, schema) => {
|
||||||
const { default: A } = await import('https://esm.sh/ajv@8.17.1')
|
const { default: Ajv } = await import('https://esm.sh/ajv@8.17.1');
|
||||||
const v = new A({ allErrors: true }).compile(s)
|
const validate = new Ajv({ allErrors: true }).compile(schema);
|
||||||
const r = v(d)
|
const valid = validate(data);
|
||||||
return {
|
return { valid, errors: valid ? [] : validate.errors.map(e => `${e.instancePath} ${e.message}`.trim()) };
|
||||||
valid: r,
|
};
|
||||||
errors: r ? [] : v.errors.map(e => `${e.instancePath} ${e.message}`.trim())
|
export default validateJSON;
|
||||||
}
|
// Generation time: 20.754s
|
||||||
}
|
// Result: PASS
|
||||||
export default validateJSON;
|
|
||||||
@@ -1,12 +1,24 @@
|
|||||||
let Ajv;
|
let a, c;
|
||||||
async function validateJSON(json, schema) {
|
|
||||||
if(!(json&&typeof json==='object')||!(schema===true||schema===false||(schema&&typeof schema==='object')))
|
export const validateJSON = async (d, s) => {
|
||||||
return{valid:false,errors:['Invalid input']};
|
try {
|
||||||
try{
|
if (!a) {
|
||||||
if(!Ajv){const m=await import('https://esm.sh/ajv@8');Ajv=m.default}
|
const { default: Ajv } = await import('https://esm.sh/ajv?bundle');
|
||||||
const ajv=new Ajv({allErrors:true}),v=ajv.compile(schema);
|
a = new Ajv({ allErrors: true });
|
||||||
const valid=v(json);
|
c = new Map();
|
||||||
return{valid,errors:valid?[]:v.errors.map(e=>`${e.instancePath||'root'} ${e.message}`)};
|
}
|
||||||
}catch(e){return{valid:false,errors:[e.message]}}
|
const k = JSON.stringify(s);
|
||||||
}
|
if (!c.has(k)) c.set(k, a.compile(s));
|
||||||
export default validateJSON;
|
const v = c.get(k);
|
||||||
|
const valid = v(d);
|
||||||
|
return {
|
||||||
|
valid,
|
||||||
|
errors: valid ? [] : v.errors.map(e => `${e.instancePath || 'root'} ${e.message}`)
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return { valid: false, errors: [e.message] };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export default validateJSON;
|
||||||
|
// Generation time: 19.566s
|
||||||
|
// Result: PASS
|
||||||
@@ -1,2 +1,21 @@
|
|||||||
const validateJSON=(()=>{let a;return async(j,s)=>{a??=(async()=>{const{default:Ajv}=await import('https://esm.run/ajv@8');return new Ajv({allErrors:1});})();const v=await a,c=v.compile(s),valid=c(j);return{valid,errors:valid?[]:(c.errors||[]).map(e=>`${e.instancePath||'/'} ${e.message}`)}}})();
|
const loadAjv = (() => {
|
||||||
export default validateJSON;
|
let ajv
|
||||||
|
return async () => {
|
||||||
|
if (!ajv) {
|
||||||
|
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/dist/ajv.js')
|
||||||
|
ajv = new Ajv({ allErrors: true, strict: false })
|
||||||
|
}
|
||||||
|
return ajv
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
export const validateJSON = async (data, schema) => {
|
||||||
|
const ajv = await loadAjv()
|
||||||
|
const validate = ajv.compile(schema)
|
||||||
|
const valid = validate(data)
|
||||||
|
const errors = valid ? [] : validate.errors.map(e => `${e.instancePath || '/'} ${e.message}`)
|
||||||
|
return { valid, errors }
|
||||||
|
}
|
||||||
|
export default validateJSON;
|
||||||
|
// Generation time: 6.678s
|
||||||
|
// Result: FAIL
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
const validateJSON = async (json, schema) => {
|
|
||||||
try {
|
|
||||||
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8.12.0/+esm')
|
|
||||||
const { default: addFormats } = await import('https://cdn.jsdelivr.net/npm/ajv-formats@2.1.1/+esm')
|
|
||||||
|
|
||||||
const ajv = new Ajv({
|
|
||||||
allErrors: true,
|
|
||||||
strict: false,
|
|
||||||
validateSchema: true
|
|
||||||
})
|
|
||||||
|
|
||||||
addFormats(ajv)
|
|
||||||
|
|
||||||
const validate = ajv.compile(schema)
|
|
||||||
const valid = validate(json)
|
|
||||||
|
|
||||||
return {
|
|
||||||
valid,
|
|
||||||
errors: valid ? [] : validate.errors.map(err => ({
|
|
||||||
message: err.message,
|
|
||||||
instancePath: err.instancePath,
|
|
||||||
schemaPath: err.schemaPath,
|
|
||||||
params: err.params
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
valid: false,
|
|
||||||
errors: [{
|
|
||||||
message: error.message,
|
|
||||||
stack: error.stack
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
let ajvInstance;
|
|
||||||
|
|
||||||
async function validateJSON(data, schema) {
|
|
||||||
if (!ajvInstance) {
|
|
||||||
const { default: Ajv } = await import('https://cdn.skypack.dev/ajv@8');
|
|
||||||
ajvInstance = new Ajv({ allErrors: true });
|
|
||||||
}
|
|
||||||
const ajv = ajvInstance;
|
|
||||||
try {
|
|
||||||
const validate = ajv.compile(schema);
|
|
||||||
const valid = validate(data);
|
|
||||||
const errors = valid ? [] : ajv.errorsText(validate.errors, { separator: '\n' })
|
|
||||||
.split('\n')
|
|
||||||
.map(s => s.trim())
|
|
||||||
.filter(Boolean);
|
|
||||||
return { valid, errors };
|
|
||||||
} catch (e) {
|
|
||||||
return { valid: false, errors: [`Schema error: ${e.message}`] };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
async function validateJSON(data,schema){
|
|
||||||
const{default:Ajv}=await import('https://esm.sh/ajv@7.13.4');
|
|
||||||
const ajv=new Ajv({allErrors:true});
|
|
||||||
const validate=ajv.compile(schema);
|
|
||||||
const valid=validate(data);
|
|
||||||
if(valid)return{valid:true,errors:[]};
|
|
||||||
const errors=validate.errors.map(e=>`${e.instancePath||''} ${e.message||'Validation error'}`.trim()).filter(Boolean);
|
|
||||||
return{valid:false,errors};
|
|
||||||
}
|
|
||||||
export default validateJSON;
|
|
||||||
13
tests/8_json_validator/outputs/x-ai_grok-4.js
Normal file
13
tests/8_json_validator/outputs/x-ai_grok-4.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
async function validateJSON(data, schema) {
|
||||||
|
const { default: Ajv } = await import('https://cdn.jsdelivr.net/npm/ajv@8/dist/ajv.min.js');
|
||||||
|
const ajv = new Ajv({ allErrors: true });
|
||||||
|
const validate = ajv.compile(schema);
|
||||||
|
const valid = validate(data);
|
||||||
|
return {
|
||||||
|
valid,
|
||||||
|
errors: valid ? [] : validate.errors.map(e => e.message)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export default validateJSON;
|
||||||
|
// Generation time: 16.498s
|
||||||
|
// Result: FAIL
|
||||||
@@ -25,4 +25,6 @@ async function createStreamVisualizer(asyncIterable, options) {
|
|||||||
|
|
||||||
return { data, path };
|
return { data, path };
|
||||||
}
|
}
|
||||||
export default createStreamVisualizer;
|
export default createStreamVisualizer;
|
||||||
|
// Generation time: 5.230s
|
||||||
|
// Result: PASS
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user