Skip to content

Commit 44e4ca8

Browse files
committed
solved day 24
1 parent 2dc3397 commit 44e4ca8

File tree

10 files changed

+1477
-832
lines changed

10 files changed

+1477
-832
lines changed

src/2024/day24.js

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import { combinations, permutations } from "combinatorial-generators";
2+
3+
function read(wiresMap, prefix) {
4+
const out = [
5+
...wiresMap.entries().filter(([wire]) => wire.startsWith(prefix)),
6+
];
7+
const n = out
8+
.sort((a, b) => b[0].localeCompare(a[0]))
9+
.map(x => x[1])
10+
.join("");
11+
return parseInt(n, 2);
12+
}
13+
14+
function run(gates, wiresMap) {
15+
let done = false;
16+
while (!done) {
17+
done = true;
18+
gates.forEach(({ left, op, right, wire }) => {
19+
let a = wiresMap.get(left);
20+
let b = wiresMap.get(right);
21+
if (a !== undefined && b !== undefined) {
22+
if (op === "AND") {
23+
wiresMap.set(wire, a & b);
24+
} else if (op === "OR") {
25+
wiresMap.set(wire, a | b);
26+
} else if (op === "XOR") {
27+
wiresMap.set(wire, a ^ b);
28+
}
29+
} else done = false;
30+
});
31+
}
32+
return read(wiresMap, "z");
33+
}
34+
35+
export function part1(input) {
36+
let [wires, gates] = input.split("\n\n");
37+
let wiresMap = new Map();
38+
wires.split("\n").forEach(line => {
39+
let [wire, value] = line.split(": ");
40+
wiresMap.set(wire, +value);
41+
return { wire, value: +value };
42+
});
43+
gates = gates.split("\n").map(line => {
44+
let [left, op, right, , wire] = line.split(" ");
45+
return { left, op, right, wire };
46+
});
47+
return run(gates, wiresMap);
48+
}
49+
50+
//shameless rip off from reddit :(
51+
export function part2(input) {
52+
let [, gates] = input.split("\n\n");
53+
gates = gates.split("\n");
54+
55+
function find(a, b, op) {
56+
const gate = gates.find(
57+
gate =>
58+
gate.startsWith(`${a} ${op} ${b}`) ||
59+
gate.startsWith(`${b} ${op} ${a}`),
60+
);
61+
return gate?.split(" -> ").pop();
62+
}
63+
64+
// half adder
65+
// X1 XOR Y1 => M1
66+
// X1 AND Y1 => N1
67+
// C0 AND M1 => R1
68+
// C0 XOR M1 -> Z1
69+
// R1 OR N1 -> C1
70+
let swapped = [];
71+
let c0 = null;
72+
for (let i = 0; i < 45; i++) {
73+
let n = i.toString().padStart(2, "0");
74+
let m1, n1, r1, z1, c1;
75+
m1 = find(`x${n}`, `y${n}`, "XOR");
76+
n1 = find(`x${n}`, `y${n}`, "AND");
77+
if (c0) {
78+
r1 = find(c0, m1, "AND");
79+
if (!r1) {
80+
[n1, m1] = [m1, n1];
81+
swapped.push(m1, n1);
82+
r1 = find(c0, m1, "AND");
83+
}
84+
85+
z1 = find(c0, m1, "XOR");
86+
if (m1?.startsWith("z")) {
87+
[m1, z1] = [z1, m1];
88+
swapped.push(m1, z1);
89+
}
90+
if (n1?.startsWith("z")) {
91+
[n1, z1] = [z1, n1];
92+
swapped.push(n1, z1);
93+
}
94+
if (r1?.startsWith("z")) {
95+
[r1, z1] = [z1, r1];
96+
swapped.push(r1, z1);
97+
}
98+
99+
c1 = find(r1, n1, "OR");
100+
if (c1?.startsWith("z") && c1 !== "z45") {
101+
[c1, z1] = [z1, c1];
102+
swapped.push(c1, z1);
103+
}
104+
}
105+
c0 = c1 || n1;
106+
}
107+
return swapped.sort().join(",");
108+
}
109+
110+
// my slow solution, runs for ever...
111+
export function oldpart2(input, n = 4, check = (x, y) => x + y) {
112+
let [wires, gates] = input.split("\n\n");
113+
let wiresMap = new Map();
114+
wires.split("\n").forEach(line => {
115+
let [wire, value] = line.split(": ");
116+
wiresMap.set(wire, +value);
117+
return { wire, value: +value };
118+
});
119+
gates = gates.split("\n").map(line => {
120+
let [left, op, right, , wire] = line.split(" ");
121+
return { left, op, right, wire };
122+
});
123+
let pairs = combinations(
124+
gates.map(({ wire }) => wire),
125+
2 * n,
126+
);
127+
let x = read(wiresMap, "x");
128+
let y = read(wiresMap, "y");
129+
let found = pairs.find(pair => {
130+
let options = permutations(pair);
131+
return options.find(permutation => {
132+
let replacements = new Map();
133+
for (let i = 0; i < permutation.length; i += 2) {
134+
if (permutation[i].localeCompare(permutation[i + 1]) < 0) return false;
135+
replacements.set(permutation[i], permutation[i + 1]);
136+
replacements.set(permutation[i + 1], permutation[i]);
137+
}
138+
let newGates = gates.map(({ left, op, right, wire }) => {
139+
return {
140+
left,
141+
op,
142+
right,
143+
wire: replacements.get(wire) || wire,
144+
};
145+
});
146+
let newWiresMap = new Map(wiresMap.entries());
147+
if (run(newGates, newWiresMap) === check(x, y)) {
148+
//try another number just to make sure addition works
149+
newWiresMap.set("x04", 1);
150+
let x = read(newWiresMap, "x");
151+
let y = read(newWiresMap, "y");
152+
let newGates = gates.map(({ left, op, right, wire }) => {
153+
return {
154+
left,
155+
op,
156+
right,
157+
wire: replacements.get(wire) || wire,
158+
};
159+
});
160+
if (run(newGates, newWiresMap) === check(x, y)) return true;
161+
}
162+
});
163+
});
164+
return found.sort().join(","); //?
165+
}

