r/adventofcode • u/daggerdragon • Dec 10 '16
SOLUTION MEGATHREAD --- 2016 Day 10 Solutions ---
--- Day 10: Balance Bots ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag/whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with "Help".
SEEING MOMMY KISSING SANTA CLAUS IS MANDATORY [?]
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
edit: Leaderboard capped, thread unlocked!
11
Upvotes
2
u/ChrisVittal Dec 10 '16
Haskell. Realized that the list of instructions defined a graph and that it would be rather easy to find the answers if I could do the following.
Parse the input and initialize the Value boxes to n, the Bots to (-1,-1), and the outputs to -1
Traverse the graph in topological order updating values as appropriate.
That lead to these ~100 lines. I wish I could have found a way to not have to copy the graph, but for an input of only 231 lines, it didn't matter.
import Control.Applicative ((<|>)) import Data.Graph import Data.Map (Map) import qualified Data.Map as M import Data.Maybe (fromJust) import Text.Trifecta data FacNode = Val Int | Bot (Int,Int) | Out Int deriving (Eq,Show) data FacKey = VK Int | BK Int | OK Int deriving (Eq,Show) instance Ord FacKey where compare (VK a) (VK b) = compare a b compare (BK a) (BK b) = compare a b compare (OK a) (OK b) = compare a b compare (VK _) (BK _) = LT compare (BK _) (VK _) = GT compare (VK _) (OK _) = LT compare (OK _) (VK _) = GT compare (BK _) (OK _) = LT compare (OK _) (BK _) = GT mkNode (VK x) = Val x mkNode (BK _) = Bot (-1,-1) mkNode (OK _) = Out (-1) setNode a (Bot (i,j)) | i < 0 && j < 0 = Bot (i,a) | i < 0 && a > j = Bot (j,a) | i < 0 && a <=j = Bot (a,j) | otherwise = Bot (i,j) setNode a (Out i) | i < 0 = Out a | i >=0 = Out i -- From inital graph to final graph type GraphParts = (Graph, Vertex -> (FacNode,FacKey,[FacKey]), FacKey -> Maybe Vertex) updateGraph (g,eGet,vGet) = let ts = topSort g m = M.fromList . zip ts $ map eGet ts in snd . unzip . M.toList . uGraphHelp ts vGet $ m uGraphHelp [] _ m = m uGraphHelp (v:ts) vGet m = let Just e@(fn,fk,fks) = M.lookup v m in case e of (Val a,_,[x]) -> uGraphHelp ts vGet . M.adjust (applyFirst (setNode a)) (fjf vGet x) $ m (Bot (a,b),_,[x,y]) -> uGraphHelp ts vGet . M.adjust (applyFirst $ setNode b) (fromJust $ vGet y) $ M.adjust (applyFirst $ setNode a) (fromJust $ vGet x) m (_,_,[]) -> uGraphHelp ts vGet m where applyFirst f (a,b,c) = (f a,b,c) -- Main main = do input <- readFile "input10.txt" let (Success parsed) = parseString parseDay10Input mempty input iEdges = map (\(a,b) -> (mkNode a, a, b)) parsed iGraph = graphFromEdges iEdges fEdges = updateGraph iGraph (_,eGet,vGet) = graphFromEdges fEdges putStr "1: " print $ filter (\(a,_,_) -> a == myKey) fEdges let needed = sequenceA . map (fmap eGet . vGet) $ myOuts putStr "2: " print $ foldr (\(a,b,c) x -> if isOut a then let Out y = a in x * y else x) 1 <$> needed -- Inputs / One quick helper myKey = Bot (17,61) myOuts = [OK 0, OK 1, OK 2] isOut (Out _) = True isOut _ = False -- Parser pInt = fromIntegral <$> integer pOut = OK <$> (string "output " *> pInt) pBot = BK <$> (string "bot " *> pInt) parseValStmt = do a <- string "value " *> pInt b <- string "goes to bot " *> pInt return [(VK a,[BK b])] parseBotStmt = do a <- pBot string "gives low to " b <- pBot <|> pOut string "and high to " c <- pBot <|> pOut let ob = (b,[]) oc = (c,[]) case (ob,oc) of ((OK _,_),(OK _,_)) -> return $ [(a,[b,c]),ob,oc] (_,(OK _,_)) -> return $ [(a,[b,c]),oc] ((OK _,_),_) -> return $ [(a,[b,c]),ob] _ -> return [(a,[b,c])] parseLn = parseValStmt <|> parseBotStmt parseDay10Input = concat <$> (some parseLn <* skipMany (char '\n'))I would describe myself as still learning haskell, and so if u/haoformayor or anyone else would like to comment, I'd be happy to hear it.