mirror of
https://codeberg.org/JasterV/aoc2024-haskell.git
synced 2026-04-26 18:10:05 +00:00
refactor: Handle file read error
This commit is contained in:
parent
0721ec8c1f
commit
36fbdd5864
1 changed files with 32 additions and 17 deletions
49
src/Day1.hs
49
src/Day1.hs
|
|
@ -4,6 +4,7 @@ module Day1
|
|||
)
|
||||
where
|
||||
|
||||
import Control.Exception (try)
|
||||
import qualified Data.Bifunctor as Bifunctor
|
||||
import Data.Either
|
||||
import Data.List (sort)
|
||||
|
|
@ -12,14 +13,22 @@ import Prelude hiding (id)
|
|||
|
||||
type LocationID = Int
|
||||
|
||||
data Error = ParseLocationError String String | ParseLineError String
|
||||
data ParseError
|
||||
= ParseLocationError String String
|
||||
| ParseLineError String
|
||||
deriving (Show)
|
||||
|
||||
data Error
|
||||
= ReadFileError String
|
||||
| ParseInputError [ParseError]
|
||||
deriving (Show)
|
||||
|
||||
partOne :: String -> IO (Either Error Int)
|
||||
partOne filepath = do
|
||||
contents <- readFile filepath
|
||||
let score = calculateScore <$> parseInput contents
|
||||
return score
|
||||
result <- tryReadFile filepath
|
||||
case result of
|
||||
Left readError -> return (Left readError)
|
||||
Right contents -> return (calculateScore <$> parseInput contents)
|
||||
where
|
||||
-- To calculate the overall score we just need to
|
||||
-- sort the lists and calculate the distances between each element
|
||||
|
|
@ -29,9 +38,10 @@ partOne filepath = do
|
|||
|
||||
partTwo :: String -> IO (Either Error Int)
|
||||
partTwo filepath = do
|
||||
contents <- readFile filepath
|
||||
let score = calculateScore <$> parseInput contents
|
||||
return score
|
||||
result <- tryReadFile filepath
|
||||
case result of
|
||||
Left readError -> return (Left readError)
|
||||
Right contents -> return (calculateScore <$> parseInput contents)
|
||||
where
|
||||
-- To calculate the overall score we need to sum all the similarity scores
|
||||
-- of each element from the left list applied to the right list
|
||||
|
|
@ -42,31 +52,30 @@ partTwo filepath = do
|
|||
count x = length . filter (== x)
|
||||
|
||||
parseInput :: String -> Either Error ([LocationID], [LocationID])
|
||||
parseInput input = do
|
||||
parsedLines <- parseLines (lines input)
|
||||
return (unzip parsedLines)
|
||||
parseInput input = Bifunctor.first ParseInputError $ unzip <$> parseLines (lines input)
|
||||
|
||||
parseLines :: [String] -> Either Error [(LocationID, LocationID)]
|
||||
parseLines xs = case take 1 errors of
|
||||
[parseError] -> Left parseError
|
||||
_ -> Right parsedLines
|
||||
parseLines :: [String] -> Either [ParseError] [(LocationID, LocationID)]
|
||||
parseLines xs =
|
||||
if null errors
|
||||
then Right parsedLines
|
||||
else Left errors
|
||||
where
|
||||
errors = lefts $ map (parseWords . words) xs
|
||||
parsedLines = rights $ map (parseWords . words) xs
|
||||
|
||||
parseWords :: [String] -> Either Error (LocationID, LocationID)
|
||||
parseWords :: [String] -> Either ParseError (LocationID, LocationID)
|
||||
parseWords [left, right] = do
|
||||
leftLocation <- parseLeft
|
||||
rightLocation <- parseRight
|
||||
return (leftLocation, rightLocation)
|
||||
where
|
||||
parseLeft :: Either Error LocationID
|
||||
parseLeft :: Either ParseError LocationID
|
||||
parseLeft =
|
||||
Bifunctor.first
|
||||
(ParseLocationError left)
|
||||
(readEither left :: Either String LocationID)
|
||||
|
||||
parseRight :: Either Error LocationID
|
||||
parseRight :: Either ParseError LocationID
|
||||
parseRight =
|
||||
Bifunctor.first
|
||||
(ParseLocationError right)
|
||||
|
|
@ -75,3 +84,9 @@ parseWords [left, right] = do
|
|||
-- If the line does not contain exactly two words,
|
||||
-- it is considered an error
|
||||
parseWords xs' = Left $ ParseLineError (unwords xs')
|
||||
|
||||
tryReadFile :: String -> IO (Either Error String)
|
||||
tryReadFile filepath = Bifunctor.first (const $ ReadFileError filepath) <$> io
|
||||
where
|
||||
io :: IO (Either IOError String)
|
||||
io = try (readFile filepath)
|
||||
|
|
|
|||
Loading…
Reference in a new issue