advent-2021/7/solution.hs

46 lines
1.5 KiB
Haskell

import Data.List.Split
main :: IO ()
main = do
input <- readFile "7/input.txt"
let x = parse input
-- Problem 1
print $ f x
-- Problem 2
print $ g x
where
f x = solve distance [ minimum x .. maximum x ] x
g x | length x >= 100 = solve triangle [ sum x `div` length x ] x
| otherwise = solve triangle [ minimum x .. maximum x ] x
-- NOTE for part 2 (`g`):
-- Just testing against the mean value of `x` only gives accurate results if the
-- sample is large enough. Here, lists of size 100 or larger are deemed "large enough",
-- but that's pretty arbitrary.
-- | 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 possible target positions
-> [Int] -- ^ List of initial positions
-> Int
solve f a x = minimum $ map g a
where
g t = sum $ map (f t) x
-- | 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)