2019-12-12 10:55:24 +01:00
import Data.List
2019-12-12 10:56:42 +01:00
import Data.List.Split
2019-12-12 07:49:36 +01:00
import Linear.V3
2019-12-12 13:23:54 +01:00
2019-12-12 10:55:24 +01:00
main :: IO ()
2019-12-12 07:49:36 +01:00
main = do
2019-12-12 10:56:42 +01:00
moons <- parseContent <$> readFile " input "
let velocity = replicate 4 [ 0 , 0 , 0 ]
print $ part1 ( toV3 moons , toV3 velocity )
print $ part2 ( moons , velocity )
2019-12-12 07:49:36 +01:00
2019-12-12 12:18:19 +01:00
parseContent :: String -> [ [ Int ] ]
parseContent = map ( map read . splitOn " , " ) . lines . removeJunk
where
removeJunk xs = [ x | x <- xs , x ` notElem ` " <>xyz= " ]
2019-12-12 07:49:36 +01:00
2019-12-12 10:55:24 +01:00
--I’m sure there is a better way to do this
toV3 :: [ [ Int ] ] -> [ V3 Int ]
2019-12-12 10:56:42 +01:00
toV3 = map ( \ [ x , y , z ] -> V3 x y z )
2019-12-12 07:49:36 +01:00
2019-12-12 12:18:19 +01:00
part1 :: ( [ V3 Int ] , [ V3 Int ] ) -> Int
part1 input = energy $ iterate step input !! 1000
2019-12-12 10:56:42 +01:00
where
2019-12-12 12:18:19 +01:00
energy ( x , y ) = sum $ zipWith ( * ) ( geten x ) ( geten y )
geten = map ( sum . abs )
2019-12-12 07:49:36 +01:00
2019-12-12 10:56:42 +01:00
step :: ( Num a , Eq a ) => ( [ a ] , [ a ] ) -> ( [ a ] , [ a ] )
step ( moons , vel ) = ( zipWith ( + ) moons newVel , newVel )
where
dVel = gravity moons
newVel = zipWith ( + ) vel dVel
gravity xs = [ sum [ signum $ x - y | x <- xs , y /= x ] | y <- xs ]
2019-12-12 07:49:36 +01:00
2019-12-12 12:18:19 +01:00
part2 :: ( Num a , Eq a ) => ( [ [ a ] ] , [ [ a ] ] ) -> Int
2019-12-12 13:23:54 +01:00
part2 ( moons , vel ) = foldr1 lcm periods
2019-12-12 10:56:42 +01:00
where
2019-12-12 12:18:19 +01:00
m = transpose moons
v = transpose vel
periods = zipWith ( curry findPeriod' ) m v
findPeriod' x = findPeriod x x 1
2019-12-12 10:55:24 +01:00
findPeriod :: ( Num a , Eq a ) => ( [ a ] , [ a ] ) -> ( [ a ] , [ a ] ) -> Int -> Int
2019-12-12 10:56:42 +01:00
findPeriod x a n =
if x' == a
then n
else findPeriod x' a ( n + 1 )
where
x' = step x