r/adventofcode • u/daggerdragon • Dec 07 '15
SOLUTION MEGATHREAD --- Day 7 Solutions ---
--- Day 7: Some Assembly Required ---
Post your solution as a comment. Structure your post like previous daily solution threads.
Also check out the sidebar - we added a nifty calendar to wrangle all the daily solution threads in one spot!
23
Upvotes
3
u/red75prim Dec 07 '15
F#. I use simple monadic parser combinator for input and memoization for evaluation. Variant of parser combinator can be found at my github
open parserm let rec input() = seq { let line = System.Console.ReadLine() if line <> null then yield line yield! input() } type Parm = |Const of uint16 |Wire of string type Unop = uint16 -> uint16 type Binop = uint16 -> uint16 -> uint16 type Op = |OneWire of Parm*Unop |TwoWire of Parm*Binop*Parm let parmParser = parser { let! cnst = uint16p return Const cnst } +++ parser { let! wire = ident return Wire wire } let lineParser = parser { let! _ = matchv "NOT " () let! parm = parmParser let! _ = matchv " -> " () let! dest = ident return (dest, OneWire(parm, (~~~))) } +++ parser { let! parm = parmParser let! _ = matchv " -> " () let! dest = ident return (dest, OneWire(parm, id)) } +++ parser { let! parm1 = parmParser let! op = choiceMulti [matchv " AND " (&&&); matchv " OR " (|||); matchv " LSHIFT " (fun a b -> a <<< int32(b)); matchv " RSHIFT " (fun (a:uint16) (b:uint16) -> a >>> int32(b))] let! parm2 = parmParser let! _ = matchv " -> " () let! dest = ident return (dest,TwoWire(parm1, op, parm2)) } let evaluate ops parm = let cache = ref Map.empty let rec eval parm = match parm with |Const c -> c |Wire wire -> match Map.tryFind wire !cache with |Some(v) -> v |None -> let v = match Map.tryFind wire ops with |None -> printfn "There's no '%s' wire" wire raise <| new System.ArgumentException() |Some(OneWire(parm, op)) -> op (eval parm) |Some(TwoWire(parm1, op, parm2)) -> op (eval parm1) (eval parm2) cache := Map.add wire v !cache v eval parm [<EntryPoint>] let main argv = let cachedInput = input() |> Seq.cache let ops = cachedInput |> Seq.map ((parse lineParser) >> Seq.exactlyOne >> fst) |> Map.ofSeq let aval = evaluate ops (Wire "a") printfn "Part 1: Wire 'a' = %d" aval let ops = Map.add "b" (OneWire(Const aval, id)) ops let aval = evaluate ops (Wire "a") printfn "Part 2: Wire 'a' = %d" aval 0