🏡 index : ~doyle/aoc.git

author Jordan Doyle <jordan@doyle.la> 2023-12-17 13:57:28.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2023-12-17 13:57:43.0 +00:00:00
commit
4b685ca6b215d59282832ee6f5550bdaa7b41e49 [patch]
tree
c553349278133920dcb55875a4519daf0850d7a8
parent
081398053614b9f17dc0bce2dd46b4967cc75bb0
download
4b685ca6b215d59282832ee6f5550bdaa7b41e49.tar.gz

Extract out common Haskell utilities



Diff

 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]]