Skip to content

Instantly share code, notes, and snippets.

@TorNATO-PRO
Last active February 10, 2024 02:15
Show Gist options
  • Save TorNATO-PRO/698a452d619b89b6504b5614bfa4f4c2 to your computer and use it in GitHub Desktop.
Save TorNATO-PRO/698a452d619b89b6504b5614bfa4f4c2 to your computer and use it in GitHub Desktop.
import Prelude
import Control.Alternative ((<|>))
import Data.Array (filter)
import Data.Array.NonEmpty (head, last)
import Data.Either (Either(..))
import Data.Int as Int
import Data.String (Pattern(..), split)
import Data.String.CodeUnits as String
import Data.Traversable (sum, traverse)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect.Class.Console (log)
import Node.Encoding (Encoding(..))
import Node.FS.Sync (readTextFile)
import Parsing (ParseError, Parser, liftMaybe, parseErrorMessage, runParser)
import Parsing.Combinators (choice, lookAhead)
import Parsing.Combinators.Array (many1)
import Parsing.String (anyTill, char, string)
import Parsing.String.Basic (digit)
---------------------------------------------------
digitOne :: Parser String Int
digitOne = do
d <- digit
liftMaybe (\_ -> "failed to convert char digit to int") (Int.fromString $ String.singleton d)
-- I could honestly just use the alternative instance for
-- Parser and combine the solutions, but for clarity i will
-- keep them separate
one' :: Parser String Int
one' = string "on" *> lookAhead (char 'e') $> 1
two' :: Parser String Int
two' = string "tw" *> lookAhead (char 'o') $> 2
three' :: Parser String Int
three' = string "thre" *> lookAhead (char 'e') $> 3
four' :: Parser String Int
four' = string "four" $> 4
five' :: Parser String Int
five' = string "fiv" *> lookAhead (char 'e') $> 5
six' :: Parser String Int
six' = string "six" $> 6
seven' :: Parser String Int
seven' = string "seven" $> 7
eight' :: Parser String Int
eight' = string "eigh" *> lookAhead (char 't') $> 8
nine' :: Parser String Int
nine' = string "nin" *> lookAhead (char 'e') $> 9
stringDigit :: Parser String Int
stringDigit = choice
[ one'
, two'
, three'
, four'
, five'
, six'
, seven'
, eight'
, nine'
]
digitTwo :: Parser String Int
digitTwo = stringDigit <|> digitOne
digitWithTrailing :: Parser String Int -> Parser String Int
digitWithTrailing digitParser = do
_ /\ res <- anyTill digitParser
pure res
lineDigit :: Parser String Int -> Parser String Int
lineDigit digitParser = do
digits <- many1 (digitWithTrailing digitParser)
let
fstDigit = 10 * head digits
sndDigit = last digits
pure $ fstDigit + sndDigit
parseInput :: Parser String Int -> Array String -> Either ParseError (Array Int)
parseInput digitParser = traverse fn
where
fn line = runParser line $ lineDigit digitParser
lines :: String -> Array String
lines = filter ((/=) "") <<< split (Pattern "\n")
displayResult :: Either ParseError (Array Int) -> Effect Unit
displayResult = case _ of
Left err -> log $ "Received parse error: " <> parseErrorMessage err
Right result -> log $ show $ sum result
program :: Effect Unit
program = do
file <- readTextFile UTF8 "aoc.txt"
log "Part One"
displayResult (parseInput digitOne $ lines file)
log "End Part One"
log "Part Two"
displayResult (parseInput digitTwo $ lines file)
log "End Part Two"
---------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment