55 lines
1.4 KiB
Haskell
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
|