improve code
This commit is contained in:
parent
6876e45877
commit
70a8c18a27
1 changed files with 24 additions and 53 deletions
77
4.hs
77
4.hs
|
@ -6,49 +6,23 @@ import Data.List
|
|||
import Data.List.Extra (stripSuffix)
|
||||
import Data.List.Split
|
||||
import Data.Maybe
|
||||
import Debug.Trace
|
||||
import Text.Read
|
||||
import Data.Set (Set, fromList, isSubsetOf)
|
||||
|
||||
data Attr
|
||||
= Byr
|
||||
| Iyr
|
||||
| Eyr
|
||||
| Hgt
|
||||
| Hcl
|
||||
| Ecl
|
||||
| Pid
|
||||
| Cid
|
||||
data Attr = Byr | Iyr | Eyr | Hgt | Hcl | Ecl | Pid | Cid
|
||||
deriving (Show, Bounded, Enum, Eq, Ord)
|
||||
|
||||
type Passport = [Attr]
|
||||
|
||||
intval :: (Int, Int) -> Int -> Maybe Int
|
||||
intval (lo, hi) = \n ->
|
||||
if n >= lo && n <= hi then Just n
|
||||
else Nothing
|
||||
intval :: Int -> Int -> Int -> Maybe Int
|
||||
intval lo hi n = guard (n >= lo && n <= hi) $> n
|
||||
|
||||
nDigits :: Int -> String -> Maybe String
|
||||
nDigits n = \s ->
|
||||
if length s == n && all isDigit s then Just s
|
||||
else Nothing
|
||||
nDigits n s = guard (length s == n && all isDigit s) $> s
|
||||
|
||||
hexColor :: String -> Maybe String
|
||||
hexColor s =
|
||||
if length s == 7
|
||||
&& s !! 0 == '#'
|
||||
&& all (\c -> elem c "0123456789abcdef") (drop 1 s) then Just s
|
||||
else Nothing
|
||||
hexColor s = guard (length s == 7 && s !! 0 == '#' && all (\c -> elem c "0123456789abcdef") (drop 1 s)) $> s
|
||||
|
||||
validEcl :: String -> Bool
|
||||
validEcl s = case s of
|
||||
"amb" -> True
|
||||
"blu" -> True
|
||||
"brn" -> True
|
||||
"gry" -> True
|
||||
"grn" -> True
|
||||
"hzl" -> True
|
||||
"oth" -> True
|
||||
_ -> False
|
||||
validEcl = flip elem ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]
|
||||
|
||||
parseAttr :: String -> Maybe Attr
|
||||
parseAttr s =
|
||||
|
@ -56,13 +30,13 @@ parseAttr s =
|
|||
let key = parts !! 0 in
|
||||
let value = parts !! 1 in
|
||||
case key of
|
||||
"byr" -> (readMaybe value >>= intval (1920, 2002)) $> Byr
|
||||
"iyr" -> (readMaybe value >>= intval (2010, 2020)) $> Iyr
|
||||
"eyr" -> (readMaybe value >>= intval (2020, 2030)) $> Eyr
|
||||
"byr" -> (readMaybe value >>= intval 1920 2002) $> Byr
|
||||
"iyr" -> (readMaybe value >>= intval 2010 2020) $> Iyr
|
||||
"eyr" -> (readMaybe value >>= intval 2020 2030) $> Eyr
|
||||
"hgt" ->
|
||||
((stripSuffix "cm" value >>= readMaybe >>= intval (150, 193)) <|>
|
||||
(stripSuffix "in" value >>= readMaybe >>= intval(59, 76)))
|
||||
$> Hgt
|
||||
let inch = stripSuffix "cm" value >>= readMaybe >>= intval 150 193 in
|
||||
let cm = stripSuffix "in" value >>= readMaybe >>= intval 59 76 in
|
||||
(inch <|> cm) $> Hgt
|
||||
"hcl" -> hexColor value $> Hcl
|
||||
"ecl" -> if validEcl value then Just Ecl else Nothing
|
||||
"pid" -> nDigits 9 value $> Pid
|
||||
|
@ -70,28 +44,25 @@ parseAttr s =
|
|||
_ -> Nothing
|
||||
|
||||
processLine :: String -> Maybe [Attr]
|
||||
processLine line = sequence $ (map parseAttr $ splitOn " " line)
|
||||
processLine = mapM parseAttr . splitOn " "
|
||||
|
||||
requiredAttrs :: [Attr]
|
||||
requiredAttrs = enumFromTo Byr Pid
|
||||
requiredAttrs :: Set Attr
|
||||
requiredAttrs = fromList $ enumFromTo Byr Pid
|
||||
|
||||
combineAttrs :: [Attr] -> Maybe Passport
|
||||
combineAttrs attrs =
|
||||
let intersection = intersect attrs requiredAttrs in
|
||||
if sort intersection == sort requiredAttrs then Just attrs
|
||||
else Nothing
|
||||
combineAttrs :: [Attr] -> Maybe [Attr]
|
||||
combineAttrs attrs = guard (isSubsetOf requiredAttrs $ fromList $ attrs) $> attrs
|
||||
|
||||
processPassport :: [String] -> Maybe Passport
|
||||
processPassport lines = concat <$> (sequence $ map processLine lines) >>= combineAttrs
|
||||
processPassport :: [String] -> Maybe [Attr]
|
||||
processPassport = combineAttrs . concat <=< mapM processLine
|
||||
|
||||
processLines :: [String] -> [Maybe Passport]
|
||||
processLines lines = map processPassport $ splitWhen (== "") lines
|
||||
processLines :: [String] -> [Maybe [Attr]]
|
||||
processLines = map processPassport . splitWhen (== "")
|
||||
|
||||
countValid :: [Maybe Passport] -> Int
|
||||
countValid :: [Maybe [Attr]] -> Int
|
||||
countValid = length . filter isJust
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
content <- readFile "4.txt"
|
||||
let valid = countValid $ processLines $ lines content
|
||||
putStrLn (show valid)
|
||||
print valid
|
||||
|
|
Loading…
Reference in a new issue