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