52 lines
1.3 KiB
Haskell
52 lines
1.3 KiB
Haskell
{-# LANGUAGE OverloadedStrings #-}
|
|
module Day01 (parse, solveA, solveB) where
|
|
|
|
import qualified Data.Text as T
|
|
import Data.Text (Text)
|
|
import Data.Char (isDigit)
|
|
import Data.Maybe (mapMaybe, listToMaybe)
|
|
|
|
|
|
parse :: Text -> [Text]
|
|
parse = T.lines
|
|
|
|
merge :: [Int] -> Int
|
|
merge xs = 10 * head xs + last xs
|
|
|
|
solveA :: [Text] -> Int
|
|
solveA = sum . map (merge . convert)
|
|
where
|
|
convert :: Text -> [Int]
|
|
convert = map (read . pure) . T.unpack . T.filter isDigit
|
|
|
|
replaces :: [(Text, Int)]
|
|
replaces =
|
|
[ ("one", 1)
|
|
, ("two", 2)
|
|
, ("three", 3)
|
|
, ("four", 4)
|
|
, ("five", 5)
|
|
, ("six", 6)
|
|
, ("seven", 7)
|
|
, ("eight", 8)
|
|
, ("nine", 9)
|
|
]
|
|
|
|
solveB :: [Text] -> Int
|
|
solveB = sum . map (merge . convert)
|
|
where
|
|
-- If `text` starts with `prefix` return `Just n`, otherwise return `Nothing`
|
|
tryReplace :: Text -> (Text, Int) -> Maybe Int
|
|
tryReplace text (prefix, n)
|
|
| prefix `T.isPrefixOf` text = Just n
|
|
| otherwise = Nothing
|
|
-- If `firstChar` is a digit return it, otherwise try replace the prefix
|
|
parsePrefix :: Text -> Maybe Int
|
|
parsePrefix text
|
|
| isDigit firstChar = Just . read . pure $ firstChar
|
|
| otherwise = listToMaybe $ mapMaybe (tryReplace text) replaces
|
|
where
|
|
firstChar = T.head text
|
|
convert :: Text -> [Int]
|
|
convert = mapMaybe parsePrefix . filter (not . T.null) . T.tails
|