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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy