Day 20: Race Condition
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
I should probably do something about the n2 loop inSomewhat better (0.575s). Can’t shake the feeling that I’m missing an obvious closed-form solution, though.findCheats
, but it’s fast enough for now. Besides, my brain has melted.import Control.Monad import Data.List import Data.Map (Map) import Data.Map qualified as Map import Data.Maybe import Data.Set qualified as Set type Pos = (Int, Int) readInput :: String -> Map Pos Char readInput s = Map.fromList [((i, j), c) | (i, l) <- zip [0 ..] (lines s), (j, c) <- zip [0 ..] l] solveMaze :: Map Pos Char -> Maybe [Pos] solveMaze maze = listToMaybe $ go [] start where walls = Map.keysSet $ Map.filter (== '#') maze Just [start, end] = traverse (\c -> fst <$> find ((== c) . snd) (Map.assocs maze)) ['S', 'E'] go h p@(i, j) | p == end = return [end] | otherwise = do p' <- [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)] guard $ p' `notElem` h guard $ p' `Set.notMember` walls (p :) <$> go [p] p' dist (i1, j1) (i2, j2) = abs (i2 - i1) + abs (j2 - j1) findCheats :: [Pos] -> Int -> Int -> [((Pos, Pos), Int)] findCheats path minScore maxLen = do (t2, end) <- zip [0 ..] path (t1, start) <- zip [0 .. t2 - minScore] path let len = dist start end score = t2 - t1 - len guard $ len <= maxLen guard $ score >= minScore return ((start, end), score) main = do Just path <- solveMaze . readInput <$> readFile "input20" mapM_ (print . length . findCheats path 100) [2, 20]
Ah, the number of potential start points is much smaller than the length of the path. I guess a map from position to offset would do it, but I’m not sure it’s really worth it.