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

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

In my original attempt I considered messages with a window size of 20.
Now that I know the message is only 10 high, I've narrowed my predicate.

-}
module Main (main) where

import Advent.Format (format)
import Advent.Coord (coordRow, drawCoords, Coord(..))
import Data.Foldable (asum)
import Data.List (transpose)
import Data.Maybe (fromJust, isJust, isNothing)

-- | Print the answers to day 10
main :: IO ()
IO ()
main =
 do let toSim :: (Int, Int, Int, Int) -> [Coord]
toSim (Int
px, Int
py, Int
dx, Int
dy) = (Coord -> Coord) -> Coord -> [Coord]
forall a. (a -> a) -> a -> [a]
iterate (Int -> Int -> Coord
C Int
dy Int
dx Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
+) (Int -> Int -> Coord
C Int
py Int
px)
    [[Coord]]
input <- ((Int, Int, Int, Int) -> [Coord])
-> [(Int, Int, Int, Int)] -> [[Coord]]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Int, Int, Int) -> [Coord]
toSim ([(Int, Int, Int, Int)] -> [[Coord]])
-> IO [(Int, Int, Int, Int)] -> IO [[Coord]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [format|2018 10 (position=< *%d, *%d> velocity=< *%d, *%d>%n)*|]
    String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Maybe String -> String
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ [Maybe String] -> Maybe String
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum ([Maybe String] -> Maybe String) -> [Maybe String] -> Maybe String
forall a b. (a -> b) -> a -> b
$ (Int -> [Coord] -> Maybe String)
-> [Int] -> [[Coord]] -> [Maybe String]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Int -> [Coord] -> Maybe String
draw [Int
0..] ([[Coord]] -> [Maybe String]) -> [[Coord]] -> [Maybe String]
forall a b. (a -> b) -> a -> b
$ [[Coord]] -> [[Coord]]
forall a. [[a]] -> [[a]]
transpose [[Coord]]
input

-- | Given a number of seconds and the current list of particles,
-- render the particles to a string when they are close enough together
-- to be considered interesting to look at.
draw :: Int -> [Coord] -> Maybe String
draw :: Int -> [Coord] -> Maybe String
draw Int
i [Coord]
ps
  | Int
hirow Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
lorow Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
10 = String -> Maybe String
forall a. a -> Maybe a
Just (Int -> String
forall a. Show a => a -> String
show Int
i String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
picture)
  | Bool
otherwise           = Maybe String
forall a. Maybe a
Nothing
  where
    lorow :: Int
lorow = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ((Coord -> Int) -> [Coord] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Coord -> Int
coordRow [Coord]
ps)
    hirow :: Int
hirow = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ((Coord -> Int) -> [Coord] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Coord -> Int
coordRow [Coord]
ps)
    picture :: String
picture = [Coord] -> String
forall (t :: * -> *). Foldable t => t Coord -> String
drawCoords [Coord]
ps