advent-2021/7/solution.hs

47 lines
1.3 KiB
Haskell

import Data.List
import Data.List.Split
main :: IO ()
main = do
input <- readFile "7/input.txt"
let x = sort $ parse input
-- Problem 1
print $ f x
-- Problem 2
print $ g x
where
f = solve distance
g = solve triangle
-- | Split on comma and interpret each element as an integer
parse :: String -> [Int]
parse = map read . wordsBy (== ',')
-- | 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
solve f x = minimum $ map g (narrow x)
where
g t = sum $ map (f t) x
-- | 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
-- | 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
-- | Calculate the absolute distance between two numbers
distance :: Int -> Int -> Int
distance a b = abs (a - b)