# HG changeset patch # User Jordi GutiƩrrez Hermoso # Date 1513658103 18000 # Node ID 5cf02601cd14422995572e51b188c7a14f81932b # Parent 4e7e7835f1dbcbb7a4589a61ec7309168d35ae10 day 18 diff --git a/2017/day18.d b/2017/day18.d new file mode 100644 --- /dev/null +++ b/2017/day18.d @@ -0,0 +1,92 @@ +import std.stdio; +import std.array: array; +import std.string: split; +import std.conv: to, ConvException; +import std.datetime: msecs; +import std.concurrency; + +void runProgram(immutable string[] opcodes, ulong pid, Tid otherProg) { + // Connect the two threads + if (otherProg == ownerTid) { + otherProg = receiveOnly!Tid(); + } else { + send(otherProg, thisTid()); + } + + long ip = 0; + long[char] regs = ['p': pid]; + long sent = 0; + + while(0 <= ip && ip < opcodes.length) { + auto opcode = opcodes[ip].split; + auto op = opcode[0]; + auto reg = opcode[1][0]; + long val = 0; + if (opcode.length > 2) { + try { + val = to!long(opcode[2]); + } + catch(ConvException){ + val = regs.get(opcode[2][0], 0); + } + } + switch(op) { + case "snd": + send(otherProg, regs.get(reg, 0)); + sent++; + goto default; + case "rcv": + if (!receiveTimeout(100.msecs, (long val) {regs[reg] = val;})) { + goto done; + } + goto default; + case "set": + regs[reg] = val; + goto default; + case "add": + regs[reg] = regs.get(reg, 0) + val; + goto default; + case "mul": + regs[reg] = regs.get(reg, 0) * val; + goto default; + case "mod": + regs[reg] = regs.get(reg, 0) % val; + goto default; + case "jgz": + long cmp; + try { + cmp = to!long(opcode[1]); + } + catch(ConvException) { + cmp = regs.get(reg, 0); + } + if (cmp > 0) { + ip += val; + break; + } + goto default; + default: + ip++; + } + } + + // We're done, dad! + done: + send(ownerTid, thisTid, sent); +} + +void main(string[] args) { + immutable auto opcodes = File(args[1]).byLineCopy.array.idup; + auto tid1 = spawn(&runProgram, opcodes, 0, thisTid); + auto tid2 = spawn(&runProgram, opcodes, 1, tid1); + + // Wait for both children to let us know they're done. + auto done1 = receiveOnly!(Tid, long); + auto done2 = receiveOnly!(Tid, long); + if (done1[0] == tid2) { + writeln(done1[1]); + } + else { + writeln(done2[1]); + } +}