Last active
December 20, 2019 22:55
-
-
Save runarorama/2c6ce84b9754ca0d9521f3c8a30acf14 to your computer and use it in GitHub Desktop.
Advent of code 2019, day 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Pos.doc = [: Represents a position in memory :] | |
unique type Pos = Pos Nat | |
-- Lets us refer to the Pos pattern unqualified | |
use Pos Pos | |
Error.doc = [: This ability lets us fail with an error anywhere. :] | |
ability Error where | |
error : Text -> a | |
outOfBounds x = error ("Memory address out of bounds: " ++ Nat.toText x) | |
overflow = '(error "Memory overflow.") | |
Memory.doc = [: The ability to read, write, and dump the computer's memory. :] | |
ability Memory where | |
read : Pos -> Nat | |
write : Pos -> Nat -> () | |
dump : [Nat] | |
errors.doc = [: An error handler that returns the error as a value. :] | |
errors : Request {Error} v -> Either Text v | |
errors failure = | |
case failure of | |
{Error.error e -> _} -> Left e | |
{ a } -> Right a | |
access.doc = [: A handler for the @Memory effect that uses an immutable list. :] | |
use Memory read write dump | |
access : [Nat] -> Request {Memory} v ->{Error} v | |
access mem instruction = | |
case instruction of | |
{ read (Pos x) -> k} -> | |
v = List.at x mem | |
case v of | |
None -> outOfBounds x | |
Some v -> handle access mem in k v | |
{write (Pos x) v -> k} -> | |
mem' = if List.size mem > x then replace x v mem else outOfBounds x | |
handle access mem' in !k | |
{dump -> k} -> handle access mem in k mem | |
{ a } -> a | |
compute : Nat ->{Memory, Error} [Nat] | |
compute pc = | |
case List.drop pc dump of | |
opcode +: rest -> | |
case opcode of | |
99 -> dump | |
op -> | |
case rest of | |
[x,y,dest] ++ _ -> | |
f = case op of | |
1 -> (Nat.+) | |
2 -> (Nat.*) | |
_ -> error ("Unknown opcode " ++ Nat.toText op) | |
write (Pos dest) (f (read (Pos x)) (read (Pos y))) | |
_ -> !overflow | |
compute (pc + 4) | |
computer.doc = [: The actual computer. :] | |
computer : [Nat] -> Either Text [Nat] | |
computer memory = handle errors in handle access memory in compute 0 | |
test> computer.works = | |
check (computer [1,0,0,0,99] == Right [2,0,0,0,99]) ++ | |
check (computer [2,3,0,3,99] == Right [2,3,0,6,99]) ++ | |
check (computer [2,4,4,5,99,0] == Right [2,4,4,5,99,9801]) ++ | |
check (computer [1,1,1,4,99,5,6,0,99] == Right [30,1,1,4,2,5,6,0,99]) | |
runComputer noun verb = | |
handle errors in handle access puzzleInput in | |
write (Pos 1) noun | |
write (Pos 2) verb | |
compute 0 | |
part1 = runComputer 12 2 | |
puzzleInput = | |
[1,0,0,3 | |
,1,1,2,3 | |
,1,3,4,3 | |
,1,5,0,3 | |
,2,13,1,19 | |
,1,5,19,23 | |
,2,10,23,27 | |
,1,27,5,31 | |
,2,9,31,35 | |
,1,35,5,39 | |
,2,6,39,43 | |
,1,43,5,47 | |
,2,47,10,51 | |
,2,51,6,55 | |
,1,5,55,59 | |
,2,10,59,63 | |
,1,63,6,67 | |
,2,67,6,71 | |
,1,71,5,75 | |
,1,13,75,79 | |
,1,6,79,83 | |
,2,83,13,87 | |
,1,87,6,91 | |
,1,10,91,95 | |
,1,95,9,99 | |
,2,99,13,103 | |
,1,103,6,107 | |
,2,107,6,111 | |
,1,111,2,115 | |
,1,115,13,0 | |
,99 | |
,2,0,14,0 | |
] | |
-- In case you don't have this | |
Either.map f e = case e of | |
Right x -> Right (f x) | |
Left e -> Left e | |
> part1.answer = Either.map (List.at 0) part1 | |
> part2.answer = | |
go nounverb = | |
result = runComputer (nounverb / 100) (mod nounverb 100) | |
case result of | |
Right (19690720 +: _) -> Some nounverb | |
_ -> if nounverb == 0 then None else go (drop nounverb 1) | |
go 10000 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment