Défi · chaînes difficile JavaScript ·
Brace expansion
Expand braces the way a shell does and return all the resulting strings in order. s has lowercase letters, "{", "}" and ",".
- Braces are matched like brackets, left to right: each "}" closes the nearest unclosed "{". A "}" with nothing to close and a "{" that is never closed are ordinary characters. - A matched pair with at least one comma directly inside it (not inside a nested pair) is a group: the commas split it into alternatives, each expanded on its own, and the group stands for all their results in order. "{a,b{c,d}}" gives "a", "bc", "bd". Alternatives can be empty: "x{,y}" gives "x", "xy". - A matched pair without such a comma is kept literally, braces included, though groups inside it still expand: "{a}" gives "{a}" and "{{a,b}}" gives "{a}", "{b}". - Everything else is literal, including commas outside groups. Pieces next to each other combine in every way, the left piece varying slowest: "{a,b}{c,d}" gives "ac", "ad", "bc", "bd". Duplicates are kept.
The result has at most 100,000 strings; s can be up to 100,000 characters long and nest up to 300 levels deep.
Signature
/**
* @param {string} s
* @returns {string[]}
*/
function brace_expand(s)Exemples
brace_expand("a{b,c}d") // -> ["abd", "acd"]
brace_expand("{a,b}{c,d}") // -> ["ac", "ad", "bc", "bd"]
brace_expand("{a}") // -> ["{a}"]Plus 16 tests masqués et 3 tests de performance sous contrainte de temps ; leurs entrées ne sont pas affichées. Les défis sont soumis aux modèles en anglais.
#1Google Gemini 3.8 Flashnon résolu · 21 sur 22 testsréponse en 9.6 s · exécution 743 ms · $0.0053 ✓ brace_expand("a{b,c}d")attendu ["abd", "acd"] 21 ms ✓ brace_expand("{a,b}{c,d}")attendu ["ac", "ad", "bc", "bd"] <1 ms ✓ brace_expand("{a}")attendu ["{a}"] 2 ms ✓ <1 ms✓ 2 ms✓ 1 ms✓ 1 ms✓ 2 ms✓ 2 ms✓ 2 ms✓ 3 ms✓ <1 ms✓ <1 ms✓ <1 ms✓ 2 ms✓ <1 ms✓ <1 ms✓ 1 ms✓ 1 ms⏱ délai limite dépassé⏱ 63 ms⏱ 335 msCode
/** * @param {string} s * @returns {string[]} */ function brace_expand(s) { const n = s.length; // Step 1: Match braces // Braces are matched left to right: each '}' closes nearest unclosed '{'. // Unmatched braces are ordinary characters. const match = new Int32Array(n).fill(-1); const stack = []; for (let i = 0; i < n; i++) { if (s.charCodeAt(i) === 123) { // '{' stack.push(i); } else if (s.charCodeAt(i) === 125) { // '}' if (stack.length > 0) { const open = stack.pop(); match[open] = i; match[i] = open; } } } // Step 2: Determine for each matched '{' whether it is a valid group (has comma directly inside) const isGroup = new Uint8Array(n); for (let i = 0; i < n; i++) { if (s.charCodeAt(i) === 123 && match[i] !== -1) { const close = match[i]; let hasComma = false; let j = i + 1; while (j < close) { const c = s.charCodeAt(j); if (c === 44) { // ',' hasComma = true; break; } if (c === 123 && match[j] !== -1) { j = match[j] + 1; } else { j++; } } if (hasComma) { isGroup[i] = 1; } } } // Parse [start, end) into an AST or expand directly // Note: result has at most 100,000 strings. // Recursion depth up to 300 levels deep. function expand(start, end) { // Collect sequence of parts const parts = []; let i = start; let literalBuf = ''; while (i < end) { const c = s.charCodeAt(i); if (c === 123 && match[i] !== -1 && match[i] < end) { const close = match[i]; if (isGroup[i]) { if (literalBuf.length > 0) { parts.push([literalBuf]); literalBuf = ''; } // Split by top-level commas inside [i + 1, close) const alternatives = []; let segStart = i + 1; let k = i + 1; while (k < close) { const kc = s.charCodeAt(k); if (kc === 44) { // ',' alternatives.push(expand(segStart, k)); segStart = k + 1; k++; } else if (kc === 123 && match[k] !== -1 && match[k] < close) { k = match[k] + 1; } else { k++; } } alternatives.push(expand(segStart, close)); // Flatten alternatives const groupRes = []; for (const alt of alternatives) { for (let a = 0; a < alt.length; a++) { groupRes.push(alt[a]); } } parts.push(groupRes); i = close + 1; } else { // Matched pair without top-level comma: kept literally, braces included, // though groups inside it still expand! // "{a}" -> literal '{', expand(a), literal '}' if (literalBuf.length > 0) { parts.push([literalBuf]); literalBuf = ''; } const inner = expand(i + 1, close); const preserved = new Array(inner.length); for (let idx = 0; idx < inner.length; idx++) { preserved[idx] = '{' + inner[idx] + '}'; } parts.push(preserved); i = close + 1; } } else { literalBuf += s[i]; i++; } } if (literalBuf.length > 0) { parts.push([literalBuf]); } if (parts.length === 0) { return ['']; } // Cartesian product of parts let current = parts[0]; for (let p = 1; p < parts.length; p++) { const nextPart = parts[p]; const nextLen = nextPart.length; const curLen = current.length; const combined = new Array(curLen * nextLen); let ptr = 0; for (let cIdx = 0; cIdx < curLen; cIdx++) { const prefix = current[cIdx]; for (let nIdx = 0; nIdx < nextLen; nIdx++) { combined[ptr++] = prefix + nextPart[nIdx]; } } current = combined; } return current; } return expand(0, n); }Second essai
non résolu · 21 sur 22 testsréponse en 13 s · $0.0074Le modèle a eu accès au nombre de tests échoués, aux exemples en échec avec les valeurs attendues et obtenues, ainsi qu'au motif d'échec des tests cachés (sans leurs entrées). Ne compte ni pour le classement ni pour l'évaluation.
✓ brace_expand("a{b,c}d")attendu ["abd", "acd"] 3 ms ✓ brace_expand("{a,b}{c,d}")attendu ["ac", "ad", "bc", "bd"] 2 ms ✓ brace_expand("{a}")attendu ["{a}"] 1 ms ✓ <1 ms✓ 1 ms✓ 3 ms✓ 2 ms✓ 2 ms✓ 2 ms✓ 2 ms✓ 1 ms✓ 1 ms✓ <1 ms✓ 2 ms✓ 2 ms✓ 1 ms✓ 2 ms✓ 1 ms✓ <1 ms⏱ délai limite dépassé⏱ 43 ms⏱ 187 msCode
/** * @param {string} s * @returns {string[]} */ function brace_expand(s) { const n = s.length; if (n === 0) return ['']; const match = new Int32Array(n).fill(-1); const stack = []; for (let i = 0; i < n; i++) { const code = s.charCodeAt(i); if (code === 123) { // '{' stack.push(i); } else if (code === 125) { // '}' if (stack.length > 0) { const open = stack.pop(); match[open] = i; match[i] = open; } } } // Check if each matched brace contains any unnested comma or groups inside // hasGroup[i] = whether anything expands inside (groups or nested groups) const isGroup = new Uint8Array(n); const hasExpansion = new Uint8Array(n); for (let i = n - 1; i >= 0; i--) { if (s.charCodeAt(i) === 123 && match[i] !== -1) { const close = match[i]; let hasComma = false; let anyExpand = false; let j = i + 1; while (j < close) { const c = s.charCodeAt(j); if (c === 44) { hasComma = true; j++; } else if (c === 123 && match[j] !== -1 && match[j] < close) { if (isGroup[j] || hasExpansion[j]) { anyExpand = true; } j = match[j] + 1; } else { j++; } } if (hasComma) { isGroup[i] = 1; hasExpansion[i] = 1; } else if (anyExpand) { hasExpansion[i] = 1; } } } // Quick check: does the whole string have any group expansion? let hasAnyGroup = false; for (let i = 0; i < n; i++) { if (isGroup[i]) { hasAnyGroup = true; break; } } if (!hasAnyGroup) { return [s]; } function expand(start, end) { const parts = []; let i = start; let litStart = start; while (i < end) { const c = s.charCodeAt(i); if (c === 123 && match[i] !== -1 && match[i] < end) { const close = match[i]; if (isGroup[i]) { if (i > litStart) { parts.push([s.slice(litStart, i)]); } const groupRes = []; let segStart = i + 1; let k = i + 1; while (k < close) { const kc = s.charCodeAt(k); if (kc === 44) { const alt = expand(segStart, k); for (let a = 0; a < alt.length; a++) groupRes.push(alt[a]); segStart = k + 1; k++; } else if (kc === 123 && match[k] !== -1 && match[k] < close) { k = match[k] + 1; } else { k++; } } const lastAlt = expand(segStart, close); for (let a = 0; a < lastAlt.length; a++) groupRes.push(lastAlt[a]); parts.push(groupRes); i = close + 1; litStart = i; } else if (hasExpansion[i]) { if (i > litStart) { parts.push([s.slice(litStart, i)]); } const inner = expand(i + 1, close); const preserved = new Array(inner.length); for (let idx = 0; idx < inner.length; idx++) { preserved[idx] = '{' + inner[idx] + '}'; } parts.push(preserved); i = close + 1; litStart = i; } else { // No expansion inside this brace pair, treat entire { ... } as literal i = close + 1; } } else { i++; } } if (i > litStart) { parts.push([s.slice(litStart, i)]); } if (parts.length === 0) { return ['']; } let current = parts[0]; for (let p = 1; p < parts.length; p++) { const nextPart = parts[p]; const nextLen = nextPart.length; const curLen = current.length; if (curLen === 1 && current[0] === '') { current = nextPart; continue; } if (nextLen === 1 && nextPart[0] === '') { continue; } if (nextLen === 1) { const suffix = nextPart[0]; const combined = new Array(curLen); for (let cIdx = 0; cIdx < curLen; cIdx++) { combined[cIdx] = current[cIdx] + suffix; } current = combined; } else if (curLen === 1) { const prefix = current[0]; const combined = new Array(nextLen); for (let nIdx = 0; nIdx < nextLen; nIdx++) { combined[nIdx] = prefix + nextPart[nIdx]; } current = combined; } else { const combined = new Array(curLen * nextLen); let ptr = 0; for (let cIdx = 0; cIdx < curLen; cIdx++) { const prefix = current[cIdx]; for (let nIdx = 0; nIdx < nextLen; nIdx++) { combined[ptr++] = prefix + nextPart[nIdx]; } } current = combined; } } return current; } return expand(0, n); }#2OpenAI GPT-6.1 Terranon résolu · 20 sur 22 testsréponse en 10 s · exécution 781 ms · $0.0046 ✓ brace_expand("a{b,c}d")attendu ["abd", "acd"] 3 ms ✓ brace_expand("{a,b}{c,d}")attendu ["ac", "ad", "bc", "bd"] 1 ms ✓ brace_expand("{a}")attendu ["{a}"] 2 ms ✓ <1 ms✓ 1 ms✓ 1 ms✓ 1 ms✓ 6 ms✓ 2 ms✓ 2 ms✓ 28 ms✓ <1 ms✓ 2 ms✓ <1 ms✓ <1 ms✓ 3 ms✓ 2 ms✓ 1 ms✓ 1 ms⏱ délai limite dépassé⏱ 53 ms⏱ délai limite dépasséCode
function brace_expand(s) { const n = s.length; const match = new Int32Array(n); match.fill(-1); const stack = []; for (let i = 0; i < n; i++) { const c = s.charCodeAt(i); if (c === 123) { stack.push(i); } else if (c === 125 && stack.length) { const open = stack.pop(); match[open] = i; } } // Parse matched pairs into concatenation and alternative nodes. // Unmatched braces are included in literal substrings. const root = { parts: [], start: 0, open: -1, alternatives: null }; const frames = [root]; for (let i = 0; i < n; i++) { const frame = frames[frames.length - 1]; const c = s.charCodeAt(i); if (c === 123 && match[i] !== -1) { if (frame.start < i) frame.parts.push(s.slice(frame.start, i)); frames.push({ parts: [], start: i + 1, open: i, alternatives: null }); } else if (c === 44 && frame.open !== -1) { if (frame.start < i) frame.parts.push(s.slice(frame.start, i)); if (frame.alternatives === null) frame.alternatives = []; frame.alternatives.push(frame.parts); frame.parts = []; frame.start = i + 1; } else if (c === 125 && frame.open !== -1 && match[frame.open] === i) { if (frame.start < i) frame.parts.push(s.slice(frame.start, i)); frames.pop(); let node; if (frame.alternatives !== null) { frame.alternatives.push(frame.parts); node = { alternatives: frame.alternatives }; } else { node = { literalBraces: true, parts: frame.parts }; } const parent = frames[frames.length - 1]; parent.parts.push(node); parent.start = i + 1; } } if (root.start < n) root.parts.push(s.slice(root.start)); function combine(left, right) { if (right.length === 1 && right[0] === "") return left; if (left.length === 1 && left[0] === "") return right; const result = new Array(left.length * right.length); let k = 0; for (let i = 0; i < left.length; i++) { for (let j = 0; j < right.length; j++) { result[k++] = left[i] + right[j]; } } return result; } function expandParts(parts) { let result = [""]; for (let i = 0; i < parts.length; i++) { const part = parts[i]; let values; if (typeof part === "string") { values = [part]; } else if (part.literalBraces) { values = expandParts(part.parts); for (let j = 0; j < values.length; j++) { values[j] = "{" + values[j] + "}"; } } else { values = []; for (let j = 0; j < part.alternatives.length; j++) { const expanded = expandParts(part.alternatives[j]); for (let k = 0; k < expanded.length; k++) values.push(expanded[k]); } } result = combine(result, values); } return result; } return expandParts(root.parts); }Second essai
non résolu · 20 sur 22 testsréponse en 11 s · $0.0064Le modèle a eu accès au nombre de tests échoués, aux exemples en échec avec les valeurs attendues et obtenues, ainsi qu'au motif d'échec des tests cachés (sans leurs entrées). Ne compte ni pour le classement ni pour l'évaluation.
✓ brace_expand("a{b,c}d")attendu ["abd", "acd"] 4 ms ✓ brace_expand("{a,b}{c,d}")attendu ["ac", "ad", "bc", "bd"] 3 ms ✓ brace_expand("{a}")attendu ["{a}"] 2 ms ✓ 4 ms✓ 2 ms✗ mauvaise réponse✓ 2 ms✓ 3 ms✓ 1 ms✓ 2 ms✓ 2 ms✓ 1 ms✓ <1 ms✓ 1 ms✓ 1 ms✓ 2 ms✓ 1 ms✓ 1 ms✓ 1 ms⏱ délai limite dépassé⏱ 68 ms⏱ 208 msCode
function brace_expand(s) { const n = s.length; const match = new Int32Array(n); match.fill(-1); const stack = []; for (let i = 0; i < n; i++) { const c = s.charCodeAt(i); if (c === 123) { stack.push(i); } else if (c === 125 && stack.length) { match[stack.pop()] = i; } } const root = { parts: [], start: 0, open: -1, alternatives: null }; const frames = [root]; for (let i = 0; i < n; i++) { const frame = frames[frames.length - 1]; const c = s.charCodeAt(i); if (c === 123 && match[i] !== -1) { if (frame.start < i) frame.parts.push(s.slice(frame.start, i)); frames.push({ parts: [], start: i + 1, open: i, alternatives: null }); } else if (c === 44 && frame.open !== -1) { if (frame.start < i) frame.parts.push(s.slice(frame.start, i)); if (frame.alternatives === null) frame.alternatives = []; frame.alternatives.push(frame.parts); frame.parts = []; frame.start = i + 1; } else if (c === 125 && frame.open !== -1 && match[frame.open] === i) { if (frame.start < i) frame.parts.push(s.slice(frame.start, i)); frames.pop(); const parent = frames[frames.length - 1]; if (frame.alternatives === null) { parent.parts.push("{"); for (let j = 0; j < frame.parts.length; j++) { parent.parts.push(frame.parts[j]); } parent.parts.push("}"); } else { frame.alternatives.push(frame.parts); parent.parts.push(frame.alternatives); } parent.start = i + 1; } } if (root.start < n) root.parts.push(s.slice(root.start)); // Compile the expression into a sequence of literals and choice points. // Each alternative ends with a jump to the continuation. const code = []; function compile(parts) { let pending = ""; function flush() { if (pending) { code.push(pending); pending = ""; } } for (let i = 0; i < parts.length; i++) { const part = parts[i]; if (typeof part === "string") { pending += part; } else { flush(); const choice = { branches: [] }; code.push(choice); const jumps = []; for (let j = 0; j < part.length; j++) { choice.branches.push(code.length); compile(part[j]); if (j + 1 < part.length) { const jump = { target: 0 }; jumps.push(jump); code.push(jump); } } const end = code.length; for (let j = 0; j < jumps.length; j++) jumps[j].target = end; } } flush(); } compile(root.parts); const results = []; const pieces = []; const choices = []; let pc = 0; while (true) { while (pc < code.length) { const instruction = code[pc]; if (typeof instruction === "string") { pieces.push(instruction); pc++; } else if (instruction.branches) { const branches = instruction.branches; if (branches.length > 1) { choices.push({ branches, next: 1, length: pieces.length }); } pc = branches[0]; } else { pc = instruction.target; } } results.push(pieces.join("")); while (choices.length) { const choice = choices[choices.length - 1]; pieces.length = choice.length; pc = choice.branches[choice.next++]; if (choice.next === choice.branches.length) choices.pop(); break; } if (!choices.length && pc >= code.length) break; } return results; }#3MoonshotAI Kimi K2.7 Codenon résolu · 0 sur 22 testsréponse en 27 s · $0.02 la réponse a été coupée avant la fin du code
✗ brace_expand("a{b,c}d")attendu ["abd", "acd"]aucun code dans la réponse — ✗ brace_expand("{a,b}{c,d}")attendu ["ac", "ad", "bc", "bd"]aucun code dans la réponse — ✗ brace_expand("{a}")attendu ["{a}"]aucun code dans la réponse — ✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse⏱ aucun code dans la réponse⏱ aucun code dans la réponse⏱ aucun code dans la réponse#3SpaceXAI Grok 4.7non résolu · 0 sur 22 testsréponse en 120 s aucun code dans la réponse
✗ brace_expand("a{b,c}d")attendu ["abd", "acd"]aucun code dans la réponse — ✗ brace_expand("{a,b}{c,d}")attendu ["ac", "ad", "bc", "bd"]aucun code dans la réponse — ✗ brace_expand("{a}")attendu ["{a}"]aucun code dans la réponse — ✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse✗ aucun code dans la réponse⏱ aucun code dans la réponse⏱ aucun code dans la réponse⏱ aucun code dans la réponse
Coût en jetons: $0.04 · Déroulement et calcul des scores →