changeset 23:5cf02601cd14

day 18
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 18 Dec 2017 23:35:03 -0500
parents 4e7e7835f1db
children 776d882c78b8
files 2017/day18.d
diffstat 1 files changed, 92 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
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]);
+  }
+}