Files
aoc/haskellAoC/src/Y2019/Day10.hs
2020-12-03 10:22:27 +01:00

56 lines
2.1 KiB
Haskell

module Y2019.Day10 (day10) where
import Data.List
import Geo.Vector
import Geo.Point
parseLine :: Int -> [Char] -> [Int]
parseLine xp ('#':cs) = xp:(parseLine (xp + 1) cs)
parseLine xp (_:cs) = parseLine (xp + 1) cs
parseLine _ [] = []
parseInput :: Int -> [String] -> [Point]
parseInput yp (l:ls) = (map convertToPoint $ parseLine 0 l) ++ parseInput (yp + 1) ls
where convertToPoint xp = Point (fromIntegral xp) (fromIntegral yp)
parseInput _ [] = []
getDirVectors :: Point -> [Point] -> [Vector]
getDirVectors src (dest:dests) = computedVect:(getDirVectors src dests)
where computedVect = roundVecAtN 5 $ directionalVectorFromPoint (dest `sub` src)
getDirVectors _ [] = []
getVectorAndDistPerPoint :: [Point] -> Point -> [(Point, Double, Double)]
getVectorAndDistPerPoint (dest:dests) src = (dest, computedVect, distance):nextEntries
where computedVect = vec2angle $ directionalVectorFromPoint diffPt
distance = roundN 5 $ sqrt $ ((Geo.Point.x diffPt) ^ 2) + ((Geo.Point.y diffPt) ^ 2)
diffPt = dest `sub` src
nextEntries = getVectorAndDistPerPoint dests src
getVectorAndDistPerPoint [] _ = []
asteroidSorting :: (Point, Double, Double) -> (Point, Double, Double) -> Ordering
asteroidSorting (_, angle1, dist1) (_, angle2, dist2)
| angle1 > angle2 = GT
| angle1 < angle2 = LT
| dist1 > dist2 = GT
| dist1 < dist2 = LT
| otherwise = EQ
getLaserOrder :: [[Point]] -> [Point]
getLaserOrder ((p:[]):xs) = p:(getLaserOrder xs)
getLaserOrder ((p:ps):xs) = p:(getLaserOrder (xs ++ [ps]))
getLaserOrder [] = []
day10 :: [String] -> (String, String)
day10 input = (part1, part2)
where asteroids = parseInput 0 input
p1 = maximumBy (\(_, a) (_, b) -> compare a b) $ map countFn asteroids
countFn pt = (pt, (length $ nub $ getDirVectors pt asteroids) - 1)
p2 = getLaserOrder $
map (\m -> map (\(p, _, _) -> p) m) $
groupBy (\(_, v1, _) (_, v2, _) -> v1 == v2) $
sortBy asteroidSorting $
getVectorAndDistPerPoint asteroids $
fst p1
part1 = show $ p1
part2 = show $ p2 !! 200