Day 6: Guard Gallivant

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

  • lwhjp@lemmy.sdf.org
    link
    fedilink
    arrow-up
    5
    ·
    edit-2
    22 days ago

    Haskell

    This was a fun one! Infinite loops, performance concerns and so on. Part 2 could be made a bit faster with a recursive approach (I think), but this is good enough for me. Lost quite a bit of time with an incorrect walk function that passed the test data and part 1 but not part 2.

    import Data.Array.Unboxed (UArray)
    import Data.Array.Unboxed qualified as Array
    import Data.List
    import Data.Maybe
    import Data.Set (Set)
    import Data.Set qualified as Set
    
    readInput :: String -> UArray (Int, Int) Char
    readInput s =
      let rows = lines s
       in Array.listArray ((1, 1), (length rows, length $ head rows)) $ concat rows
    
    startPos = fst . fromJust . find ((== '^') . snd) . Array.assocs
    
    walk grid = go (startPos grid) (-1, 0)
      where
        go pos@(i, j) dir@(di, dj) =
          (pos, dir)
            : let pos' = (i + di, j + dj)
               in if Array.inRange (Array.bounds grid) pos'
                    then case grid Array.! pos' of
                      '#' -> go pos (dj, -di)
                      _ -> go pos' dir
                    else []
    
    path = Set.fromList . map fst . walk
    
    part1 = Set.size . path
    
    part2 grid = Set.size $ Set.filter (isLoop . walk . addO) $ Set.delete (startPos grid) $ path grid
      where
        addO pos = grid Array.// [(pos, '#')]
        isLoop xs = or $ zipWith Set.member xs $ scanl' (flip Set.insert) Set.empty xs
    
    main = do
      input <- readInput <$> readFile "input06"
      print $ part1 input
      print $ part2 input