--- /dev/null
+-- import Debug.Trace
+
+import Data.Text (Text)
+-- import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+
+import Data.Attoparsec.Text hiding (take)
+-- import Data.Attoparsec.Combinator
+-- import Control.Applicative
+-- import Control.Applicative.Combinators
+
+import qualified Data.Set as S
+import Linear (V2(..), (^+^))
+-- import Data.Semigroup
+-- import Data.Monoid
+
+
+data Direction = NE | E | SE | SW | W | NW
+ deriving (Show, Eq, Enum, Bounded)
+
+type Tile = V2 Int -- x, y
+type Grid = S.Set Tile
+
+instance Semigroup Int where
+ (<>) = (+)
+
+instance Monoid Int where
+ mempty = 0
+
+main :: IO ()
+main =
+ do text <- TIO.readFile "data/advent24.txt"
+ let walks = successfulParse text
+ let grid0 = foldr flipTile S.empty walks
+ print $ part1 grid0
+ print $ part2 grid0
+
+part1 grid0 = S.size grid0
+part2 grid0 = S.size $ (iterate update grid0) !! 100
+
+delta :: Direction -> Tile
+delta NE = V2 1 0
+delta E = V2 0 1
+delta SE = V2 -1 1
+delta SW = V2 -1 0
+delta W = V2 0 -1
+delta NW = V2 1 -1
+
+
+flipTile :: Tile -> Grid -> Grid
+flipTile tile tiles
+ | tile `S.member` tiles = S.delete tile tiles
+ | otherwise = S.insert tile tiles
+
+
+neighbourSpaces :: Tile -> Grid
+neighbourSpaces here = S.fromList $ map nbrSpace [minBound .. maxBound] -- [NE .. NW]
+ where nbrSpace d = here ^+^ (delta d)
+
+countOccupiedNeighbours :: Tile -> Grid -> Int
+countOccupiedNeighbours cell grid =
+ S.size $ S.intersection grid $ neighbourSpaces cell
+
+tileBecomesWhite :: Grid -> Tile -> Bool
+tileBecomesWhite grid cell = black && ((nNbrs == 0) || (nNbrs > 2))
+ where black = cell `S.member` grid
+ nNbrs = countOccupiedNeighbours cell grid
+
+tileBecomesBlack :: Grid -> Tile -> Bool
+tileBecomesBlack grid cell = white && (nNbrs == 2)
+ where white = cell `S.notMember` grid
+ nNbrs = countOccupiedNeighbours cell grid
+
+update :: Grid -> Grid
+update grid = (grid `S.union` newBlacks) `S.difference` newWhites
+ where neighbours = (S.foldr mergeNeighbours S.empty grid) `S.difference` grid
+ mergeNeighbours cell acc = S.union acc $ neighbourSpaces cell
+ newWhites = S.filter (tileBecomesWhite grid) grid
+ newBlacks = S.filter (tileBecomesBlack grid) neighbours
+
+
+-- Parse the input file
+
+tilesP = tileP `sepBy` endOfLine
+tileP = foldMap delta <$> many1 stepP
+
+stepP = choice [neP, nwP, seP, swP, eP, wP]
+
+neP = "ne" *> pure NE
+nwP = "nw" *> pure NW
+seP = "se" *> pure SE
+swP = "sw" *> pure SW
+eP = "e" *> pure E
+wP = "w" *> pure W
+
+-- successfulParse :: Text -> [Tile]
+successfulParse input =
+ case parseOnly tilesP input of
+ Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
+ Right tiles -> tiles