Day 4: Restroom Redoubt
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Haskell
Spent a lot of time trying to find symmetric quadrants. In the end made an interactive visualization and found that a weird pattern appeared on iterations (27 + 101k) and (75 + 103k’). Put those congruences in an online Chinese remainder theorem calculator and go to the answer:
x ≡ 8006 (mod 101*103)
import Data.Bifunctor import Data.Char import qualified Data.Set as S import Data.Functor import Data.List import Control.Monad import Text.ParserCombinators.ReadP import Data.IORef bounds = (101, 103) parseInt :: ReadP Int parseInt = (*) <$> option 1 (char '-' $> (-1)) <*> (read <$> munch1 isDigit) parseTuple = (,) <$> parseInt <*> (char ',' *> parseInt) parseRow = (,) <$> (string "p=" *> parseTuple) <*> (string " v=" *> parseTuple) parse = fst . last . readP_to_S (endBy parseRow (char '\n')) move t (x, y) (vx, vy) = bimap (mod (x + vx * t)) (mod (y + vy * t)) bounds getQuadrant :: (Int, Int) -> Int getQuadrant (x, y) | x == mx || y == my = 0 | otherwise = case (x > mx, y > my) of (True, True) -> 1 (True, False) -> 2 (False, True) -> 3 (False, False) -> 4 where (mx, my) = bimap (`div` 2) (`div` 2) bounds step (x, y) (vx, vy) = (,(vx, vy)) $ bimap (mod (x + vx)) (mod (y + vy)) bounds main = do p <- parse <$> readFile "input14" print . product . fmap length . group . sort . filter (/=0) . fmap (getQuadrant . uncurry (move 100)) $ p let l = iterate (fmap (uncurry step)) p current <- newIORef 0 actions <- lines <$> getContents forM_ actions $ \a -> do case a of "" -> modifyIORef current (+1) "+" -> modifyIORef current (+1) "-" -> modifyIORef current (subtract 1) n -> writeIORef current (read n) pos <- readIORef current putStr "\ESC[2J" -- clear screen print pos visualize $ fst <$> l !! pos visualize :: [(Int, Int)] -> IO () visualize pos = do let p = S.fromList pos forM_ [1..(snd bounds)] $ \y -> do forM_ [1..(fst bounds)] $ \x -> do putChar $ if S.member (x, y) p then '*' else '.' putChar '\n'