123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- use "collections"
- use "files"
- use "format"
- class Value
- let _addr: I64
- let _value: I64
- new create(__addr: I64, __value: I64) =>
- _addr = __addr
- _value = __value
- fun addr(): I64 => _addr
- fun value(): I64 => _value
- class Operands
- let _lhs: Value
- let _rhs: Value
- let _tgt: I64
- new create(__lhs: Value, __rhs: Value, __tgt: I64) =>
- _lhs = __lhs
- _rhs = __rhs
- _tgt = __tgt
- fun val1(): I64 => _lhs.value()
- fun val2(): I64 => _rhs.value()
- fun tgt(): USize => _tgt.usize()
- trait Error
- fun message(): String
- class OutOfBounds is Error
- let _loc: USize
- new create(loc: USize) => _loc = loc
- fun message(): String =>
- "Memory access out of bounds: " + Format.int[USize](_loc)
- class UnknownOperand is Error
- let _op: I64
- new create(op: I64) => _op = op
- fun message(): String =>
- "Unknown operand: " + Format.int[I64](_op)
- primitive Handler
- fun run(env: Env, result: (None | Error)) =>
- match result
- | None => None
- | let e: Error => env.err.print(e.message())
- end
- 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_value(addr_loc: USize): (Value | Error) =>
- let addr = try storage(addr_loc)? else return OutOfBounds(addr_loc) end
- let value = try storage(addr.usize())? else return OutOfBounds(addr.usize()) end
- Value(addr, value)
- fun ref get_op_data(): (Operands | Error) =>
- let lhs = match get_value(pc+1)
- | let v: Value => v
- | let e: Error => return e
- end
- let rhs = match get_value(pc+2)
- | let v: Value => v
- | let e: Error => return e
- end
- let tgt = try storage(pc+3)? else return OutOfBounds(pc+1) end
- Operands(lhs, rhs, tgt)
- fun ref do_add(): (None | Error) =>
- let data = match get_op_data()
- | let o: Operands => o
- | let e: Error => return e
- end
- try
- storage(data.tgt())? = data.val1() + data.val2()
- else
- return OutOfBounds(data.tgt())
- end
- pc = pc + 4
- None
- fun ref do_mul(): (None | Error) =>
- let data = match get_op_data()
- | let o: Operands => o
- | let e: Error => return e
- end
- try
- storage(data.tgt())? = data.val1() * data.val2()
- else
- return OutOfBounds(data.tgt())
- end
- pc = pc + 4
- None
- fun ref run(): (None | Error) =>
- try
- match storage(pc)?
- | 1 => do_add()
- | 2 => do_mul()
- | 99 => return None
- | let x: I64 => return UnknownOperand(x)
- end
- else
- return OutOfBounds(pc)
- end
- run()
- fun make_trial(a: I64, b: I64): Program ? =>
- var arr = storage.clone()
- arr(1)? = a
- arr(2)? = b
- Program(arr)
- fun ref run_trial(env: Env): Bool =>
- Handler.run(env, run())
- 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
|