Day 14: 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
You are viewing a single thread.
View all comments 1 point
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'