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
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 |
|
|
|
|
|
|