Last active
February 10, 2024 02:15
-
-
Save TorNATO-PRO/698a452d619b89b6504b5614bfa4f4c2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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