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