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
You are viewing a single thread.
View all comments 3 points
*
Haskell
I should probably do something about the n2 loop in Somewhat 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]
1 point