Skip to content

Commit aadcb3f

Browse files

File tree

5 files changed

+144
-0
lines changed

5 files changed

+144
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ leetcode 测试
1010

1111
##### 包含的内容如下
1212

13+
https://leetcode.cn/problems/brace-expansion-ii/
14+
15+
https://leetcode.cn/problems/brace-expansion/
16+
1317
https://leetcode.cn/problems/array-nesting/
1418

1519
https://leetcode.cn/problems/super-ugly-number/

brace-expansion-ii/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { evaluate, parse } from "../brace-expansion/index.ts";
2+
import { deduplication } from "../fraction-addition-and-subtraction/deduplication.ts";
3+
4+
export default function braceExpansionII(s: string): string[] {
5+
if (s.includes("{")) {
6+
const m = parse(s);
7+
8+
if (typeof m === "string") return [m];
9+
return deduplication(evaluate(m)).sort();
10+
} else {
11+
return [s];
12+
}
13+
}

brace-expansion-ii/test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
2+
import braceExpansionII from "./index.ts";
3+
Deno.test("brace-expansion-ii", () => {
4+
const inputs = [
5+
"{a,b}",
6+
"{a,b}{c,{d,e}}",
7+
"{{a,z},a{b,c},{ab,z}}",
8+
"{a,b}c{d,e}f",
9+
"abcd",
10+
"{a,b,c}",
11+
"zabcde{a,b,c}",
12+
"zab",
13+
"{a,b,c}{a,b,c}",
14+
"{a,b}{c,{d,e}}",
15+
"{z,{a,b}{c,{d,e}}}",
16+
];
17+
const outputs = [
18+
["a", "b"],
19+
["ac", "ad", "ae", "bc", "bd", "be"],
20+
["a", "ab", "ac", "z"],
21+
["acdf", "acef", "bcdf", "bcef"],
22+
["abcd"],
23+
["a", "b", "c"],
24+
["zabcdea", "zabcdeb", "zabcdec"],
25+
["zab"],
26+
["aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"],
27+
["ac", "ad", "ae", "bc", "bd", "be"],
28+
["ac", "ad", "ae", "bc", "bd", "be", "z"],
29+
];
30+
assertEquals(inputs.map(braceExpansionII), outputs);
31+
});

brace-expansion/index.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
export default function expand(s: string): string[] {
2+
if (s.includes("{")) {
3+
const m = parse(s);
4+
5+
if (typeof m === "string") return [m];
6+
return evaluate(m).sort();
7+
} else {
8+
return [s];
9+
}
10+
}
11+
export type Expression = AddExpression | MultExpression;
12+
13+
export interface AddExpression {
14+
type: "AddExpression";
15+
children: (Expression | string)[];
16+
}
17+
export interface MultExpression {
18+
type: "MultExpression";
19+
children: (Expression | string)[];
20+
}
21+
22+
export function parse(s: string): Expression | string {
23+
const m = s.match(/\,|\{|\}|[a-z]+/g) ?? [];
24+
if (!m || !m.length) return { type: "AddExpression", children: [] };
25+
26+
let i = 0;
27+
28+
function dfs(): Expression | string {
29+
const a: (string | Expression)[] = [];
30+
31+
while (i < m.length) {
32+
const value = m[i];
33+
if (value === "{") {
34+
i++;
35+
a.push(dfs());
36+
} else if (value === "}") {
37+
i++;
38+
break;
39+
} else {
40+
a.push(value);
41+
i++;
42+
}
43+
}
44+
45+
if (a.length == 1) {
46+
return a[0];
47+
}
48+
return a.includes(",")
49+
? splitAdd(a)
50+
: { type: "MultExpression", children: a };
51+
}
52+
const r = dfs();
53+
return r;
54+
}
55+
56+
function splitAdd(a: (string | Expression)[]): Expression | string {
57+
const e: AddExpression = { type: "AddExpression", children: [] };
58+
if (a.length === 1) return a[0];
59+
const index = a.indexOf(",");
60+
if (index < 0) return { type: "MultExpression", children: a };
61+
62+
if (index === 1) {
63+
e.children.push(a[0]);
64+
} else {
65+
e.children.push({
66+
type: "MultExpression",
67+
children: a.slice(0, index),
68+
});
69+
}
70+
e.children.push(splitAdd(a.slice(index + 1)));
71+
if (e.children.length == 1) {
72+
return e.children[0];
73+
}
74+
return e;
75+
}
76+
export function evaluate(m: Expression | string): string[] {
77+
if (typeof m === "string") return [m];
78+
79+
if (m.type === "MultExpression") {
80+
return m.children.reduce((p: string[], c): string[] => {
81+
const left = p;
82+
const right = typeof c === "string" ? [c] : evaluate(c);
83+
if (p.length === 0) return right;
84+
return left.map((v) => right.map((r) => v + r)).flat();
85+
}, [] as string[]);
86+
} else {
87+
return m.children.map(evaluate).flat();
88+
}
89+
}

brace-expansion/test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
2+
import expand from "./index.ts";
3+
Deno.test("brace-expansion", () => {
4+
const inputs = ["{a,b}c{d,e}f", "abcd"];
5+
const outputs = [["acdf", "acef", "bcdf", "bcef"], ["abcd"]];
6+
assertEquals(inputs.map(expand), outputs);
7+
});

0 commit comments

Comments
 (0)