# (io, w) = stdio w
# ls = read io
# ls = {l\\l<-ls}
- = one ls
+ = (one ls, two ls)
-instance == {#String} where
- (==) l r = and [l==r\\l<-:l & r<-:r]
+one = numOccupied o cell isOccupied ((==)0) ((<=)4)
+two = numOccupied o cell seeOccupied ((==)0) ((<=)5)
-one :: {#String} -> Int
-one ls = length [()\\r<-:cell ls, c<-:r | c == '#']
+isOccupied :: Int Int Int Int {#String} -> Bool
+isOccupied x y dx dy ls = seat (x+dx) (y+dy) ls == '#'
-cell :: !{#String} -> {#String}
-cell ls = let ls` = step ls in if (ls` == ls) ls (cell ls`)
+seeOccupied :: Int Int Int Int {#String} -> Bool
+seeOccupied x y dx dy ls = case seat (x+dx) (y+dy) ls of
+ '#' = True
+ 'L' = False
+ '-' = False
+ '.' = seeOccupied (x+dx) (y+dy) dx dy ls
-step :: !{#String} -> {#String}
-step ls = {{step` x y\\x<-[0..size ls.[0] - 1]}\\y<-[0..size ls - 1]}
+numOccupied :: {#String} -> Int
+numOccupied ls = length [()\\r<-:ls, c<-:r | c == '#']
+
+cell :: (Int Int Int Int {#String} -> Bool) (Int -> Bool) (Int -> Bool) {#String} -> {#String}
+cell lookfun live die ls
+ # ls` = {{step x y\\x<-[0..size ls.[0] - 1]}\\y<-[0..size ls - 1]}
+ = if (and [l==r\\l<-:ls` & r<-:ls]) ls (cell lookfun live die ls`)
where
- step` :: Int Int -> Char
- step` x y = case ls.[y,x] of
+ step x y = case ls.[y,x] of
'.' = '.'
- 'L' = if (occupied == 0) '#' 'L'
- '#' = if (occupied >= 4) 'L' '#'
+ 'L' = if (live numOccupied) '#' 'L'
+ '#' = if (die numOccupied) 'L' '#'
where
- occupied = length [()\\dx<-[-1..1], dy<-[-1..1] | not (dx == 0 && dy == 0) && not (empty (x+dx) (y+dy))]
- empty :: Int Int -> Bool
- empty x y
- | x < 0 || x >= size ls.[0] || y < 0 || y >= size ls = True
- = ls.[y,x] <> '#'
+ numOccupied = length [()\\dx<-[-1..1], dy<-[-1..1] | not (dx == 0 && dy == 0) && lookfun x y dx dy ls]
+
+seat :: Int Int {#String} -> Char
+seat x y ls
+ | x < 0 || x >= size ls.[0] || y < 0 || y >= size ls = '-'
+ = ls.[y,x]