Skip to content

Commit b3491e7

Browse files
committed
q
1 parent c7cf630 commit b3491e7

File tree

1 file changed

+47
-51
lines changed

1 file changed

+47
-51
lines changed

2024/Day24/Solution.cs

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,102 +4,98 @@ namespace AdventOfCode.Y2024.Day24;
44
using System.Collections.Generic;
55
using System.Linq;
66
using System.Text.RegularExpressions;
7+
using Circuit = System.Collections.Generic.Dictionary<string, Gate>;
78

8-
record struct Rule(string in1, string in2, string kind, string output);
9+
record struct Gate(string in1, string kind, string in2);
910

1011
[ProblemName("Crossed Wires")]
1112
class Solution : Solver {
1213

1314
public object PartOne(string input) {
14-
var gate = Parse(input);
15-
var bits = gate.Keys.Where(k => k.StartsWith("z")).OrderByDescending(x => x).ToArray();
15+
var (inputs, circuit) = Parse(input);
16+
17+
var outputs = from label in circuit.Keys where label.StartsWith("z") select label;
18+
1619
var res = 0L;
17-
foreach (var b in bits) {
18-
res = res * 2 + gate[b]();
20+
foreach (var label in outputs.OrderByDescending(label=>label)) {
21+
res = res * 2 + Evaluate(label, circuit, inputs);
1922
}
2023
return res;
2124
}
2225

26+
int Evaluate(string label, Circuit circuit, Dictionary<string, int> inputs) {
27+
if (inputs.TryGetValue(label, out var res)) {
28+
return res;
29+
} else {
30+
return circuit[label] switch {
31+
Gate(var in1, "AND", var in2) => Evaluate(in1, circuit, inputs) & Evaluate(in2, circuit, inputs),
32+
Gate(var in1, "OR", var in2) => Evaluate(in1, circuit, inputs) | Evaluate(in2, circuit, inputs),
33+
Gate(var in1, "XOR", var in2) => Evaluate(in1, circuit, inputs) ^ Evaluate(in2, circuit, inputs),
34+
_ => throw new Exception(circuit[label].ToString()),
35+
};
36+
}
37+
}
38+
2339
public object PartTwo(string input) {
24-
var swaps = Fix(ParseRules(input.Split("\n\n")[1]));
25-
return string.Join(",", swaps.OrderBy(x => x));
40+
var circuit = Parse(input).circuit;
41+
return string.Join(",", Fix(circuit).OrderBy(label => label));
2642
}
2743

28-
// the rules should define a full adder for two 44 bit numbers
44+
// the circuit should define a full adder for two 44 bit numbers
2945
// this fixer is specific to my input.
30-
IEnumerable<string> Fix(List<Rule> rules) {
31-
var cin = Output(rules, "x00", "AND", "y00");
46+
IEnumerable<string> Fix(Circuit circuit) {
47+
var cin = Output(circuit, "x00", "AND", "y00");
3248
for (var i = 1; i < 45; i++) {
3349
var x = $"x{i:D2}";
3450
var y = $"y{i:D2}";
3551
var z = $"z{i:D2}";
3652

37-
var xor1 = Output(rules, x, "XOR", y);
38-
var and1 = Output(rules, x, "AND", y);
39-
40-
var and2 = Output(rules, cin, "AND", xor1);
41-
var xor2 = Output(rules, cin, "XOR", xor1);
53+
var xor1 = Output(circuit, x, "XOR", y);
54+
var and1 = Output(circuit, x, "AND", y);
55+
var xor2 = Output(circuit, cin, "XOR", xor1);
56+
var and2 = Output(circuit, cin, "AND", xor1);
4257

4358
if (xor2 == null && and2 == null) {
44-
return Swap(rules, xor1, and1);
59+
return SwapAndFix(circuit, xor1, and1);
4560
}
4661

47-
var carry = Output(rules, and1, "OR", and2);
62+
var carry = Output(circuit, and1, "OR", and2);
4863
if (xor2 != z) {
49-
return Swap(rules,z,xor2);
64+
return SwapAndFix(circuit, z, xor2);
5065
} else {
5166
cin = carry;
5267
}
5368
}
5469
return [];
5570
}
5671

57-
string Output(IEnumerable<Rule> rules, string x, string gate, string y) =>
58-
rules.SingleOrDefault(rule =>
59-
(rule.in1 == x && rule.kind == gate && rule.in2 == y) ||
60-
(rule.in1 == y && rule.kind == gate && rule.in2 == x)
61-
).output;
62-
63-
IEnumerable<string> Swap(List<Rule> rules, string out1, string out2) {
64-
rules = rules.Select(rule =>
65-
rule.output == out1 ? rule with {output = out2} :
66-
rule.output == out2 ? rule with {output = out1} :
67-
rule
68-
).ToList();
69-
70-
return Fix(rules).Concat([out1, out2]);
72+
IEnumerable<string> SwapAndFix(Circuit circuit, string out1, string out2) {
73+
(circuit[out1], circuit[out2]) = (circuit[out2], circuit[out1]);
74+
return Fix(circuit).Concat([out1, out2]);
7175
}
7276

73-
List<Rule> ParseRules(string input) => input
74-
.Split("\n")
75-
.Select(line => {
76-
var parts = line.Split(" ");
77-
return new Rule(in1: parts[0], in2: parts[2], kind: parts[1], output: parts[4]);
78-
})
79-
.ToList();
80-
Dictionary<string, Gate> Parse(string input) {
77+
string Output(Circuit circuit, string x, string kind, string y) =>
78+
circuit.SingleOrDefault(pair =>
79+
(pair.Value.in1 == x && pair.Value.kind == kind && pair.Value.in2 == y) ||
80+
(pair.Value.in1 == y && pair.Value.kind == kind && pair.Value.in2 == x)
81+
).Key;
8182

82-
var res = new Dictionary<string, Gate>();
83+
(Dictionary<string, int> inputs, Circuit circuit) Parse(string input) {
84+
var inputs = new Dictionary<string, int>();
85+
var circuit = new Circuit();
8386

8487
var blocks = input.Split("\n\n");
8588

8689
foreach (var line in blocks[0].Split("\n")) {
8790
var parts = line.Split(": ");
88-
res.Add(parts[0], () => int.Parse(parts[1]));
91+
inputs.Add(parts[0], int.Parse(parts[1]));
8992
}
9093

9194
foreach (var line in blocks[1].Split("\n")) {
9295
var parts = Regex.Matches(line, "[a-zA-z0-9]+").Select(m => m.Value).ToArray();
93-
Gate gate = (parts[0], parts[1], parts[2]) switch {
94-
(var in1, "AND", var in2) => () => res[in1]() & res[in2](),
95-
(var in1, "OR", var in2) => () => res[in1]() | res[in2](),
96-
(var in1, "XOR", var in2) => () => res[in1]() ^ res[in2](),
97-
_ => throw new Exception(),
98-
};
99-
res.Add(parts[3], gate);
96+
circuit.Add(parts[3], new Gate(in1: parts[0], kind: parts[1], in2: parts[2]));
10097
}
101-
return res;
98+
return (inputs, circuit);
10299
}
103100

104-
delegate int Gate();
105101
}

0 commit comments

Comments
 (0)