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

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

-}
module Main (main) where

import Advent (format, countBy)
import Data.List (group)

-- | >>> :main
-- 1929
-- 1306
main :: IO ()
IO ()
main =
  do [(Int
lo,Int
hi)] <- [format|2019 4 (%u-%u%n)*|]
     let nums :: [[Int]]
nums = (String -> [Int]) -> [String] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map String -> [Int]
forall a. Eq a => [a] -> [Int]
runs ([String] -> [[Int]]) -> [String] -> [[Int]]
forall a b. (a -> b) -> a -> b
$ (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter String -> Bool
forall a. Ord a => [a] -> Bool
nondecreasing ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ (Int -> String) -> [Int] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Int -> String
forall a. Show a => a -> String
show [Int
lo..Int
hi]
     Int -> IO ()
forall a. Show a => a -> IO ()
print (([Int] -> Bool) -> [[Int]] -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countBy ((Int -> Bool) -> [Int] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1)) [[Int]]
nums)
     Int -> IO ()
forall a. Show a => a -> IO ()
print (([Int] -> Bool) -> [[Int]] -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countBy (Int -> [Int] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem Int
2   ) [[Int]]
nums)

-- | Return a list of the lengths of consecutive elements in a list.
--
-- >>> runs [1,2,3]
-- [1,1,1]
-- >>> runs [1,1,1]
-- [3]
-- >>> runs [1,1,2,2,2,1,1]
-- [2,3,2]
-- >>> runs []
-- []
runs :: Eq a => [a] -> [Int]
runs :: forall a. Eq a => [a] -> [Int]
runs = ([a] -> Int) -> [[a]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([[a]] -> [Int]) -> ([a] -> [[a]]) -> [a] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [[a]]
forall a. Eq a => [a] -> [[a]]
group

-- | Predicate for non-decreasing lists.
--
-- >>> nondecreasing []
-- True
-- >>> nondecreasing [1,1,2,3]
-- True
-- >>> nondecreasing [3,3,2]
-- False
nondecreasing :: Ord a => [a] -> Bool
nondecreasing :: forall a. Ord a => [a] -> Bool
nondecreasing [a]
xs = [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ((a -> a -> Bool) -> [a] -> [a] -> [Bool]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(<=) [a]
xs ([a] -> [a]
forall a. HasCallStack => [a] -> [a]
tail [a]
xs))