{-|
Module      : Advent.Coord
Description : Day 19 solution
Copyright   : (c) Eric Mertens, 2017
License     : ISC
Maintainer  : emertens@gmail.com

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

Day 19 has us follow an ASCII art trail and report on the letters
we find along the way as well as the total trail path length.

-}
module Main where

import Advent.Input (getInputArray)
import Advent.Coord (Coord(..), north, east, south, west)
import Data.Char (isAlpha)
import Data.Array.Unboxed (UArray, (!), assocs)

-- | Print the solutions to both parts of day 19. Input file can be
-- overridden via the command-line arguments.
main :: IO ()
IO ()
main =
 do UArray Coord Char
input <- Int -> Int -> IO (UArray Coord Char)
getInputArray Int
2017 Int
19

    let Coord
start:[Coord]
_ = [Coord
c | (c :: Coord
c@(C Int
0 Int
_), Char
'|') <- UArray Coord Char -> [(Coord, Char)]
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> [(i, e)]
assocs UArray Coord Char
input]
        path :: String
path = UArray Coord Char -> Coord -> Coord -> String
toPath UArray Coord Char
input Coord
south Coord
start

    String -> IO ()
putStrLn ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter Char -> Bool
isAlpha String
path)
    Int -> IO ()
forall a. Show a => a -> IO ()
print (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
path)

-- | Return the path given a map, current travel direction,
-- and current location.
toPath ::
  UArray Coord Char {- ^ map       -} ->
  Coord             {- ^ direction -} ->
  Coord             {- ^ location  -} ->
  String            {- ^ path      -}
toPath :: UArray Coord Char -> Coord -> Coord -> String
toPath UArray Coord Char
grid Coord
d Coord
c =
  let isPath :: Coord -> Bool
isPath Coord
d' = UArray Coord Char
grid UArray Coord Char -> Coord -> Char
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! (Coord
c Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
+ Coord
d') Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' '
      next :: Coord -> String
next Coord
d'   = UArray Coord Char -> Coord -> Coord -> String
toPath UArray Coord Char
grid Coord
d' (Coord
c Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
+ Coord
d') in
  case UArray Coord Char
grid UArray Coord Char -> Coord -> Char
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! Coord
c of
    Char
' '                            -> []
    Char
'+' | Coord
d Coord -> Coord -> Bool
forall a. Eq a => a -> a -> Bool
/= Coord
south, Coord -> Bool
isPath Coord
north -> Char
'+' Char -> String -> String
forall a. a -> [a] -> [a]
: Coord -> String
next Coord
north
        | Coord
d Coord -> Coord -> Bool
forall a. Eq a => a -> a -> Bool
/= Coord
north, Coord -> Bool
isPath Coord
south -> Char
'+' Char -> String -> String
forall a. a -> [a] -> [a]
: Coord -> String
next Coord
south
        | Coord
d Coord -> Coord -> Bool
forall a. Eq a => a -> a -> Bool
/= Coord
west,  Coord -> Bool
isPath Coord
east  -> Char
'+' Char -> String -> String
forall a. a -> [a] -> [a]
: Coord -> String
next Coord
east
        | Coord
d Coord -> Coord -> Bool
forall a. Eq a => a -> a -> Bool
/= Coord
east,  Coord -> Bool
isPath Coord
west  -> Char
'+' Char -> String -> String
forall a. a -> [a] -> [a]
: Coord -> String
next Coord
west
    Char
a                              -> Char
a   Char -> String -> String
forall a. a -> [a] -> [a]
: Coord -> String
next Coord
d