{-# Language QuasiQuotes #-}
module Main where
import Advent.Format (format)
import Data.List (transpose)
main :: IO ()
IO ()
main =
do [([Char], [([Char], Integer)])]
input <- [format|2015 15 (%s: (%s %ld)&(, )%n)*|]
let stats :: [[Integer]]
stats = (([Char], [([Char], Integer)]) -> [Integer])
-> [([Char], [([Char], Integer)])] -> [[Integer]]
forall a b. (a -> b) -> [a] -> [b]
map ((([Char], Integer) -> Integer) -> [([Char], Integer)] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], Integer) -> Integer
forall a b. (a, b) -> b
snd ([([Char], Integer)] -> [Integer])
-> (([Char], [([Char], Integer)]) -> [([Char], Integer)])
-> ([Char], [([Char], Integer)])
-> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [([Char], Integer)]) -> [([Char], Integer)]
forall a b. (a, b) -> b
snd) [([Char], [([Char], Integer)])]
input
n :: Integer
n = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([([Char], [([Char], Integer)])] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [([Char], [([Char], Integer)])]
input)
possibilities :: [[Integer]]
possibilities = [[Integer]] -> [Integer] -> [Integer]
computeStats [[Integer]]
stats ([Integer] -> [Integer]) -> [[Integer]] -> [[Integer]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Integer -> Integer -> [[Integer]]
divisions Integer
n Integer
100
Integer -> IO ()
forall a. Show a => a -> IO ()
print ([Integer] -> Integer
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (([Integer] -> Integer) -> [[Integer]] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map [Integer] -> Integer
score [[Integer]]
possibilities))
Integer -> IO ()
forall a. Show a => a -> IO ()
print ([Integer] -> Integer
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [[Integer] -> Integer
score [Integer]
meal | [Integer]
meal <- [[Integer]]
possibilities, [Integer] -> Integer
forall a. HasCallStack => [a] -> a
last [Integer]
meal Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
500])
score ::
[Integer] ->
Integer
score :: [Integer] -> Integer
score = [Integer] -> Integer
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product ([Integer] -> Integer)
-> ([Integer] -> [Integer]) -> [Integer] -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Integer] -> [Integer]
forall a. HasCallStack => [a] -> [a]
init
computeStats ::
[[Integer]] ->
[Integer] ->
[Integer]
computeStats :: [[Integer]] -> [Integer] -> [Integer]
computeStats [[Integer]]
props [Integer]
divs
= ([Integer] -> Integer) -> [[Integer]] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map (Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max Integer
0 (Integer -> Integer)
-> ([Integer] -> Integer) -> [Integer] -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [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
$ [[Integer]] -> [[Integer]]
forall a. [[a]] -> [[a]]
transpose
([[Integer]] -> [[Integer]]) -> [[Integer]] -> [[Integer]]
forall a b. (a -> b) -> a -> b
$ (Integer -> [Integer] -> [Integer])
-> [Integer] -> [[Integer]] -> [[Integer]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ((Integer -> Integer) -> [Integer] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map ((Integer -> Integer) -> [Integer] -> [Integer])
-> (Integer -> Integer -> Integer)
-> Integer
-> [Integer]
-> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(*)) [Integer]
divs [[Integer]]
props
divisions ::
Integer ->
Integer ->
[[Integer]]
divisions :: Integer -> Integer -> [[Integer]]
divisions Integer
1 Integer
n = [[Integer
n]]
divisions Integer
cnt Integer
n =
do Integer
x <- [Integer
1..Integer
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
cntInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1]
[Integer]
xs <- Integer -> Integer -> [[Integer]]
divisions (Integer
cnt Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1) (Integer
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
x)
[Integer] -> [[Integer]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer
xInteger -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
:[Integer]
xs)