import Data.List as List import Debug.Trace as Trace main = do content <- getContents let layers = lines content let indexlayers = map(\x-> mapInd(\x y -> (y,x)) x ) layers let points = concat (mapInd(\x y->map(\x->((fst x,y),snd x))x) $ indexlayers) let asteroids = (map fst (filter(\(x,y) -> y == '#' ) points)) let maximum = List.maximum(map(\x-> length(getViews (changeCoordinate (asteroids) x))) (asteroids)) let station = head $ map(\x-> fst x) $ filter(\x-> snd x == maximum )(map(\x-> (x,( length(getViews (changeCoordinate asteroids x))))) (asteroids)) let changedAsteroids = changeCoordinate asteroids station let sortedAsteroids = sortBy sortDistance changedAsteroids let views = getViews sortedAsteroids let sortedViews = sortBy sortDegree views let destroyed = getDestroyOrder sortedAsteroids [] let destroyNormal = map (\(a,b)-> (((fst station) + a),((snd station) + b))) destroyed putStrLn(show maximum) putStrLn(show station) putStrLn(show views) putStrLn(show sortedViews) putStrLn(show $ map degree destroyed) putStrLn(show $ destroyNormal) putStrLn(show $ destroyNormal!!199) mapInd :: (a -> Int -> b) -> [a] -> [b] mapInd f l = zipWith f l [0..] getDestroyOrder :: [(Int,Int)] -> [(Int,Int)] -> [(Int,Int)] getDestroyOrder ast out | length ast > 0 = do let views = getViews ast let sortedViews = sortBy sortDegree views let newout = out ++ sortedViews let newast = ast \\ sortedViews getDestroyOrder newast newout | otherwise = out sortDistance ((a,b)) ((a2,b2)) | abs(a) + abs(b) > abs(a2) + abs(b2) = GT | abs(a) + abs(b) < abs(a2) + abs(b2) = LT | abs(a) + abs(b) == abs(a2) + abs(b2) = EQ sortDegree a b | degree a < degree b = GT | degree a > degree b = LT | degree a == degree b = EQ getViews :: [(Int,Int)] -> [(Int,Int)] getViews xs = foldl getView [] xs changeCoordinate :: [(Int, Int)] -> (Int,Int) -> [(Int,Int)] changeCoordinate xs (a,b) = (delete (0,0)( (map(\(x,y) -> ((x-a),(y-b)))xs))) getView :: [(Int,Int)] -> (Int,Int) -> [(Int,Int)] getView xs y |notElem (reduce y) (map reduce xs) = xs ++ [y] |otherwise = xs reduce :: (Int,Int) -> (Int,Int) reduce (a,b) = ((div a (gcd a b)),(div b (gcd a b))) degree :: (Int,Int) -> Double degree (a,b) = do let x = fromIntegral a let y = fromIntegral b atan2 x (y)