diff --git a/day4/part2/main.d b/day4/part2/main.d index b897b69..b4b8196 100644 --- a/day4/part2/main.d +++ b/day4/part2/main.d @@ -17,31 +17,6 @@ auto parsePassports(string input) }).assocArray); } -enum Field : string -{ - birthYear = "byr", - issueYear = "iyr", - expirationYear = "eyr", - height = "hgt", - hairColor = "hcl", - eyeColor = "ecl", - passportID = "pid", - countryID = "cid", -} - -bool isValidYear(int min, int max)(string yr) -{ - if (yr.length != 4 || yr.canFind!(not!isDigit)) - return false; - auto year = yr.to!int; - return year >= min && year <= max; - -} - -alias isValidBirthYear = isValidYear!(1920, 2002); -alias isValidIssueYear = isValidYear!(2010, 2020); -alias isValidExpirationYear = isValidYear!(2020, 2030); - bool isValidHeight(string hgt) { auto match = hgt.matchFirst(r"^(\d+)(cm|in)$"); @@ -61,36 +36,24 @@ bool isValidHeight(string hgt) } } -bool isValidHairColor(string hcl) -{ - return hcl.matchFirst(r"^#[0-9a-f]{6}$").to!bool; -} - -bool isValidEyeColor(string ecl) -{ - return ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"].canFind(ecl); -} - -bool isValidPassportID(string pid) -{ - return pid.matchFirst(r"^\d{9}$").to!bool; -} - -enum requiredFields = [ - Field.birthYear, Field.issueYear, Field.expirationYear, Field.height, - Field.hairColor, Field.eyeColor, Field.passportID - ]; +alias isBetween = (x, min, max) => x >= min && x <= max; bool isValidPassport(Passport passport) { - return requiredFields.all!(field => field in passport) - && isValidBirthYear(passport[Field.birthYear]) - && isValidIssueYear(passport[Field.issueYear]) - && isValidExpirationYear(passport[Field.expirationYear]) - && isValidHeight(passport[Field.height]) - && isValidHairColor(passport[Field.hairColor]) - && isValidEyeColor(passport[Field.eyeColor]) - && isValidPassportID(passport[Field.passportID]); + // dfmt off + auto validators = [ + "byr" : s => s.length == 4 && s.all!isDigit && s.to!int.isBetween(1920, 2002), + "iyr" : s => s.length == 4 && s.all!isDigit && s.to!int.isBetween(2010, 2020), + "eyr" : s => s.length == 4 && s.all!isDigit && s.to!int.isBetween(2020, 2030), + "hgt" : &isValidHeight, + "hcl" : s => s.matchFirst(r"^#[0-9a-f]{6}$").to!bool, + "ecl" : s => [ "amb", "blu", "brn", "gry", "grn", "hzl", "oth" ].canFind(s), + "pid" : s => s.matchFirst(r"^\d{9}$").to!bool + ]; + // dfmt on + + return validators.byKeyValue.all!(validator => validator.key in passport + && validator.value()(passport[validator.key])); } auto countValidPassports(R)(R r) if (isInputRange!R && is(ElementType!R == Passport))