Skip to content

Commit e128e93

Browse files
committed
less involved solution
1 parent 1ef2d87 commit e128e93

File tree

1 file changed

+104
-29
lines changed

1 file changed

+104
-29
lines changed

src/2024/day24.js

Lines changed: 104 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ function run(gates, wiresMap) {
1111
gates.forEach(({ a, op, b, wire }) => {
1212
a = wiresMap.get(a);
1313
b = wiresMap.get(b);
14-
if (a !== undefined && b !== undefined) {
14+
let c = wiresMap.get(wire);
15+
if (a !== undefined && b !== undefined && c === undefined) {
16+
done = false;
1517
if (op === "AND") wiresMap.set(wire, a & b);
1618
if (op === "OR") wiresMap.set(wire, a | b);
1719
if (op === "XOR") wiresMap.set(wire, a ^ b);
18-
} else done = false;
20+
}
1921
});
2022
}
21-
return parseInt(read(wiresMap, "z"), 2);
2223
}
2324

2425
function parse(input) {
@@ -38,37 +39,111 @@ function parse(input) {
3839

3940
export function part1(input) {
4041
let { wiresMap, gates } = parse(input);
41-
return run(gates, wiresMap);
42+
run(gates, wiresMap);
43+
return parseInt(read(wiresMap, "z"), 2);
44+
}
45+
46+
function extractUnit(gates, i) {
47+
let num = i.toString().padStart(2, "0");
48+
let next = (i + 1).toString().padStart(2, "0");
49+
let unit = gates.filter(x => x.a === `x${num}` && x.b === `y${num}`);
50+
let not = gates
51+
.filter(x => x.a === `x${next}` && x.b === `y${next}`)
52+
.map(x => x.wire);
53+
let wires = unit.map(x => x.wire);
54+
let done = false;
55+
while (!done) {
56+
done = true;
57+
let more = gates.filter(x => wires.includes(x.a) || wires.includes(x.b));
58+
more = more.filter(x => !unit.includes(x));
59+
more = more.filter(x => !not.includes(x.a) && !not.includes(x.b));
60+
if (more.length) {
61+
done = false;
62+
unit.push(...more);
63+
wires.push(...more.map(x => x.wire));
64+
}
65+
}
66+
return unit;
67+
}
68+
69+
function unitTest(gates) {
70+
let inp = new Set(gates.flatMap(x => [x.a, x.b]));
71+
let out = new Set(gates.map(x => x.wire));
72+
let inputs = [...inp.difference(out)].sort();
73+
let outputs = [...out.difference(inp)].sort();
74+
if (outputs.every(x => x.startsWith("z"))) outputs.reverse();
75+
for (let i = 0; i < 2 ** inputs.length; i++) {
76+
let wiresMap = new Map();
77+
let bin = i.toString(2);
78+
inputs.forEach((x, j) => wiresMap.set(x, +bin[j]));
79+
run(gates, wiresMap);
80+
let result = parseInt(outputs.map(x => wiresMap.get(x)).join(""), 2);
81+
let expect = bin.split("").reduce((a, b) => +a + +b, 0);
82+
if (result !== expect) return false;
83+
}
84+
return true;
85+
}
86+
87+
function getSwamps(gates) {
88+
let options = [];
89+
let out = gates.map(x => x.wire);
90+
for (let i = 0; i < out.length; i++) {
91+
for (let j = i + 1; j < out.length; j++) {
92+
let option = gates.map(x => {
93+
let next = { ...x };
94+
if (x.wire === out[i]) next.wire = out[j];
95+
if (x.wire === out[j]) next.wire = out[i];
96+
return next;
97+
});
98+
options.push({ swap: [out[i], out[j]], gates: option });
99+
}
100+
}
101+
return options;
102+
}
103+
104+
export function part2(input) {
105+
let { wiresMap, gates } = parse(input);
106+
let { length } = read(wiresMap, "x");
107+
let swapped = [];
108+
for (let i = 0; i < length; i++) {
109+
let unit = extractUnit(gates, i);
110+
let pass = unitTest(unit);
111+
if (!pass) {
112+
let { swap } = getSwamps(unit).find(x => unitTest(x.gates));
113+
swapped.push(...swap);
114+
}
115+
}
116+
return swapped.sort().join(",");
42117
}
43118

44-
// full adder
119+
// Shorter but much more involved solution adapted from reddit
45120
// https://www.build-electronic-circuits.com/wp-content/uploads/2022/10/fullAdder-1-1024x473.png
46121
// X XOR Y => M
47122
// X AND Y => N
48123
// CIN XOR M => Z
49124
// CIN AND M => R
50125
// R OR N => COUT
51-
export function part2(input) {
52-
let { gates, wiresMap } = parse(input);
53-
function find(a, b, op) {
54-
[a, b] = [a, b].sort();
55-
return gates.find(x => x.a === a && x.b === b && x.op === op)?.wire;
56-
}
57-
let swapped = [];
58-
let { length } = read(wiresMap, "x");
59-
let cin = find("x00", "y00", "AND");
60-
for (let i = 1; i < length; i++) {
61-
let num = i.toString().padStart(2, "0");
62-
let m = find(`x${num}`, `y${num}`, "XOR");
63-
let n = find(`x${num}`, `y${num}`, "AND");
64-
if (find(cin, n, "XOR")) swapped.push(...([m, n] = [n, m]));
65-
let z = find(cin, m, "XOR");
66-
let r = find(cin, m, "AND");
67-
if (find(r, z, "OR")) swapped.push(...([n, z] = [z, n]));
68-
if (find(n, z, "OR")) swapped.push(...([r, z] = [z, r]));
69-
let cout = find(r, n, "OR");
70-
if (cout === `z${num}`) swapped.push(...([z, cout] = [cout, z]));
71-
cin = cout;
72-
}
73-
return swapped.sort().join(",");
74-
}
126+
// export function part2(input) {
127+
// let { wiresMap, gates } = parse(input);
128+
// function find(a, b, op) {
129+
// [a, b] = [a, b].sort();
130+
// return gates.find(x => x.a === a && x.b === b && x.op === op)?.wire;
131+
// }
132+
// let swapped = [];
133+
// let { length } = read(wiresMap, "x");
134+
// let cin = find("x00", "y00", "AND");
135+
// for (let i = 1; i < length; i++) {
136+
// let num = i.toString().padStart(2, "0");
137+
// let m = find(`x${num}`, `y${num}`, "XOR");
138+
// let n = find(`x${num}`, `y${num}`, "AND");
139+
// if (find(cin, n, "XOR")) swapped.push(...([m, n] = [n, m]));
140+
// let z = find(cin, m, "XOR");
141+
// let r = find(cin, m, "AND");
142+
// if (find(r, z, "OR")) swapped.push(...([n, z] = [z, n]));
143+
// if (find(n, z, "OR")) swapped.push(...([r, z] = [z, r]));
144+
// let cout = find(r, n, "OR");
145+
// if (cout === `z${num}`) swapped.push(...([z, cout] = [cout, z]));
146+
// cin = cout;
147+
// }
148+
// return swapped.sort().join(",");
149+
// }

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