type Coord = (Integer, Integer) -- x, y
type Bounds = (Integer, Integer, Integer, Integer) -- minX, maxX, minY, maxY
data Particle = Particle {_position :: Coord, _velocity :: Coord} deriving (Eq, Show)
-type Swarm = [Particle]
-type Grid = S.Set Coord
+type Grid = [Particle]
+type Matrix = S.Set Coord
main :: IO ()
main = do
putStrLn $ showParticles final
print time
-part0 :: Swarm -> (Swarm, Int)
+part0 :: Grid -> (Grid, Int)
part0 particles = (snd $ last $ gridPairs, length gridPairs)
where gridPairs = findEnd particles
-runParticles :: Swarm -> [Swarm]
+runParticles :: Grid -> [Grid]
runParticles = iterate updateAll
-findEnd :: Swarm -> [(Swarm, Swarm)]
+findEnd :: Grid -> [(Grid, Grid)]
findEnd particles = takeWhile firstLarger gridPairs
where grids = runParticles particles
gridPairs = zip grids (drop 1 grids)
-boundsArea :: Swarm -> Integer
+boundsArea :: Grid -> Integer
boundsArea particles = (maxX - minX) * (maxY - minY)
where (minX, maxX, minY, maxY) = findBounds particles
-findBounds :: Swarm -> Bounds
+findBounds :: Grid -> Bounds
findBounds particles =
( minX -- small x edge
, maxX -- large x edge
(vx, vy) = _velocity particle
-updateAll :: Swarm -> Swarm
+updateAll :: Grid -> Grid
updateAll = map update
-showParticles :: Swarm -> String
+showParticles :: Grid -> String
showParticles particles = intercalate "\n" rows
where (minX, maxX, minY, maxY) = findBounds particles
- grid = S.fromList $ map _position particles
- rows = [showRow y minX maxX grid | y <- [minY..maxY] ]
+ swarm = S.fromList $ map _position particles
+ rows = [showRow y minX maxX swarm | y <- [minY..maxY] ]
-showCell :: Integer -> Integer -> Grid -> Char
+showCell :: Integer -> Integer -> Matrix -> Char
showCell x y grid
- | (x, y) `S.member` grid = '*'
- | otherwise = ' '
+ | (x, y) `S.member` grid = '\x2593'
+ | otherwise = '\x2591'
-showRow :: Integer -> Integer -> Integer -> Grid -> String
+showRow :: Integer -> Integer -> Integer -> Matrix -> String
showRow y minX maxX grid = [showCell x y grid | x <- [minX..maxX] ]
-- Parse the input file
particleP = particlify <$> positionP <*> velocityP
where particlify x v = Particle x v
-positionP = posPrefix *> pairP <* suffix
-velocityP = velPrefix *> pairP <* suffix
+positionP = between posPrefix suffix pairP
+velocityP = between velPrefix suffix pairP
pairP = (,) <$> signedInteger <* commaP <*> signedInteger
-successfulParse :: Text -> Swarm
+successfulParse :: Text -> Grid
successfulParse input =
case parse particleFileP "input" input of
Left _error -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
import qualified Text.Megaparsec.Char.Lexer as L
import qualified Control.Applicative as CA
-import qualified Data.Map.Strict as M
import qualified Data.Set as S
type Coord = (Integer, Integer) -- x, y
print time
-part1 particles
- | area' > area = showParticles particles
- | otherwise = part1 particles'
- where particles' = updateAll particles
- area = boundsArea particles
- area' = boundsArea particles'
+-- part1 particles
+-- | area' > area = showParticles particles
+-- | otherwise = part1 particles'
+-- where particles' = updateAll particles
+-- area = boundsArea particles
+-- area' = boundsArea particles'
+part2 :: Integer -> [Particle] -> (Integer, String)
part2 time particles
| area' > area = (time, showParticles particles)
| otherwise = part2 (time+1) particles'
showCell :: Integer -> Integer -> Grid -> Char
showCell x y grid
- | (x, y) `S.member` grid = '*'
- | otherwise = ' '
+ | (x, y) `S.member` grid = '\x2593'
+ | otherwise = '\x2591'
showRow :: Integer -> Integer -> Integer -> Grid -> String
showRow y minX maxX grid = [showCell x y grid | x <- [minX..maxX] ]
particleP = particlify <$> positionP <*> velocityP
where particlify x v = Particle x v
-positionP = posPrefix *> pairP <* suffix
-velocityP = velPrefix *> pairP <* suffix
+positionP = between posPrefix suffix pairP
+velocityP = between velPrefix suffix pairP
pairP = (,) <$> signedInteger <* commaP <*> signedInteger