{-# Language QuasiQuotes #-}
{-|
Module      : Main
Description : Day 1 solution
Copyright   : (c) Eric Mertens, 2019
License     : ISC
Maintainer  : emertens@gmail.com

<https://adventofcode.com/2019/day/1>

Compute fuel costs for a rocket.

-}
module Main (main) where

import Advent.Format (format)

-- | >>> :main
-- 3188480
-- 4779847
main :: IO ()
IO ()
main =
  do [Integer]
inp <- [format|2019 1 (%lu%n)*|]
     Integer -> IO ()
forall a. Show a => a -> IO ()
print ([Integer] -> Integer
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Integer -> Integer) -> [Integer] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Integer
fuelCost          [Integer]
inp))
     Integer -> IO ()
forall a. Show a => a -> IO ()
print ([Integer] -> Integer
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Integer -> Integer) -> [Integer] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Integer
recursiveFuelCost [Integer]
inp))

-- | Compute fuel cost given a mass.
--
-- >>> fuelCost 12
-- 2
-- >>> fuelCost 14
-- 2
-- >>> fuelCost 1969
-- 654
-- >>> fuelCost 100756
-- 33583
fuelCost :: Integer -> Integer
fuelCost :: Integer -> Integer
fuelCost Integer
x = Integer
x Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
3 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
2

-- | Compute fuel cost given a mass.
--
-- >>> recursiveFuelCost 14
-- 2
-- >>> recursiveFuelCost 1969
-- 966
-- >>> recursiveFuelCost 100756
-- 50346
recursiveFuelCost :: Integer -> Integer
recursiveFuelCost :: Integer -> Integer
recursiveFuelCost = [Integer] -> Integer
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Integer] -> Integer)
-> (Integer -> [Integer]) -> Integer -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Bool) -> [Integer] -> [Integer]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0) ([Integer] -> [Integer])
-> (Integer -> [Integer]) -> Integer -> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Integer] -> [Integer]
forall a. HasCallStack => [a] -> [a]
tail ([Integer] -> [Integer])
-> (Integer -> [Integer]) -> Integer -> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer) -> Integer -> [Integer]
forall a. (a -> a) -> a -> [a]
iterate Integer -> Integer
fuelCost