this repo has no description
1module Lib
2 ( parseParticles
3 , closestToZeroOverXSteps
4 , stepParticles
5 , removeCollisions
6 ) where
7
8import Data.List.Split (splitOn)
9import Data.List
10
11data Particle = Particle
12 { pos :: (Int, Int, Int)
13 , vel :: (Int, Int, Int)
14 , acc :: (Int, Int, Int)
15 } deriving (Eq, Show)
16
17parseParticles :: [String] -> [Particle]
18parseParticles = map parseParticle
19
20stepParticles :: [Particle] -> [Particle]
21stepParticles = map stepParticle
22
23closestToZeroOverXSteps :: Int -> [Particle] -> Int
24closestToZeroOverXSteps steps = go 0 []
25 where getMostOccurring = head . maximumBy (\x y -> compare (length x) (length y)) . group . sort
26 go :: Int -> [Int] -> [Particle] -> Int
27 go step maxes particles
28 | step == steps = getMostOccurring maxes
29 | otherwise = go (step + 1) (closestToZero particles : maxes) (stepParticles particles)
30
31removeCollisions :: [Particle] -> [Particle]
32removeCollisions = concat . filter (\g -> length g == 1) . groupBy collidesWith
33
34collidesWith :: Particle -> Particle -> Bool
35collidesWith Particle { pos = p1 }
36 Particle { pos = p2 }
37 = p1 == p2
38
39closestToZero :: [Particle] -> Int
40closestToZero [] = -1
41closestToZero (p:ps) = go (0, distanceToZero p) 1 ps
42 where go :: (Int, Int) -> Int -> [Particle] -> Int
43 go (i, _) _ [] = i
44 go (i, d) ci (p':ps')
45 | distanceToZero p' < d = go (ci, distanceToZero p') (ci + 1) ps'
46 | otherwise = go (i, d) (ci + 1) ps'
47
48distanceToZero :: Particle -> Int
49distanceToZero Particle { pos = (x, y, z) } = abs x + abs y + abs z
50
51stepParticle :: Particle -> Particle
52stepParticle Particle { pos = (px, py, pz)
53 , vel = (vx, vy, vz)
54 , acc = (ax, ay, az)
55 } =
56 Particle { pos = (px + (vx + ax), py + (vy + ay), pz + (vz + az))
57 , vel = (vx + ax, vy + ay, vz + az)
58 , acc = (ax, ay, az) }
59
60parseParticle :: String -> Particle
61parseParticle str =
62 let parts = splitOn ", " str
63 p = parseXYZ $ parts !! 0
64 v = parseXYZ $ parts !! 1
65 a = parseXYZ $ parts !! 2
66 in Particle { pos = p, vel = v, acc = a }
67
68parseXYZ :: String -> (Int, Int, Int)
69parseXYZ str =
70 let parts = map strToInt . splitOn "," . last . splitOn "=<" $ init str
71 in (parts !! 0, parts !! 1, parts !! 2)
72
73strToInt :: String -> Int
74strToInt s = (read s :: Int)