47 lines
1.2 KiB
Haskell
47 lines
1.2 KiB
Haskell
import Data.Char (isDigit, digitToInt)
|
|
import Data.Function (on)
|
|
import Data.List (tails, findIndex, isPrefixOf, minimumBy)
|
|
import Data.Maybe (mapMaybe)
|
|
import Data.Bifunctor (first, bimap)
|
|
|
|
type LineOp = String -> Int
|
|
|
|
wordMap :: [(String, Int)]
|
|
wordMap = [ ("one", 1)
|
|
, ("two", 2)
|
|
, ("three", 3)
|
|
, ("four", 4)
|
|
, ("five", 5)
|
|
, ("six", 6)
|
|
, ("seven", 7)
|
|
, ("eight", 8)
|
|
, ("nine", 9)
|
|
]
|
|
|
|
fullWordMap :: [(String, Int)]
|
|
fullWordMap = wordMap ++ (zip =<< map show) [1..9]
|
|
|
|
opLineBasic :: LineOp
|
|
opLineBasic l = (combineDigits `on` ($ digitToInt <$> filter isDigit l)) head last
|
|
|
|
firstNumInLine :: String -> [(String, Int)] -> Int
|
|
firstNumInLine l = fst . minimumBy (compare `on` snd) . mapMaybe numIndex
|
|
where
|
|
numIndex (str, num) = (num,) <$> findIndex (isPrefixOf str) (tails l)
|
|
|
|
opLineAdvanced :: LineOp
|
|
opLineAdvanced l = (combineDigits `on` uncurry firstNumInLine)
|
|
<*> bimap reverse (map $ first reverse)
|
|
$ (l, fullWordMap)
|
|
|
|
combineDigits :: Int -> Int -> Int
|
|
combineDigits = (+) . (10 *)
|
|
|
|
opLines :: [String] -> Int
|
|
opLines = sum . map opLineAdvanced
|
|
|
|
main :: IO ()
|
|
main = do
|
|
content <- readFile "data.txt"
|
|
print . opLines . lines $ content
|