|
1 | | -{-# LANGUAGE FlexibleContexts #-} |
| 1 | +-- module AOC2017.Day20 (day20a, day20b) where |
| 2 | +module AOC2017.Day20 where |
2 | 3 |
|
3 | | -module AOC2017.Day20 (day20a, day20b) where |
| 4 | +import AOC2017.Types (Challenge) |
| 5 | +import AOC2017.Util (scanlT) |
| 6 | +import Data.Char (isDigit) |
| 7 | +import Data.Foldable (toList) |
| 8 | +import Data.List (find) |
| 9 | +import Data.List.Split (splitOn) |
| 10 | +import Data.Maybe (fromJust) |
| 11 | +import qualified Data.Map as M |
| 12 | +import qualified Data.Set as S |
| 13 | +import qualified Data.Vector as V |
| 14 | +import qualified Linear as L |
4 | 15 |
|
5 | | -import AOC2017.Types (Challenge) |
6 | | -import Control.Applicative (liftA2) |
7 | | -import Control.Monad (mfilter) |
8 | | -import Data.Char (isDigit) |
9 | | -import Data.Foldable (toList) |
10 | | -import Data.List |
11 | | -import Data.List.Split (splitOn) |
12 | | -import Data.Maybe (fromJust) |
13 | | -import qualified Data.Map as M |
14 | | -import qualified Data.Set as S |
15 | | -import qualified Data.Vector as V |
16 | | -import qualified Linear as L |
| 16 | +type Point = L.V3 Int |
17 | 17 |
|
18 | | -data S=S { _sPos :: !(V.Vector (Maybe (L.V3Int))) |
19 | | - , _sVel :: !(V.Vector (Maybe (L.V3Int))) |
20 | | - , _sAcc :: !(V.Vector (Maybe (L.V3Int))) |
21 | | - } |
22 | | - deriving Show |
| 18 | +data Particlea=P { _pAcc :: !a |
| 19 | + , _pVel :: !a |
| 20 | + , _pPos :: !a |
| 21 | + } |
| 22 | + deriving (Functor, Foldable, Traversable, Show, Eq, Ord) |
23 | 23 |
|
24 | | -step::S->S |
25 | | -step s@S{..} = s { _sPos = p, _sVel = v } |
26 | | -where |
27 | | - [_,v,p] =scanl1 ((V.zipWith. liftA2) (+)) [_sAcc, _sVel, _sPos] |
| 24 | +typeSystem= [ParticlePoint] |
| 25 | + |
| 26 | +step::Numa=>Particlea->Particlea |
| 27 | +step = scanlT (+)0 |
28 | 28 |
|
29 | | -collide :: S -> S |
30 | | -collide s@S{..} = s { _sPos = mfilter (`S.notMember` collisions) <$> _sPos } |
| 29 | +collide :: System -> System |
| 30 | +collide s0 = filter ((`S.notMember` collisions) . _pPos) s0 |
31 | 31 | where
|
| 32 | + collisions :: S.Set Point |
32 | 33 | collisions = M.keysSet . M.filter @Int (> 1)
|
33 | | - . M.fromListWith (+) . fmap (,1) |
34 | | - $ foldMap toList _sPos |
| 34 | + . M.fromListWith (+) |
| 35 | + . map ((,1) . _pPos) |
| 36 | + $ toList s0 |
35 | 37 |
|
36 | | -norm :: L.V3Int -> Int |
| 38 | +norm :: Point -> Int |
37 | 39 | norm = sum . fmap abs
|
38 | 40 |
|
39 | 41 | day20a :: Challenge
|
40 | | -day20a = show . V.minIndex |
41 | | - . (fmap . fmap . fmap) norm |
42 | | - . (\case S r v a -> V.zipWith3 L.V3 a v r) |
| 42 | +day20a = show . V.minIndex . V.fromList |
| 43 | + . (map . fmap) norm |
43 | 44 | . parse
|
44 | 45 |
|
45 | 46 | day20b :: Challenge
|
46 | 47 | day20b = show . length . fromJust . find stop
|
47 | | - . map (foldMap toList . _sPos) |
48 | | - . iterate (collide . step) |
| 48 | + . (map .map) (norm . _pPos) |
| 49 | + . iterate (collide . mapstep) |
49 | 50 | . parse
|
50 | 51 | where
|
51 | | - -- assumes there will be at least one particule left |
52 | | - stop = (> 1000) . minimum . map norm |
| 52 | + stop = (> 1000) . minimum |
53 | 53 |
|
54 | | -parse :: String -> S |
55 | | -parse = (\case L.V3 r v a -> S r v a) |
56 | | - . traverse (fmap Just . parseLine) |
57 | | - . V.fromList . lines |
58 | | - |
59 | | -parseLine :: String -> L.V3 (L.V3 Int) |
60 | | -parseLine (map(read.filter numChar).splitOn","->[pX,pY,pZ,vX,vY,vZ,aX,aY,aZ]) |
61 | | - = L.V3 (L.V3 pX pY pZ) (L.V3 vX vY vZ) (L.V3 aX aY aZ) |
62 | | -parseLine _ = error "No parse" |
| 54 | +parse :: String -> System |
| 55 | +parse = map parseLine . lines |
| 56 | + where |
| 57 | + parseLine :: String -> Particle Point |
| 58 | + parseLine (map(read.filter numChar).splitOn","->[pX,pY,pZ,vX,vY,vZ,aX,aY,aZ]) |
| 59 | + = P { _pAcc = L.V3 aX aY aZ |
| 60 | + , _pVel = L.V3 vX vY vZ |
| 61 | + , _pPos = L.V3 pX pY pZ |
| 62 | + } |
| 63 | + parseLine _ = error "No parse" |
63 | 64 |
|
64 | 65 | numChar :: Char -> Bool
|
65 | 66 | numChar c = isDigit c || c == '-'
|
0 commit comments