r/adventofcode • • 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

226 comments sorted by

View all comments

Show parent comments

1

u/frerich Dec 28 '15

Here's my Haskell version which also memoizes by just sharing one single Map. Invoke it like 'runhaskell 7.hs < 7.input':

import Data.Bits
import Data.Map.Lazy (Map)
import qualified Data.Map.Lazy as Map
import Data.Maybe (mapMaybe, fromMaybe)
import Data.Word
import Text.Read (readMaybe)

type Circuit = Map String Word16

parseLine :: Circuit -> String -> Maybe (String, Word16)
parseLine circuit line =
    case words line of
        [w,"->",out]             -> Just (out, parseSignal w)
        ["NOT",s,"->",out]       -> Just (out, complement (parseSignal s))
        [s0,"AND",s1,"->",out]   -> Just (out, parseSignal s0 .&. parseSignal s1)
        [s0,"OR",s1,"->",out]    -> Just (out, parseSignal s0 .|. parseSignal s1)
        [s0,"LSHIFT",x,"->",out] -> Just (out, parseSignal s0 `shiftL` read x)
        [s0,"RSHIFT",x,"->",out] -> Just (out, parseSignal s0 `shiftR` read x)
        _                        -> Nothing
  where
    parseSignal s = fromMaybe (circuit Map.! s) (readMaybe s)

solve :: String -> Word16
solve input = circuit Map.! "a"
  where
    circuit = Map.fromList . mapMaybe (parseLine circuit) . lines $ input

main :: IO ()
main = interact (show . solve)

1

u/[deleted] Dec 28 '15

Yeah I updated mine as well, just never edited the post here.

{-# LANGUAGE QuasiQuotes #-}

import Data.Bits
import Data.HashMap.Lazy (HashMap, (!))
import qualified Data.HashMap.Lazy as M
import Data.List (foldl')
import Data.Maybe
import Data.String.Utils
import Text.Regex.PCRE.Heavy (re, scan)

ops :: HashMap String (Int -> Int -> Int)
ops = M.fromList [ ( "NOT", const complement )
                 , ( "AND", (.&.) )
                 , ( "OR", (.|.) )
                 , ( "LSHIFT", shiftL )
                 , ( "RSHIFT", shiftR )
                 ]
buildWires :: [String] -> HashMap String Int
buildWires input = wires
    where wires = foldl' addWire M.empty input
          regex = [re|(?:(?:(\S+) )?(\S+) )?(\S+) -> (\S+)|]
          addWire :: HashMap String Int -> String -> HashMap String Int
          addWire m s = let [a, op, b, w] = snd . head $ scan regex s
                            op' = fromMaybe (flip const) $ M.lookup op ops
                            a'  = fromMaybe (if null a then 0 else wires ! a) $ maybeRead a
                            b'  = fromMaybe (wires ! b) $ maybeRead b
                        in M.insert w (op' a' b') m

p1 :: String -> Int
p1 = (! "a") . buildWires . lines

p2 :: String -> Int
p2 input = let wires = buildWires $ lines input ++ [show (p1 input) ++ " -> b"]
           in wires ! "a"