69 lines
1.8 KiB
Haskell
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]
|