From 4b685ca6b215d59282832ee6f5550bdaa7b41e49 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 17 Dec 2023 13:57:28 +0000 Subject: [PATCH] Extract out common Haskell utilities --- aoc.hs | 34 ++++++++++++++++++++++++++++++++++ 2023/10.hs | 13 +++---------- 2023/11.hs | 29 +++-------------------------- 2023/6.hs | 13 +++---------- 2023/7.hs | 13 +++---------- 2023/8.hs | 13 +++---------- 2023/9.hs | 13 +++---------- 7 files changed, 52 insertions(+), 76 deletions(-) diff --git a/aoc.hs b/aoc.hs new file mode 100644 index 0000000..dda9f26 100644 --- /dev/null +++ a/aoc.hs @@ -1,0 +1,34 @@ +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\n" + +-- parse an entire grid +parseGrid :: Parser [[Bool]] +parseGrid = parseGridRow `sepBy` char '\n' + +-- parse an incoming grow +parseGridRow :: Parser [Bool] +parseGridRow = many1 parseGridTile + +-- parses a single tile on a grid +parseGridTile :: Parser Bool +parseGridTile = + choice + [ True <$ char '#', + False <$ char '.' + ] diff --git a/2023/10.hs b/2023/10.hs index 75a3d8f..e4c560f 100755 --- a/2023/10.hs +++ a/2023/10.hs @@ -1,5 +1,5 @@ #!/usr/bin/env nix-shell -#!nix-shell --pure -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" +#!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" import Data.List import Data.Maybe (listToMaybe) @@ -8,9 +8,10 @@ import Text.Parsec.Char import Text.Parsec.Combinator import Text.Parsec.String (Parser) +import Aoc (readAndParseStdin) main = do - input <- buildPipeLoop <$> readAndParseStdin + input <- buildPipeLoop <$> readAndParseStdin parseInput print $ part1 input print $ part2 input @@ -97,14 +98,6 @@ findStartingPosition tiles = case listToMaybe [(x, y) | (y, row) <- zip [0 ..] tiles, (x, val) <- zip [0 ..] row, val == Start] of Just v -> v Nothing -> error "input contains no starting tile" - --- read and parse stdin -readAndParseStdin :: IO [[Tile]] -readAndParseStdin = do - content <- getContents - case parse parseInput "" content of - Left parseError -> error $ show parseError - Right doc -> return doc -- parse each input line parseInput :: Parser [[Tile]] diff --git a/2023/11.hs b/2023/11.hs index cc4a456..53f5cfb 100755 --- a/2023/11.hs +++ a/2023/11.hs @@ -1,14 +1,15 @@ #!/usr/bin/env nix-shell -#!nix-shell --pure -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" +#!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" import Data.List (tails, transpose) import Text.Parsec import Text.Parsec.Char import Text.Parsec.Combinator import Text.Parsec.String (Parser) +import Aoc (parseGrid, readAndParseStdin) main = do - input <- readAndParseStdin + input <- readAndParseStdin parseGrid let expansion = findEmptySpace input print $ part1 input expansion print $ part2 input expansion @@ -57,27 +58,3 @@ -- returns combinations of [a] pairs :: [a] -> [(a, a)] pairs xs = [(x, y) | (x : ys) <- tails xs, y <- ys] - --- read and parse stdin -readAndParseStdin :: IO [[Bool]] -readAndParseStdin = do - content <- getContents - case parse parseInput "" content of - Left parseError -> error $ show parseError - Right doc -> return doc - --- parse each input line -parseInput :: Parser [[Bool]] -parseInput = parseLine `sepBy` char '\n' - --- parse an incoming line -parseLine :: Parser [Bool] -parseLine = many1 parseTile - --- parses a single tile on the grid -parseTile :: Parser Bool -parseTile = - choice - [ True <$ char '#', - False <$ char '.' - ] diff --git a/2023/6.hs b/2023/6.hs index e16fcd0..6b9afa8 100755 --- a/2023/6.hs +++ a/2023/6.hs @@ -1,16 +1,17 @@ #!/usr/bin/env nix-shell -#!nix-shell -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" +#!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" import Control.Applicative ((<*)) import Text.Parsec import Text.Parsec.Char import Text.Parsec.Combinator import Text.Parsec.String (Parser) +import Aoc (readAndParseStdin) {- https://adventofcode.com/2023/day/6 -} main = do - game <- readAndParseStdin + game <- readAndParseStdin gameParser print $ part1 game print $ part2 game @@ -36,14 +37,6 @@ -- calculates distance travelled in a game based on velocity * time minus "button pressing time" distance :: Int -> Int -> Int distance v t = v * (t - v) - --- reads stdin and parses game -readAndParseStdin :: IO [(Int, Int)] -readAndParseStdin = do - content <- getContents - case parse gameParser "" content of - Left parseError -> error $ show parseError - Right game -> return game -- parses `Time: [n1] [n2] [n3]\nDistance:[n4] [n5] [n6]` and returns `[(n1, n4), (n2, n5), (n3, n6)]` gameParser :: Parser [(Int, Int)] diff --git a/2023/7.hs b/2023/7.hs index a58dcca..135e12d 100755 --- a/2023/7.hs +++ a/2023/7.hs @@ -1,5 +1,5 @@ #!/usr/bin/env nix-shell -#!nix-shell -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" +#!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" import Data.List import Data.Ord @@ -7,12 +7,13 @@ import Text.Parsec.Char import Text.Parsec.Combinator import Text.Parsec.String (Parser) +import Aoc (readAndParseStdin) {- https://adventofcode.com/2023/day/7 -} main :: IO () main = do - games <- readAndParseStdin + games <- readAndParseStdin parseAllGames print $ part1 games print $ part2 games @@ -65,14 +66,6 @@ -- groups any ranks together, returning the amount of items per group. ie. [J, J, A, A, A, 1] would return [3, 2, 1] groupCards :: [Rank] -> [Int] groupCards = sortOn Down . map length . group . sort - --- reads stdin and parses game -readAndParseStdin :: IO [Game] -readAndParseStdin = do - content <- getContents - case parse parseAllGames "" content of - Left parseError -> error $ show parseError - Right game -> return game -- parses each game delimited by a newline parseAllGames :: Parser [Game] diff --git a/2023/8.hs b/2023/8.hs index fa3ec83..b137bcd 100755 --- a/2023/8.hs +++ a/2023/8.hs @@ -1,5 +1,5 @@ #!/usr/bin/env nix-shell -#!nix-shell -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" +#!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" import Data.List import qualified Data.Map as Map @@ -7,11 +7,12 @@ import Text.Parsec.Char import Text.Parsec.Combinator import Text.Parsec.String (Parser) +import Aoc (readAndParseStdin) {- https://adventofcode.com/2023/day/8 -} main = do - document <- readAndParseStdin + document <- readAndParseStdin parseDocument print $ part1 document print $ part2 document @@ -40,14 +41,6 @@ Nothing -> error (show elem) readNext (n, _) DirectionLeft = n readNext (_, n) DirectionRight = n - --- parse entirety of stdin -readAndParseStdin :: IO Document -readAndParseStdin = do - content <- getContents - case parse parseDocument "" content of - Left parseError -> error $ show parseError - Right doc -> return doc -- parse entire document parseDocument :: Parser Document diff --git a/2023/9.hs b/2023/9.hs index 5623c9e..370b6d2 100755 --- a/2023/9.hs +++ a/2023/9.hs @@ -1,5 +1,5 @@ #!/usr/bin/env nix-shell -#!nix-shell --pure -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" +#!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])" import Control.Monad (guard) import Data.List (unfoldr) @@ -7,9 +7,10 @@ import Text.Parsec.Char import Text.Parsec.Combinator import Text.Parsec.String (Parser) +import Aoc (readAndParseStdin) main = do - input <- readAndParseStdin + input <- readAndParseStdin parseInput print $ part1 input print $ part2 input @@ -58,14 +59,6 @@ buildRow lst = let row = diffPairs $ zipPairs lst in guard (not $ null row) >> Just (row, row) - --- read and parse stdin -readAndParseStdin :: IO [[Int]] -readAndParseStdin = do - content <- getContents - case parse parseInput "" content of - Left parseError -> error $ show parseError - Right doc -> return doc -- parse each input line parseInput :: Parser [[Int]] -- rgit 0.1.5