123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- use "collections"
- use "files"
- use "format"
- interface Value
- fun value(): I64
- class Position
- 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 Immediate
- let _value: I64
- new create(__value: I64) =>
- _value = __value
- 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 val OutOfBounds is Error
- let _loc: USize
- new val create(loc: USize) => _loc = loc
- fun message(): String =>
- "Memory access out of bounds: " + Format.int[USize](_loc)
- class val UnknownOperand is Error
- let _op: I64
- new val 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
- var errors: Array[Error val]
- new create(s: Array[I64]) =>
- storage = s
- errors = Array[Error val]()
- 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
- errors = Array[Error val]()
- 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 read_storage(addr: USize): I64 ? =>
- try
- storage(addr)?
- else
- errors.push(OutOfBounds(addr))
- error
- end
- fun ref write_storage(addr: USize, value: I64) ? =>
- try
- storage(addr)? = value
- else
- errors.push(OutOfBounds(addr))
- error
- end
- fun ref get_immediate(addr_loc: USize): Immediate ? =>
- let value = read_storage(addr_loc)?
- Immediate(value)
- fun ref get_position(addr_loc: USize): Position ? =>
- let addr = read_storage(addr_loc)?
- let value = read_storage(addr.usize())?
- Position(addr, value)
- fun ref get_op_data(): Operands ? =>
- let lhs = get_position(pc+1)?
- let rhs = get_position(pc+2)?
- let tgt = read_storage(pc+3)?
- Operands(lhs, rhs, tgt)
- fun ref do_add() ? =>
- let data = get_op_data()?
- write_storage(data.tgt(), data.val1() + data.val2())?
- pc = pc + 4
- None
- fun ref do_mul() ? =>
- let data = get_op_data()?
- write_storage(data.tgt(), data.val1() * data.val2())?
- pc = pc + 4
- None
- fun ref run() ? =>
- match read_storage(pc)?
- | 1 => do_add()?
- | 2 => do_mul()?
- | 99 => return None
- | let x: I64 =>
- errors.push(UnknownOperand(x))
- error
- 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 =>
- try
- run()?
- else
- for err in errors.values() do
- env.out.print(err.message())
- end
- end
- 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
|