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

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

-}
module Main (main) where

import Advent (format)
import Data.Char (digitToInt)


-- | Print the solution to day 1. Input file can be overridden via the
-- command-line.
main :: IO ()
IO ()
main =
  do [Int]
xs <- (Char -> Int) -> [Char] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
digitToInt ([Char] -> [Int]) -> IO [Char] -> IO [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [format|2017 1 %s%n|]
     Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
part1 [Int]
xs)
     Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
part2 [Int]
xs)


-- | Parse the first line of the input as a list of digits
--
-- >>> parseInput "1234\n"
-- [1,2,3,4]
parseInput :: String -> [Int]
parseInput :: [Char] -> [Int]
parseInput = (Char -> Int) -> [Char] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
digitToInt ([Char] -> [Int]) -> ([Char] -> [Char]) -> [Char] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> [Char]
forall a. HasCallStack => [a] -> a
head ([[Char]] -> [Char]) -> ([Char] -> [[Char]]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [[Char]]
lines


-- | Compute checksum matching against next neighbor.
--
-- >>> part1 [1,1,2,2]
-- 3
-- >>> part1 [1,1,1,1]
-- 4
-- >>> part1 [1,2,3,4]
-- 0
-- >>> part1 [9,1,2,1,2,1,2,9]
-- 9
part1 :: [Int] -> Int
part1 :: [Int] -> Int
part1 = Int -> [Int] -> Int
solve Int
1


-- | Compute checksum matching against furthest neighbor.
--
-- >>> part2 [1,2,1,2]
-- 6
-- >>> part2 [1,2,2,1]
-- 0
-- >>> part2 [1,2,3,4,2,5]
-- 4
-- >>> part2 [1,2,3,1,2,3]
-- 12
-- >>> part2 [1,2,1,3,1,4,1,5]
-- 4
part2 :: [Int] -> Int
part2 :: [Int] -> Int
part2 [Int]
xs = Int -> [Int] -> Int
solve ([Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
xs Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2) [Int]
xs


-- | Compute the sum of the elements of a list where the
-- neighbor @n@ elements to the right (circularly) is a
-- match.
solve :: Int -> [Int] -> Int
solve :: Int -> [Int] -> Int
solve Int
n [Int]
xs = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ Int
x | (Int
x,Int
y) <- [Int]
xs [Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
drop Int
n ([Int] -> [Int]
forall a. HasCallStack => [a] -> [a]
cycle [Int]
xs), Int
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
y ]