Day 8 solution
[?]
Jan 14, 2021, 12:58 AM
W7FIR7DH7GKAPUIL535JFW2XRP7UADFJHTFQAKPBRLPJZFBEJWPACDependencies
- [2]
B527MN66Solve day 1 for 2020
Change contents
- file addition: day8.hs[2.17]
{-# LANGUAGE LambdaCase #-}import Control.Applicativeimport Control.Monad.Stateimport Data.Charimport Data.Eitherimport Data.Maybeimport Data.List (intercalate)import Data.Monoidimport qualified Data.IntMap as IMimport qualified Data.Set as Simport System.Environmentdata Operation = ACC | JMP | NOP deriving (Eq,Show)pcIncrement :: Operation -> Int -> IntpcIncrement JMP i = ipcIncrement _ _ = 1accIncrement :: Operation -> Int -> IntaccIncrement ACC i = iaccIncrement _ _ = 0runBoot :: IM.IntMap (Operation,Int) -> [(Int,Int)]runBoot b = case IM.lookupMin b ofNothing -> []Just (pc0,_) -> go pc0 0wherego pc acc = case IM.lookup pc b ofNothing -> []Just (op,i) -> letpc' = pc + pcIncrement op iacc' = acc + accIncrement op iin (pc', acc') : go pc' acc'repairAttempts :: Alternative f =>IM.IntMap (Operation, Int) -> f (IM.IntMap (Operation, Int))repairAttempts = alterEach $ \(opc,i) -> case opc ofACC -> emptyNOP -> pure $ Just (JMP,i)JMP -> pure $ Just (NOP,i)alterEach :: Alternative f =>(a -> f (Maybe a)) -> IM.IntMap a -> f (IM.IntMap a)alterEach f m = getAlt $IM.foldMapWithKey (\k _ -> Alt $ IM.alterF (f . fromJust) k m) maccBeforeLoop :: [(Int,Int)] -> Maybe IntaccBeforeLoop = go (S.singleton 0) . ((0,0):) wherego v ((_,acc):r@((pc,_):_)) = either Just (flip go r) $ S.alterF (\p -> if p then Left acc else Right True) pc vgo _ _ = NothingaccOnComplete :: Int -> [(Int,Int)] -> Maybe IntaccOnComplete t = go S.empty wherego _ [] = Nothinggo _ [(pc,acc)]| pc == t = Just acc| otherwise = Nothinggo v ((pc,acc):r)| pc `S.member` v = Nothing| otherwise = go (S.insert pc v) ranyChar :: StateT String [] CharanyChar = StateT (\case[] -> [](a:r) -> [(a,r)])string :: String -> StateT String [] ()string [] = return ()string (a:r) = anyChar >>= \c -> if a == cthen string relse emptyopcode :: StateT String [] Operationopcode = (ACC <$ string "acc") <|>(JMP <$ string "jmp") <|>(NOP <$ string "nop")natural :: Num a => StateT String [] anatural = go 0 wherego acc = anyChar >>= \c -> if isDigit cthen letacc' = acc * 10 + fromIntegral (digitToInt c)in acc' `seq` return acc' <|> go acc'else emptyeos :: StateT String [] ()eos = StateT (\case[] -> [((),[])]_ -> [])neos :: StateT String [] ()neos = StateT (\case[] -> []_ -> [((),[])])line :: StateT String [] (Operation,Int)line = (,) <$>(opcode <* string " ") <*>(((id <$ string "+") <|> (negate <$ string "-")) <*>natural)sepBy :: Alternative m => m a -> m s -> m [a]sepBy a s = pure [] <|>((:) <$> a <*> many (s *> a))file :: StateT String [] (IM.IntMap (Operation,Int))file = (IM.fromList . zip [0..]) <$> sepBy line (string "\n") <* (pure () <|> void (string "\n"))main = do(part:fn:_) <- getArgs(b:_) <- evalStateT (file <* eos) <$> readFile fnprint $ case part of"1" -> fromJust $ accBeforeLoop $ runBoot b"2" -> letgc = accOnComplete $ IM.size bin head $ dob' <- repairAttempts bmaybeToList $ gc $ runBoot b'showOps :: IM.IntMap (Operation,Int) -> StringshowOps = intercalate "\n" . map (\(op,i) ->map toLower (show op) ++" " ++(if i < 0 then "-" else "+") ++show (abs i)) . IM.elems