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

<https://adventofcode.com/2017/day/2>

-}
module Main where

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

main :: IO ()
IO ()
main =
  do [[Int]]
xs <- [format|2017 2 (%u&%t%n)*|]
     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
checksum1 [[Int]]
xs))
     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
checksum2 [[Int]]
xs))

-- | First checksum is the difference of the largest and smallest elements
--
-- >>> checksum1 [5,1,9,5]
-- 8
-- >>> checksum1 [7,5,3]
-- 4
-- >>> checksum1 [2,4,6,8]
-- 6
checksum1 :: [Int] -> Int
checksum1 :: [Int] -> Int
checksum1 [Int]
xs = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
xs Int -> Int -> Int
forall a. Num a => a -> a -> a
- [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Int]
xs

-- | Second checksum is the quotient of the only two elements that evenly
-- divide each other.
--
-- >>> checksum2 [5,9,2,8]
-- 4
-- >>> checksum2 [9,4,7,3]
-- 3
-- >>> checksum2 [3,8,6,5]
-- 2
checksum2 :: [Int] -> Int
checksum2 :: [Int] -> Int
checksum2 [Int]
xs =
  [Int] -> Int
forall a. HasCallStack => [a] -> a
head [ Int
q | Int
x <- [Int]
xs, Int
y <- Int -> [Int] -> [Int]
forall a. Eq a => a -> [a] -> [a]
delete Int
x [Int]
xs, (Int
q,Int
0) <- [Int
x Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
y] ]