🏡 index : ~doyle/aoc.git

module Aoc where

import Text.Parsec
import Text.Parsec.Char
import Text.Parsec.Combinator
import Text.Parsec.String (Parser)

-- read and parse stdin
readAndParseStdin :: Parser a -> IO a
readAndParseStdin parser = do
  content <- getContents
  case parse parser "" content of
    Left parseError -> error $ show parseError
    Right doc -> return doc

-- parse multiple grids
parseMultipleGrids :: Parser [[[Bool]]]
parseMultipleGrids = parseGrid `sepBy` string "\n"

-- parse an entire grid
parseGrid :: Parser [[Bool]]
parseGrid = parseGridRow `endBy` char '\n'

-- parse an incoming row
parseGridRow :: Parser [Bool]
parseGridRow = many1 parseGridTile

-- parses a single tile on a grid
parseGridTile :: Parser Bool
parseGridTile =
  choice
    [ True <$ char '#',
      False <$ char '.'
    ]

-- parse an entire multichoice grid
parseMultiChoiceGrid :: Parser [[Maybe Bool]]
parseMultiChoiceGrid = parseMultiChoiceGridRow `endBy` char '\n'

-- parse an incoming row
parseMultiChoiceGridRow :: Parser [Maybe Bool]
parseMultiChoiceGridRow = many1 parseMultiChoiceGridTile

-- parse a single multi-choice tile on a grid
parseMultiChoiceGridTile :: Parser (Maybe Bool)
parseMultiChoiceGridTile =
  choice
    [ Just True <$ char 'O',
      Just False <$ char '#',
      Nothing <$ char '.'
    ]

-- debugging for multi-choice tile grids
printMultiChoiceGrid :: [[Maybe Bool]] -> IO ()
printMultiChoiceGrid xs = putStrLn $ unlines $ (map . map) multiChoiceGridTileChar xs
  where
    multiChoiceGridTileChar (Just True) = 'O'
    multiChoiceGridTileChar (Just False) = '#'
    multiChoiceGridTileChar Nothing = '.'

-- calculates the area for a polygon described by the set of
-- verticies using the shoelace formula
shoelace :: [(Int, Int)] -> Double
shoelace vertices =
  let pairs = zip vertices $ tail vertices
      sumProd (x1, y1) (x2, y2) = x1 * y2 - x2 * y1
   in fromIntegral (abs . sum $ zipWith sumProd vertices (tail vertices)) / 2