2021-12-07 15:23:29 +01:00
|
|
|
import Data.List
|
2021-12-07 10:16:41 +01:00
|
|
|
import Data.List.Split
|
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = do
|
|
|
|
input <- readFile "7/input.txt"
|
2021-12-07 15:23:29 +01:00
|
|
|
let x = sort $ parse input
|
2021-12-07 10:16:41 +01:00
|
|
|
-- Problem 1
|
|
|
|
print $ f x
|
|
|
|
-- Problem 2
|
|
|
|
print $ g x
|
|
|
|
where
|
2021-12-07 15:23:29 +01:00
|
|
|
f = solve distance
|
|
|
|
g = solve triangle
|
2021-12-07 13:29:48 +01:00
|
|
|
|
|
|
|
-- | Split on comma and interpret each element as an integer
|
2021-12-07 10:16:41 +01:00
|
|
|
parse :: String -> [Int]
|
|
|
|
parse = map read . wordsBy (== ',')
|
|
|
|
|
2021-12-07 13:29:48 +01:00
|
|
|
-- | Solve the problem by finding the minimum of a list of integers, where
|
|
|
|
-- | each element is the total amount of fuel needed for each crab to reach
|
|
|
|
-- | that position.
|
|
|
|
solve :: (Int -> Int -> Int) -- ^ Fuel calculation to get between two points
|
|
|
|
-> [Int] -- ^ List of initial positions
|
|
|
|
-> Int
|
2021-12-07 15:23:29 +01:00
|
|
|
solve f x = minimum $ map g (narrow x)
|
2021-12-07 13:29:48 +01:00
|
|
|
where
|
|
|
|
g t = sum $ map (f t) x
|
2021-12-07 10:16:41 +01:00
|
|
|
|
2021-12-07 15:23:29 +01:00
|
|
|
-- | Get a slice of numbers around the mean in order to narrow the
|
|
|
|
-- | range of possible best positions to search.
|
|
|
|
narrow :: [Int] -> [Int]
|
|
|
|
narrow x = [ m - n .. m + n ]
|
|
|
|
where m = sum x `div` length x
|
|
|
|
n = 5
|
|
|
|
|
2021-12-07 13:29:48 +01:00
|
|
|
-- | Calculate the fuel usage based on the triangle number of the distance
|
|
|
|
-- | between the two numbers.
|
|
|
|
triangle :: Int -> Int -> Int
|
|
|
|
triangle a b = tri $ distance a b
|
|
|
|
where
|
|
|
|
tri n = n * (n + 1) `div` 2 -- Calculate nth triangle number
|
2021-12-07 10:16:41 +01:00
|
|
|
|
2021-12-07 13:29:48 +01:00
|
|
|
-- | Calculate the absolute distance between two numbers
|
2021-12-07 10:16:41 +01:00
|
|
|
distance :: Int -> Int -> Int
|
2021-12-07 13:29:48 +01:00
|
|
|
distance a b = abs (a - b)
|