data Seat = Occupied | Empty
data Board =
B { table :: M.Map (Int, Int) Seat
, getWidth :: Int
, getHeight :: Int
}
newtype Direction = D (Int, Int)
(!?) = (M.!?)
concat
[([disp (tbl !? (x,y)) | x <- [0..width-1]] ++ "\n") | y <- [0..height-1]]
where tbl = table board
width = getWidth board
height = getHeight board
disp Nothing = '.'
disp (Just Occupied) = '#'
disp (Just Empty) = 'L'
putStr . display
let
rows = lines ss
height = length rows
width = length $ head rows
annotated = join $ zipWith (\y -> zipWith (\x s -> ((x,y), s)) [0..]) [0..] rows
asList = map (second $ const Empty) $ filter ((== 'L') . snd) annotated
tbl = M.fromList asList
in
B tbl width height
if x < 0 || x >= width || y < 0 || y >= height
then False
else case M.lookup next tbl of
Just Occupied -> True
Just Empty -> False
Nothing -> seesOccupied board next dir
where tbl = table board
width = getWidth board
height = getHeight board
next = (x+xOffs, y+yOffs)
board { table = M.mapWithKey go tbl}
where
tbl = table board
go loc status =
let visible = length $ filter (seesOccupied board loc) directions
in case status of
Occupied -> if visible >= 5 then Empty else Occupied
Empty -> if visible == 0 then Occupied else Empty
map D $ half ++ ((negate *** negate) <$> half)
where half = [(1,0),(0,1),(1,1),(1,-1)]
if x' == x then x' else fix f x'
where x' = f x
(parse <$>) . readFile
do
board <- readBoard s
let equilibrium = fix step board
print $ M.foldr (+) 0 $ M.map numSeated $ table equilibrium
return ()
where numSeated Occupied = 1
numSeated Empty = 0
solve "input.txt"