advent-of-code-2023/src/Day1.hs

69 lines
1.8 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-unused-do-bind #-}
module Day1 where
import Data.Semigroup
import Data.Char
import Data.String
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as Char8
import Data.Attoparsec.Lazy
import Data.Attoparsec.ByteString.Char8 (letter_ascii)
import Data.Either (fromRight)
-- import Debug.Trace
main :: IO ()
main = do
day1input <- lines <$> readFile "inputs/day1.input"
putStrLn "Part 1 result:"
print $ part1 day1input
putStrLn "Part 2 result:"
print $ part2 day1input
part1 :: [String] -> Sum Int
part1 = foldMap go
where
go :: String -> Sum Int
go = glueFirstLast . map (\c -> read [c]) . filter isNumber
part2 :: [String] -> Sum Int
part2 = foldMap (glueFirstLast . getNumbers)
glueFirstLast :: [Int] -> Sum Int
glueFirstLast xs = Sum $ 10 * head xs + last xs
getNumbers :: String -> [Int]
getNumbers = fromRight [] . parseOnly numberParser . fromString
numberParser :: Parser [Int]
numberParser = do
s <- concat <$> (parseN `sepBy` letter_ascii)
pure $ concatMap toInt s
where
parseN = many' . choice $ map string
["oneight","threeight","fiveight","sevenine","nineight","eightwo","eighthree","twone"
,"one","two","three","four","five","six","seven","eight","nine"
, "1","2","3","4","5","6","7","8","9"
]
toInt :: B.ByteString -> [Int]
toInt "one" = [1]
toInt "two" = [2]
toInt "three" = [3]
toInt "four" = [4]
toInt "five" = [5]
toInt "six" = [6]
toInt "seven" = [7]
toInt "eight" = [8]
toInt "nine" = [9]
toInt "oneight" = [1,8]
toInt "threeight" = [3,8]
toInt "fiveight" = [5,8]
toInt "sevenine" = [7,9]
toInt "nineight" = [9,8]
toInt "eighthree" = [8,3]
toInt "eightwo" = [8,2]
toInt "twone" = [2,1]
toInt ss = [read $ Char8.unpack ss]