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

<https://adventofcode.com/2023/day/4>

We get a list of the winning numbers and out numbers
and have to figure out how many points we got and then
using a recursive card winning system count up how many
cards we played.

>>> :{
:main +
"Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3:  1 21 53 59 44 | 69 82 63 72 16 21 14  1
Card 4: 41 92 73 84 69 | 59 84 76 51 58  5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
"
:}
13
30

-}
module Main (main) where

import Advent (format)
import Data.List (intersect)

-- | Parse the input and print out the answers to both parts.
--
-- >>> :main
-- 21485
-- 11024379
main :: IO ()
IO ()
main =
 do [(Int, [Int], [Int])]
input <- [format|2023 4 (Card +%d:( +%d)* %|( +%d)*%n)*|]
    let wins :: [Int]
wins = [[Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Int]
a [Int] -> [Int] -> [Int]
forall a. Eq a => [a] -> [a] -> [a]
`intersect` [Int]
b) | (Int
_, [Int]
a, [Int]
b) <- [(Int, [Int], [Int])]
input]
    Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Int
points [Int]
wins))
    Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> [Int]
asPart2 [Int]
wins))

-- | Convert wins to points for part 1
points :: Int -> Int
points :: Int -> Int
points Int
0 = Int
0
points Int
n = Int
2 Int -> Int -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

-- | Convert a list of wins for each card into the number of cards
-- each card turns into.
asPart2 :: [Int] -> [Int]
asPart2 :: [Int] -> [Int]
asPart2 = (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int]
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\Int
wins [Int]
xs -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
take Int
wins [Int]
xs) Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
xs) []