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

<https://adventofcode.com/2020/day/10>

-}
module Main (main) where

import Advent (count)
import Advent.Format (format)
import Data.List (sort)

-- |
-- >>> :main
-- 1998
-- 347250213298688
main :: IO ()
IO ()
main =
  do [Int]
adapters <- [format|2020 10 (%u%n)*|]
     let socket :: Int
socket = Int
0
     let device :: Int
device = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
adapters Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3

     let jolts :: [Int]
jolts = [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort (Int
socket Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: Int
device Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
adapters)
     let diffs :: [Int]
diffs = (Int -> Int -> Int) -> [Int] -> [Int] -> [Int]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (-) ([Int] -> [Int]
forall a. HasCallStack => [a] -> [a]
tail [Int]
jolts) [Int]
jolts
     Int -> IO ()
forall a. Show a => a -> IO ()
print (Int -> [Int] -> Int
forall (f :: * -> *) a. (Foldable f, Eq a) => a -> f a -> Int
count Int
3 [Int]
diffs Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int -> [Int] -> Int
forall (f :: * -> *) a. (Foldable f, Eq a) => a -> f a -> Int
count Int
1 [Int]
diffs)

     let part2 :: [a] -> t -> t -> t -> t
part2 (a
1:[a]
ds) t
x t
y t
z = [a] -> t -> t -> t -> t
part2 [a]
ds t
y t
z (t
zt -> t -> t
forall a. Num a => a -> a -> a
+t
yt -> t -> t
forall a. Num a => a -> a -> a
+t
x)
         part2 (a
2:[a]
ds) t
_ t
y t
z = [a] -> t -> t -> t -> t
part2 [a]
ds t
z t
0 (t
zt -> t -> t
forall a. Num a => a -> a -> a
+t
y) -- unused in normal input
         part2 (a
3:[a]
ds) t
_ t
_ t
z = [a] -> t -> t -> t -> t
part2 [a]
ds t
0 t
0 t
z
         part2 []     t
_ t
_ t
z = t
z
         part2 [a]
_      t
_ t
_ t
_ = String -> t
forall a. HasCallStack => String -> a
error String
"unexpected gap"
     Integer -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Integer -> Integer -> Integer -> Integer
forall {a} {t}. (Eq a, Num a, Num t) => [a] -> t -> t -> t -> t
part2 [Int]
diffs Integer
0 Integer
0 Integer
1 :: Integer)