1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
import { of } from "rxjs";
import { concatAll, map, reduce, toArray } from 'rxjs/operators';
import { ExerciseModuleFunc } from "../types";
interface RuleChild {
type: string;
num: number;
}
interface Rule {
type: string;
children: RuleChild[];
}
interface TreeNode {
type: string;
children: TreeNode[];
}
const union = <T extends unknown>(...sets: Set<T>[]): Set<T> => {
let result = new Set<T>();
for (const set of sets) {
result = new Set([...Array.from(result), ...Array.from(set)]);
}
return result;
}
const rowToRule = (row: string): Rule => {
const [lhs, rhs] = row.split("bags contain").map(part => part.trim());
if (rhs.startsWith("no")) {
return {
type: lhs,
children: []
}
}
const childBags = rhs.split(", ");
const children = childBags.map(str => {
const match = str.match(/(\d)\ (\w+\ \w+).*?/);
const num = Number(match[1]);
const type = match[2];
return {
type,
num
}
});
return {
type: lhs,
children
}
};
const constructNode = (rules: Rule[], type: string): TreeNode => {
const children = rules
.filter(rule => rule.children.some(child => child.type === type))
.reduce((acc: TreeNode, rule) => {
const newChild = constructNode(rules, rule.type);
acc.children.push(newChild);
return acc;
}, { type, children: [] });
return children;
}
const buildTree = (rules: Rule[], rootType: string) => {
return constructNode(rules, rootType);
}
const uniqueNonRootNodes = (tree: TreeNode): Set<string> => {
let set = new Set<string>();
for (let child of tree.children) {
set.add(child.type);
const childUniques = uniqueNonRootNodes(child);
set = union(set, childUniques);
}
return set;
}
const day7: ExerciseModuleFunc = async (input: string) => {
const rows = input.split("\n");
const prom1 = of(rows).pipe(
concatAll(),
map(rowToRule),
toArray(),
map(rules => buildTree(rules, "shiny gold")),
map(tree => uniqueNonRootNodes(tree)),
map(set => set.size)
).toPromise();
// const prom2 = of(rows).pipe(
// ).toPromise();
return Promise.all([prom1]);
}
export default day7;
|