-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday25.ts
127 lines (102 loc) · 2.71 KB
/
day25.ts
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const puzzle_input = `<get from AoC>`.split('\n');
function log(u: unknown) {
console.log(JSON.stringify(u, undefined, 2));
}
function part1(input: string[]) {
const edges: [number, number][] = [];
const vToId: Map<string, number> = new Map();
for (let line of input) {
let [v1, v2s] = line.split(': ');
if (!vToId.has(v1)) {
vToId.set(v1, vToId.size);
}
for (let v2 of v2s.split(' ')) {
if (!vToId.has(v2)) {
vToId.set(v2, vToId.size);
}
edges.push([vToId.get(v1)!, vToId.get(v2)!]);
}
}
while (true) {
let groups = unionFind(vToId.size, edges, 3);
if (groups != null) {
let group1Count = groups.filter((x) => x === groups?.[0]).length;
log(group1Count * (vToId.size - group1Count));
break;
}
}
}
function unionFind(
vertexCount: number,
edges: [number, number][],
desiredCuts: number,
) {
//shuffle
for (let i = 0; i < edges.length; ++i) {
let idx = Math.floor(Math.random() * i + 1);
[edges[i], edges[idx]] = [edges[idx], edges[i]];
}
let groupParents = [-1];
let vertexGroups = new Uint16Array(vertexCount);
let groupPromotions = [-1];
function union(v1: number, v2: number) {
if (!vertexGroups[v1] && !vertexGroups[v2]) {
let group = groupParents.length;
groupParents.push(group);
groupPromotions.push(1);
vertexGroups[v1] = group;
vertexGroups[v2] = group;
} else if (!vertexGroups[v1]) {
let g = (vertexGroups[v2] = parent(v2));
++groupPromotions[g];
vertexGroups[v1] = g;
} else if (!vertexGroups[v2]) {
let g = (vertexGroups[v1] = parent(v1));
++groupPromotions[g];
vertexGroups[v2] = g;
} else {
let g1 = parent(v1);
let g2 = parent(v2);
if (g1 !== g2) {
if (groupPromotions[g1] > groupPromotions[g2]) {
[g2, g1] = [g1, g2];
}
groupPromotions[g2] += groupPromotions[g1] + 1;
groupParents[g1] = g2;
vertexGroups[v1] = g2;
vertexGroups[v2] = g2;
} else {
return false;
}
}
return true;
}
function parent(v: number) {
if (vertexGroups[v] === 0) {
return -1;
}
let group = vertexGroups[v];
while (group !== groupParents[group]) {
group = groupParents[group];
}
return group;
}
let edgeIdx = 0;
while (vertexCount > 2) {
let [v1, v2] = edges[edgeIdx++];
if (union(v1, v2)) {
--vertexCount;
}
}
let removedEdges = 0;
for (let [v1, v2] of edges) {
if ((vertexGroups[v1] = parent(v1)) !== (vertexGroups[v2] = parent(v2))) {
++removedEdges;
}
}
if (removedEdges === desiredCuts) {
return vertexGroups;
}
return null;
}
part1(puzzle_input);