You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.6 KiB

import Data.List.Split
import Data.List
import Data.Char as Char
import Linear.V3
main = do
moons <- map createMoon <$> map getList <$> map cleanString <$> lines <$> getContents
--let newMoons = calculateMoons moons 1000
--let ernergy = sum $ map getErnergy newMoons
let xAxis = getXAxis moons
let loopx = findLoop xAxis xAxis 0
let yAxis = getYAxis moons
let loopy = findLoop yAxis yAxis 0
let zAxis = getZAxis moons
let loopz = findLoop zAxis zAxis 0
let result = foldl1 lcm [loopx, loopy, loopz]
--mapM putStrLn ( map show newMoons )
--putStrLn ( show ernergy)
putStrLn(show result)
data Moon = Moon{ position :: V3 Int
,velocity :: V3 Int
} deriving Show
getList :: String -> [Int]
getList = map read . splitOn ", "
cleanString :: String -> String
cleanString xs = xs \\ "<>xyz==="
createMoon :: [Int] -> Moon
createMoon [x,y,z] = Moon (V3 x y z) (V3 0 0 0)
stepGravity :: [Moon] -> [Moon]
stepGravity xs = map (\(p,v) -> Moon p v) $ zip (newPos) newVel
where newVel = zipWith (+) (getVel xs) (gravity $ getPos xs)
newPos = zipWith (+) (getPos xs) (newVel)
gravity :: (Num a, Eq a)=> [a] -> [a]
gravity xs = [sum [signum $ x-y | x<-xs, y/=x] | y<-xs]
calculateMoons :: [Moon] -> Int -> [Moon]
calculateMoons xs 0 = xs
calculateMoons xs n = calculateMoons (stepGravity xs) (n-1)
findLoop :: ([Int],[Int]) -> ([Int],[Int]) -> Int -> Int
findLoop pos start c
| pos /= start || c == 0 = findLoop (stepAxis pos) start (c+1)
| pos == start = c
stepAxis :: ([Int],[Int]) -> ([Int],[Int])
stepAxis (pos,vel) = (newPos, newVel)
where newVel = zipWith (+) (vel) (gravity pos)
newPos = zipWith (+) (pos) (newVel)
getPos :: [Moon] -> [V3 Int]
getPos xs = map(\x -> position x) xs
getVel :: [Moon] -> [V3 Int]
getVel xs = map(\x -> velocity x) xs
getErnergy :: Moon -> Int
getErnergy (Moon pos vel) = (sum $ abs pos) * (sum $ abs vel)
getXAxis :: [Moon] -> ([Int],[Int])
getXAxis xs = (pos,vel)
where pos = map(\x -> getX $ position x) xs
vel = map(\x -> getX $ velocity x) xs
getZAxis :: [Moon] -> ([Int],[Int])
getZAxis xs = (pos,vel)
where pos = map(\x -> getZ $ position x) xs
vel = map(\x -> getZ $ velocity x) xs
getYAxis :: [Moon] -> ([Int],[Int])
getYAxis xs = (pos,vel)
where pos = map(\x -> getY $ position x) xs
vel = map(\x -> getY $ velocity x) xs
getX :: V3 Int -> Int
getX (V3 x y z) = x
getY :: V3 Int -> Int
getY (V3 x y z) = y
getZ :: V3 Int -> Int
getZ (V3 x y z) = z