Day 4: Ceres Search
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
import Control.Arrow
import Data.Array.Unboxed
import Data.List
type Pos = (Int, Int)
type Board = Array Pos Char
data Dir = N | NE | E | SE | S | SW | W | NW
target = "XMAS"
parse s = listArray ((1, 1), (n, m)) [l !! i !! j | i <- [0 .. n - 1], j <- [0 .. m - 1]]
where
l = lines s
(n, m) = (length $ head l, length l)
move N = first pred
move S = first succ
move E = second pred
move W = second succ
move NW = move N . move W
move SW = move S . move W
move NE = move N . move E
move SE = move S . move E
check :: Board -> Pos -> Int -> Dir -> Bool
check b p i d =
i >= length target
|| ( inRange (bounds b) p
&& (b ! p) == (target !! i)
&& check b (move d p) (succ i) d
)
checkAllDirs :: Board -> Pos -> Int
checkAllDirs b p = length . filter (check b p 0) $ [N, NE, E, SE, S, SW, W, NW]
check2 :: Board -> Pos -> Bool
check2 b p =
all (inRange (bounds b)) moves && ((b ! p) == 'A') && ("SSMM" `elem` rotations)
where
rotations = rots $ (b !) <$> moves
moves = flip move p <$> [NE, SE, SW, NW]
rots xs = init $ zipWith (++) (tails xs) (inits xs)
part1 b = sum $ checkAllDirs b <$> indices b
part2 b = length . filter (check2 b) $ indices b
main = getContents >>= print . (part1 &&& part2) . parse