-
Notifications
You must be signed in to change notification settings - Fork 0
/
day07_logic_gates.d
92 lines (80 loc) · 2.21 KB
/
day07_logic_gates.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/+ dub.sdl:
name "aoc07"
+/
import std.typecons : Tuple;
import std.variant : Algebraic;
alias Input = Algebraic!(string, ushort);
alias Wire = Algebraic!(Input, Tuple!(bool, Input), Tuple!(string, Input, Input));
pure Input parseInput(string s) {
import std.conv : ConvException, to;
try {
return Input(to!ushort(s));
} catch (ConvException e) {
return Input(s);
}
}
ushort value(const Wire[string] circuit, string wire, ushort[string] cache) {
import std.variant : visit;
if (wire in cache) {
return cache[wire];
}
auto input = delegate ushort(Input i) {
return i.visit!(
(string s) => value(circuit, s, cache),
(ushort v) => v,
);
};
return cache[wire] = circuit[wire].visit!(
(Input i) => input(i),
// https://dlang.org/changelog/2.078.0.html#fix16997 ???
(Tuple!(bool, Input) unop) => cast(ushort)((~cast(int)(input(unop[1])))),
delegate ushort(Tuple!(string, Input, Input) binop) {
ushort v1 = input(binop[1]);
ushort v2 = input(binop[2]);
switch (binop[0]) {
case "AND":
return v1 & v2;
case "OR":
return v1 | v2;
case "LSHIFT":
return cast(ushort)(v1 << v2);
case "RSHIFT":
return v1 >> v2;
default:
throw new Exception("Unknown command " ~ binop[0]);
}
},
);
}
void main(string[] args) {
import std.array : split;
import std.file : slurp;
import std.stdio : writeln;
import std.typecons : tuple;
const lines = slurp!(string)(args.length <= 1 ? "/dev/stdin" : args[1], "%s");
Wire[string] wires;
foreach (string line; lines) {
auto splits = line.split();
switch (splits.length) {
case 3:
wires[splits[2]] = parseInput(splits[0]);
break;
case 4:
if (splits[0] != "NOT") {
throw new Exception("Unknown command " ~ line);
}
wires[splits[3]] = tuple(true, parseInput(splits[1]));
break;
case 5:
wires[splits[4]] = tuple(splits[1], parseInput(splits[0]), parseInput(splits[2]));
break;
default:
throw new Exception("Unknown command " ~ line);
}
}
auto run = () => value(wires, "a", ["": 0]);
ushort a = run();
writeln(a);
wires["b"] = Input(a);
writeln(run());
}