src/2024/day24.spec.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { part1, part2, oldpart2 } from "./day24.js";
2+
import readInput from "../utils/read-input.js";
3+
4+
let input = readInput(import.meta.url);
5+
6+
describe("day24 2024", () => {
7+
describe("part1", () => {
8+
test("it should work for part 1 examples", () => {
9+
expect(
10+
part1(
11+
[
12+
"x00: 1",
13+
"x01: 1",
14+
"x02: 1",
15+
"y00: 0",
16+
"y01: 1",
17+
"y02: 0",
18+
"",
19+
"x00 AND y00 -> z00",
20+
"x01 XOR y01 -> z01",
21+
"x02 OR y02 -> z02",
22+
].join("\n"),
23+
),
24+
).toEqual(4);
25+
});
26+
27+
test("it should work for part 1 input", () => {
28+
expect(part1(input)).toEqual(55920211035878);
29+
});
30+
});
31+
32+
describe("part2", () => {
33+
test("it should work for part 2 examples", () => {
34+
expect(
35+
oldpart2(
36+
[
37+
"x00: 0",
38+
"x01: 1",
39+
"x02: 0",
40+
"x03: 1",
41+
"x04: 0",
42+
"x05: 1",
43+
"y00: 0",
44+
"y01: 0",
45+
"y02: 1",
46+
"y03: 1",
47+
"y04: 0",
48+
"y05: 1",
49+
"",
50+
"x00 AND y00 -> z05",
51+
"x01 AND y01 -> z02",
52+
"x02 AND y02 -> z01",
53+
"x03 AND y03 -> z03",
54+
"x04 AND y04 -> z04",
55+
"x05 AND y05 -> z00",
56+
].join("\n"),
57+
2,
58+
(x, y) => x & y,
59+
),
60+
).toEqual("z00,z01,z02,z05");
61+
});
62+
63+
test("it should work for part 2 input", () => {
64+
expect(part2(input)).toEqual("btb,cmv,mwp,rdg,rmj,z17,z23,z30");
65+
});
66+
});
67+
});

0 commit comments

Comments
 (0)