adventofcode-2021/7/crabfuel.hs

55 lines
1.4 KiB
Haskell

import Data.List (nub)
import Parsing (splitByString)
main :: IO ()
main = do
input <- getContents
let
crabs = parseCrabs input
(putStrLn . show . solution1) crabs
(putStrLn . show . solution2) crabs
solution1 :: [Int] -> Int
solution1 = minFuel crabFuel1
solution2 :: [Int] -> Int
solution2 = minFuel crabFuel2
parseCrabs :: String -> [Int]
parseCrabs = (map read) . (splitByString ",")
minFuel :: (Int -> Int -> Int) -> [Int] -> Int
minFuel crabf crabs = minimum (map total positions)
where
uniqueCrabs = nub crabs
positions = [minimum uniqueCrabs..maximum uniqueCrabs]
total position = totalFuel crabf position crabs
totalFuel :: (Int -> Int -> Int) -> Int -> [Int] -> Int
totalFuel crabf position = sum . (map (crabf position))
crabFuel1 :: Int -> Int -> Int
crabFuel1 crab position = abs (crab - position)
crabFuel2 :: Int -> Int -> Int
crabFuel2 crab position =
-- Just the sum of 1..<distance from crab to position>
-- (using that Gauß-attributed sum)
end * (end + 1) `quot` 2
where
end :: Int
end = crabFuel1 crab position
-- Tests
testInput = "16,1,2,0,4,2,7,1,2,14"
parsedInput = parseCrabs testInput
test1 = solution1 parsedInput
test2 = solution2 parsedInput
testTotalFuel1 = totalFuel crabFuel1 2 parsedInput
testTotalFuel2 = totalFuel crabFuel1 1 parsedInput
testTotalFuel3 = totalFuel crabFuel1 3 parsedInput
testTotalFuel4 = totalFuel crabFuel1 10 parsedInput