-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday7_1.d
125 lines (116 loc) · 3.79 KB
/
day7_1.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module day7_1;
import io = std.stdio, std.file, std.algorithm, std.range, std.typecons;
import std.conv, std.math, std.string : splitLines;
enum RunState { Running, Paused, Finished };
struct Program {
int id;
int[] mem;
int ip = 0;
RunState runState = RunState.Running;
int delegate(ref Program me) getInput;
void delegate(ref Program me, int output) doOutput;
}
int getValue(ref Program p, int numOperand) {
int mode;
if (numOperand == 1)
mode = p.mem[p.ip] / 100 % 10;
else if (numOperand == 2)
mode = p.mem[p.ip] / 1000 % 10;
else if (numOperand == 3)
mode = p.mem[p.ip] / 10000 % 10;
if (mode != 1 && mode != 0)
throw new Exception("Error in mode");
return (mode == 1) ? p.mem[p.ip + numOperand] : p.mem[p.mem[p.ip + numOperand]];
}
alias Runner = int function(ref Program);
immutable Runner[int] runners;
shared static this() {
import std.exception: assumeUnique;
Runner[int] temp;
temp[1] = (ref Program p) {
p.mem[p.mem[p.ip + 3]] = getValue(p, 1) + getValue(p, 2);
return p.ip + 4;
};
temp[2] = (ref Program p) {
p.mem[p.mem[p.ip + 3]] = getValue(p, 1) * getValue(p, 2);
return p.ip + 4;
};
temp[3] = (ref Program p) {
int input = p.getInput(p);
p.mem[p.mem[p.ip + 1]] = input;
return p.ip + 2;
};
temp[4] = (ref Program p) {
p.doOutput(p, getValue(p, 1));
return p.ip + 2;
};
temp[5] = (ref Program p) {
return (getValue(p, 1) != 0) ? getValue(p, 2) : (p.ip + 3);
};
temp[6] = (ref Program p) {
return (getValue(p, 1) == 0) ? getValue(p, 2) : (p.ip + 3);
};
temp[7] = (ref Program p) {
p.mem[p.mem[p.ip + 3]] = (getValue(p, 1) < getValue(p,2)) ? 1 : 0;
return p.ip + 4;
};
temp[8] = (ref Program p) {
p.mem[p.mem[p.ip + 3]] = (getValue(p, 1) == getValue(p,2 )) ? 1 : 0;
return p.ip + 4;
};
temp[99] = (ref Program p) {
p.runState = RunState.Finished;
return p.ip;
};
runners = assumeUnique(temp);
}
void runProgram(ref Program p) {
while(p.runState == RunState.Running) {
int opcode = p.mem[p.ip] % 100;
p.ip = runners[opcode](p);
}
}
int runSystem_1(int[] programCode, int[] initialInputs) {
const numPrograms = initialInputs.length;
auto programs = new Program[numPrograms];
auto givenInitial = new bool[numPrograms];
int inOutChannel = 0;
foreach(i, ref p; programs) {
// Initialize program p
p.id = i.to!int;
p.mem = programCode.dup;
// Initialize the program's input/output callbacks to read/write through the "channel"
// which is really a simple integer, since we run them all sequentially anyway..,
p.getInput = (ref p) {
if (givenInitial[p.id])
return inOutChannel;
else {
givenInitial[p.id] = true;
return initialInputs[p.id];
}
};
p.doOutput = (ref p, output) {
inOutChannel = output;
// Pause this program after outputting, so the next one could pick it up as input and continue
p.runState = RunState.Paused;
};
}
// Main runner
foreach(ref p; programs) {
p.runState = RunState.Running;
p.runProgram;
if (p.runState == RunState.Finished)
break;
}
return inOutChannel;
}
void main() {
int[] a = io.stdin.byLineCopy.array[0].split(",").map!(to!int).array;
int[] inputs = iota(0, 5).array;
int[] allOutputs;
do {
allOutputs ~= runSystem_1(a, inputs);
// DLANG: I couldn't figure out how to work with permutations(), I used nextPermutation instead
} while (inputs.nextPermutation);
io.writeln(allOutputs.maxElement);
}