Browse Source

Move conway to common/

main
Xiretza 1 year ago
parent
commit
d35b079fb4
Signed by: xiretza
GPG Key ID: 17B78226F7139993
  1. 28
      common/Conway.hs
  2. 19
      day17/day17.hs

28
common/Conway.hs

@ -0,0 +1,28 @@
module Conway
( Index(..)
, update
)
where
import Data.List
import qualified Data.Vector.Sized as V
import Data.Map (Map)
import qualified Data.Map as M
import Data.Set (Set)
import qualified Data.Set as S
class Index i where
neighbours :: i -> [i]
addIndex :: i -> i -> i
counts :: Ord a => [a] -> Map a Int
counts = M.fromList . map (\xs -> (head xs, length xs)) . group . sort
neighbourCounts :: (Index i, Ord i) => Set i -> Map i Int
neighbourCounts = counts . concatMap neighbours . S.elems
update :: (Index i, Ord i) => (Int -> Bool) -> (Int -> Bool) -> Set i -> Set i
update create destroy old = M.keysSet $ M.filterWithKey shouldLive $ M.fromSet (flip (M.findWithDefault 0) nCounts) indices
where nCounts = neighbourCounts old
indices = S.union old $ M.keysSet nCounts
shouldLive ix n = if S.notMember ix old then create n else not $ destroy n

19
day17/day17.hs

@ -3,35 +3,18 @@
module Day17 where
import AoC
import Conway
import Data.List
import Data.Vector.Sized (Vector)
import qualified Data.Vector.Sized as V
import Data.Map (Map)
import qualified Data.Map as M
import Data.Set (Set)
import qualified Data.Set as S
class Index i where
neighbours :: i -> [i]
addIndex :: i -> i -> i
instance (Num a, Eq a) => Index (Vector n a) where
neighbours i = filter (/= i) . V.mapM (flip map [-1, 0, 1] . (+)) $ i
addIndex = V.zipWith (+)
counts :: Ord a => [a] -> Map a Int
counts = M.fromList . map (\xs -> (head xs, length xs)) . group . sort
neighbourCounts :: (Index i, Ord i) => Set i -> Map i Int
neighbourCounts = counts . concatMap neighbours . S.elems
update :: (Index i, Ord i) => (Int -> Bool) -> (Int -> Bool) -> Set i -> Set i
update create destroy old = M.keysSet $ M.filterWithKey shouldLive $ M.fromSet (flip (M.findWithDefault 0) nCounts) indices
where nCounts = neighbourCounts old
indices = S.union old $ M.keysSet nCounts
shouldLive ix n = if S.notMember ix old then create n else not $ destroy n
run6 :: (Index i, Ord i) => Set i -> Int
run6 = S.size . (!! 6) . iterate (update (==3) (`notElem` [2, 3]))

Loading…
Cancel
Save