this post was submitted on 06 Dec 2024
26 points (96.4% liked)

Advent Of Code

987 readers
4 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 1 year ago
MODERATORS
 

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

you are viewing a single comment's thread
view the rest of the comments
[โ€“] [email protected] 4 points 3 weeks ago* (last edited 3 weeks 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