Skip to content

Instantly share code, notes, and snippets.

@runarorama
Last active December 20, 2019 22:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save runarorama/2c6ce84b9754ca0d9521f3c8a30acf14 to your computer and use it in GitHub Desktop.
Save runarorama/2c6ce84b9754ca0d9521f3c8a30acf14 to your computer and use it in GitHub Desktop.
Advent of code 2019, day 2
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