Browse Source

Add second exercise

Getty Ritter 4 years ago
parent
commit
5c3b1b9bea
2 changed files with 103 additions and 0 deletions
  1. 2 0
      02/.gitignore
  2. 101 0
      02/main.pony

+ 2 - 0
02/.gitignore

@@ -0,0 +1,2 @@
+02
+input.txt

+ 101 - 0
02/main.pony

@@ -0,0 +1,101 @@
+use "collections"
+use "files"
+use "format"
+
+class Program
+  var storage: Array[I64]
+  var pc: USize = 0
+
+  new create(s: Array[I64]) =>
+    storage = s
+
+  new from_file(file: File) =>
+    storage = Array[I64](0)
+    for line in file.lines() do
+      for chunk in line.split(",").values() do
+        try
+          storage.push(chunk.i64()?)
+        end
+      end
+    end
+
+  fun print(env: Env) =>
+    env.out.write("[")
+    for x in storage.values() do
+      env.out.write(Format.int[I64](x))
+      env.out.write(" ")
+    end
+    env.out.print("]")
+
+  fun ref get_op_data(env: Env): (I64, I64, I64, I64, I64) ? =>
+    let addr1 = storage(pc+1)?
+    let addr2 = storage(pc+2)?
+    let tgt = storage(pc+3)?
+
+    let val1 = storage(addr1.usize())?
+    let val2 = storage(addr2.usize())?
+    (addr1, val1, addr2, val2, tgt)
+
+  fun ref do_add(env: Env) ? =>
+    (let x1, let op1, let x2, let op2, let tgt) = get_op_data(env)?
+    storage.update(tgt.usize(), op1 + op2)?
+    pc = pc + 4
+    run(env)
+
+  fun ref do_mul(env: Env) ? =>
+    (let x1, let op1, let x2, let op2, let tgt) = get_op_data(env)?
+    storage.update(tgt.usize(), op1 * op2)?
+    pc = pc + 4
+    run(env)
+
+  fun ref run(env: Env) =>
+    try
+      match storage(pc)?
+        | 1 => do_add(env)?
+        | 2 => do_mul(env)?
+        | 99 => None
+        | let x: I64 => env.err.print("Unknown opcode " + Format.int[I64](x))
+      end
+    else
+      env.err.print("PC " + Format.int[USize](pc) + " out of bounds")
+  end
+
+  fun make_trial(a: I64, b: I64): Program ? =>
+    var arr = storage.clone()
+    arr.update(1, a)?
+    arr.update(2, b)?
+    Program(arr)
+
+  fun ref run_trial(env: Env): Bool =>
+    run(env)
+    try
+      storage(0)? == 19690720
+    else
+      false
+    end
+
+actor Main
+  new create(env: Env) =>
+    let caps = recover val FileCaps.>set(FileRead).>set(FileStat) end
+
+    try
+      with
+        file = OpenFile(FilePath(env.root as AmbientAuth, "input.txt", caps)?) as File
+      do
+        let program = Program.from_file(file)
+        program.print(env)
+        for a in Range[I64](0, 100) do
+          for b in Range[I64](0, 100) do
+            let trial = program.make_trial(a, b)?
+            if trial.run_trial(env) then
+              env.out.print("noun=" + Format.int[I64](a) + ", verb=" + Format.int[I64](b))
+              env.out.print("result=" + Format.int[I64]((a * 100) + b))
+            end
+          end
+        end
+      end
+    else
+      // if something failed, then print an error message of some kind and exit
+      env.err.print("Couldn't read expected file `input.txt'")
+      env.exitcode(99)
+    end