|
@@ -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
|