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 --- 2023/10.hs | 13 +++---------- 2023/11.hs | 29 +++-------------------------- 2023/6.hs | 13 +++---------- 2023/7.hs | 13 +++---------- 2023/8.hs | 13 +++---------- 2023/9.hs | 13 +++---------- aoc.hs | 34 ++++++++++++++++++++++++++++++++++ 7 files changed, 52 insertions(+), 76 deletions(-) create mode 100644 aoc.hs diff --git a/2023/10.hs b/2023/10.hs index 75a3d8f..e4c560f 100755 --- a/2023/10.hs +++ b/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 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 @@ -98,14 +99,6 @@ findStartingPosition tiles = case listToMaybe [(x, y) | (y, row) <- zip [0 ..] t 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]] parseInput = parseLine `sepBy` char '\n' diff --git a/2023/11.hs b/2023/11.hs index cc4a456..53f5cfb 100755 --- a/2023/11.hs +++ b/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 @@ findEmptySpace grid = (findX grid, findY grid) -- 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 +++ b/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 @@ -37,14 +38,6 @@ scale n 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)] gameParser = do diff --git a/2023/7.hs b/2023/7.hs index a58dcca..135e12d 100755 --- a/2023/7.hs +++ b/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 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 @@ -66,14 +67,6 @@ getHandStrength sortedCardCount = case sortedCardCount of 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] parseAllGames = parseGame `endBy` char '\n' diff --git a/2023/8.hs b/2023/8.hs index fa3ec83..b137bcd 100755 --- a/2023/8.hs +++ b/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 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 @@ -41,14 +42,6 @@ traverseTreeUntil (x : xs) m n predicate 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 parseDocument = do diff --git a/2023/9.hs b/2023/9.hs index 5623c9e..370b6d2 100755 --- a/2023/9.hs +++ b/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 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 @@ -59,14 +60,6 @@ buildDifferenceTable input = input : unfoldr buildRow input 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]] parseInput = parseSequence `sepBy` char '\n' diff --git a/aoc.hs b/aoc.hs new file mode 100644 index 0000000..dda9f26 --- /dev/null +++ b/aoc.hs @@ -0,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 '.' + ] -- libgit2 1.7.2