DEV Community

Discussion on: Advent of Code 2020 Solution Megathread - Day 24: Lobby Layout

Collapse
 
bgaster profile image
Benedict Gaster • Edited

Well back to Haskell today, although not 100% sure this was a good choice. The problem being that updating an ever growing floor map in part 2 meant that after about 50 iterations it starts to get pretty slow. So much so I had to add some prints, inititally, to check it was actually making progress. However, it was and it kindly got to the right answer. Another issue was that as I'd choosen to use a map that used the position as a key, which for me were complex numbers, then i had to convert to string and back, as Haskell won't allow "real" numbers to have order defined that is needed for maps, at least I could not resolve that issue. Ahh well it still worked out pretty nicely, if not a little on the slow side.

replace :: Char -> String -> String -> String
replace c w [] = [] 
replace c w (x:xs) | c == x    = w ++ replace c w xs
                   | otherwise = x : replace c w xs

dir = M.fromList [("nw", (-1) :+ 1), ("ne", 1 :+ 1), 
                  ("w", (-2) :+ 0), ("e", 2 :+ 0), 
                  ("sw", (-1) :+ (-1)), ("se", 1 :+ (-1))]

task1 floor [] = floor
task1 floor (x:xs) = task1 (uFloor x floor) xs 
    where
        uFloor :: String -> M.Map String Int -> M.Map String Int
        uFloor ts = M.insertWith (\_ o -> 1 - o) (show $ tile ts) 1 
        tile = sum . map (fromJust . flip M.lookup dir) . filter (/= "") . splitOn " "

task2 0 !floor = floor
task2 n !floor = task2 (n-1) (aux floor)
    where
        aux floor = let keys = map read (M.keys floor)
                        bs = union keys [ x | f <- keys,
                                            x <- neighbours f  ]
                        kd = map (\k -> (show k, sum (map (\k -> M.findWithDefault 0 (show k) floor) (neighbours k)))) bs
                      in foldr (\(k,s) floor ->  M.insert k (check k s floor) floor) floor kd

        check k s floor | s == 2 || (M.findWithDefault 0 k floor == 1 && s == 1) = 1
                        | otherwise = 0
        neighbours l = map (l+) (M.elems dir)

main = do
    is <- readFile "day24_input" <&> replace 'e' "e " 
                                 <&> replace 'w' "w "
                                 <&> lines
    let floor = task1 M.empty is
    print (sum floor)
    print (sum $ task2 100 floor)
Enter fullscreen mode Exit fullscreen mode