Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
shahata committed Dec 24, 2024
1 parent 44e4ca8 commit 1ef2d87
Show file tree
Hide file tree
Showing 6 changed files with 2,091 additions and 2,080 deletions.
6 changes: 1 addition & 5 deletions src/2024/day05.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ function correct(update, rules) {
for (let i = 0; i < update.length; i++) {
for (let j = 0; j < i; j++) {
if (rules.has(`${update[i]}|${update[j]}`)) {
return () => {
let tmp = update[i];
update[i] = update[j];
update[j] = tmp;
};
return () => ([update[i], update[j]] = [update[j], update[i]]);
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/2024/day09.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ function move(disk, from, to) {
split(disk, from, disk[from].count - disk[to].count);
from++;
}
let tmp = disk[to].id;
disk[to].id = disk[from].id;
disk[from].id = tmp;
[disk[to].id, disk[from].id] = [disk[from].id, disk[to].id];
return from;
}

Expand Down
177 changes: 43 additions & 134 deletions src/2024/day24.js
Original file line number Diff line number Diff line change
@@ -1,165 +1,74 @@
import { combinations, permutations } from "combinatorial-generators";

function read(wiresMap, prefix) {
const out = [
...wiresMap.entries().filter(([wire]) => wire.startsWith(prefix)),
];
const n = out
.sort((a, b) => b[0].localeCompare(a[0]))
.map(x => x[1])
.join("");
return parseInt(n, 2);
let out = [...wiresMap.keys().filter(x => x.startsWith(prefix))];
out = out.sort().reverse();
return out.map(x => wiresMap.get(x)).join("");
}

function run(gates, wiresMap) {
let done = false;
while (!done) {
done = true;
gates.forEach(({ left, op, right, wire }) => {
let a = wiresMap.get(left);
let b = wiresMap.get(right);
gates.forEach(({ a, op, b, wire }) => {
a = wiresMap.get(a);
b = wiresMap.get(b);
if (a !== undefined && b !== undefined) {
if (op === "AND") {
wiresMap.set(wire, a & b);
} else if (op === "OR") {
wiresMap.set(wire, a | b);
} else if (op === "XOR") {
wiresMap.set(wire, a ^ b);
}
if (op === "AND") wiresMap.set(wire, a & b);
if (op === "OR") wiresMap.set(wire, a | b);
if (op === "XOR") wiresMap.set(wire, a ^ b);
} else done = false;
});
}
return read(wiresMap, "z");
return parseInt(read(wiresMap, "z"), 2);
}

export function part1(input) {
function parse(input) {
let [wires, gates] = input.split("\n\n");
let wiresMap = new Map();
wires.split("\n").forEach(line => {
let [wire, value] = line.split(": ");
wiresMap.set(wire, +value);
return { wire, value: +value };
});
gates = gates.split("\n").map(line => {
let [left, op, right, , wire] = line.split(" ");
return { left, op, right, wire };
let [a, op, b, , wire] = line.split(" ");
[a, b] = [a, b].sort();
return { a, op, b, wire };
});
return { wiresMap, gates };
}

export function part1(input) {
let { wiresMap, gates } = parse(input);
return run(gates, wiresMap);
}

//shameless rip off from reddit :(
// full adder
// https://www.build-electronic-circuits.com/wp-content/uploads/2022/10/fullAdder-1-1024x473.png
// X XOR Y => M
// X AND Y => N
// CIN XOR M => Z
// CIN AND M => R
// R OR N => COUT
export function part2(input) {
let [, gates] = input.split("\n\n");
gates = gates.split("\n");

let { gates, wiresMap } = parse(input);
function find(a, b, op) {
const gate = gates.find(
gate =>
gate.startsWith(`${a} ${op} ${b}`) ||
gate.startsWith(`${b} ${op} ${a}`),
);
return gate?.split(" -> ").pop();
[a, b] = [a, b].sort();
return gates.find(x => x.a === a && x.b === b && x.op === op)?.wire;
}

// half adder
// X1 XOR Y1 => M1
// X1 AND Y1 => N1
// C0 AND M1 => R1
// C0 XOR M1 -> Z1
// R1 OR N1 -> C1
let swapped = [];
let c0 = null;
for (let i = 0; i < 45; i++) {
let n = i.toString().padStart(2, "0");
let m1, n1, r1, z1, c1;
m1 = find(`x${n}`, `y${n}`, "XOR");
n1 = find(`x${n}`, `y${n}`, "AND");
if (c0) {
r1 = find(c0, m1, "AND");
if (!r1) {
[n1, m1] = [m1, n1];
swapped.push(m1, n1);
r1 = find(c0, m1, "AND");
}

z1 = find(c0, m1, "XOR");
if (m1?.startsWith("z")) {
[m1, z1] = [z1, m1];
swapped.push(m1, z1);
}
if (n1?.startsWith("z")) {
[n1, z1] = [z1, n1];
swapped.push(n1, z1);
}
if (r1?.startsWith("z")) {
[r1, z1] = [z1, r1];
swapped.push(r1, z1);
}

c1 = find(r1, n1, "OR");
if (c1?.startsWith("z") && c1 !== "z45") {
[c1, z1] = [z1, c1];
swapped.push(c1, z1);
}
}
c0 = c1 || n1;
let { length } = read(wiresMap, "x");
let cin = find("x00", "y00", "AND");
for (let i = 1; i < length; i++) {
let num = i.toString().padStart(2, "0");
let m = find(`x${num}`, `y${num}`, "XOR");
let n = find(`x${num}`, `y${num}`, "AND");
if (find(cin, n, "XOR")) swapped.push(...([m, n] = [n, m]));
let z = find(cin, m, "XOR");
let r = find(cin, m, "AND");
if (find(r, z, "OR")) swapped.push(...([n, z] = [z, n]));
if (find(n, z, "OR")) swapped.push(...([r, z] = [z, r]));
let cout = find(r, n, "OR");
if (cout === `z${num}`) swapped.push(...([z, cout] = [cout, z]));
cin = cout;
}
return swapped.sort().join(",");
}

// my slow solution, runs for ever...
export function oldpart2(input, n = 4, check = (x, y) => x + y) {
let [wires, gates] = input.split("\n\n");
let wiresMap = new Map();
wires.split("\n").forEach(line => {
let [wire, value] = line.split(": ");
wiresMap.set(wire, +value);
return { wire, value: +value };
});
gates = gates.split("\n").map(line => {
let [left, op, right, , wire] = line.split(" ");
return { left, op, right, wire };
});
let pairs = combinations(
gates.map(({ wire }) => wire),
2 * n,
);
let x = read(wiresMap, "x");
let y = read(wiresMap, "y");
let found = pairs.find(pair => {
let options = permutations(pair);
return options.find(permutation => {
let replacements = new Map();
for (let i = 0; i < permutation.length; i += 2) {
if (permutation[i].localeCompare(permutation[i + 1]) < 0) return false;
replacements.set(permutation[i], permutation[i + 1]);
replacements.set(permutation[i + 1], permutation[i]);
}
let newGates = gates.map(({ left, op, right, wire }) => {
return {
left,
op,
right,
wire: replacements.get(wire) || wire,
};
});
let newWiresMap = new Map(wiresMap.entries());
if (run(newGates, newWiresMap) === check(x, y)) {
//try another number just to make sure addition works
newWiresMap.set("x04", 1);
let x = read(newWiresMap, "x");
let y = read(newWiresMap, "y");
let newGates = gates.map(({ left, op, right, wire }) => {
return {
left,
op,
right,
wire: replacements.get(wire) || wire,
};
});
if (run(newGates, newWiresMap) === check(x, y)) return true;
}
});
});
return found.sort().join(","); //?
}
32 changes: 1 addition & 31 deletions src/2024/day24.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { part1, part2, oldpart2 } from "./day24.js";
import { part1, part2 } from "./day24.js";
import readInput from "../utils/read-input.js";

let input = readInput(import.meta.url);
Expand Down Expand Up @@ -30,36 +30,6 @@ describe("day24 2024", () => {
});

describe("part2", () => {
test("it should work for part 2 examples", () => {
expect(
oldpart2(
[
"x00: 0",
"x01: 1",
"x02: 0",
"x03: 1",
"x04: 0",
"x05: 1",
"y00: 0",
"y01: 0",
"y02: 1",
"y03: 1",
"y04: 0",
"y05: 1",
"",
"x00 AND y00 -> z05",
"x01 AND y01 -> z02",
"x02 AND y02 -> z01",
"x03 AND y03 -> z03",
"x04 AND y04 -> z04",
"x05 AND y05 -> z00",
].join("\n"),
2,
(x, y) => x & y,
),
).toEqual("z00,z01,z02,z05");
});

test("it should work for part 2 input", () => {
expect(part2(input)).toEqual("btb,cmv,mwp,rdg,rmj,z17,z23,z30");
});
Expand Down
Loading

0 comments on commit 1ef2d87

Please sign in to comment.