diff --git a/AOC2020/AOC2020.csproj b/AOC2020/AOC2020.csproj index a1bba53..44ca9e1 100644 --- a/AOC2020/AOC2020.csproj +++ b/AOC2020/AOC2020.csproj @@ -26,4 +26,8 @@ + + + + diff --git a/AOC2020/Day04.cs b/AOC2020/Day04.cs index 669d558..224e853 100644 --- a/AOC2020/Day04.cs +++ b/AOC2020/Day04.cs @@ -1,3 +1,5 @@ +using MoreLinq; + namespace AOC2020; /// @@ -5,176 +7,80 @@ namespace AOC2020; /// public sealed partial class Day04 : Day { - private List? _passports; + private List>? _passports; public Day04() : base(2020, 4, "Passport Processing") { } - public override void ProcessInput() + public override void ProcessInput() => + _passports = Input.Split("").Select(Parse).ToList(); + + [GeneratedRegex("#[0-9a-f]{6}")] + private static partial Regex HexColor(); + + private static Dictionary Parse(IEnumerable list) => + string.Join(' ', list).Split(' ', StringSplitOptions.TrimEntries) + .ToDictionary(k => k.Split(':', 2)[0], v => v.Split(':', 2)[1]); + + private static bool IsValid(Dictionary d) => + new[] { "byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid" }.All(d.ContainsKey); + + private static bool ExtendedValidation(Dictionary d) { - _passports = new(); + if (!IsValid(d)) return false; - var a = new List(); - foreach (var line in Input) + // birth year + if (int.TryParse(d["byr"], out var byr)) { - if (line == "") - { - _passports.Add(Passport.Parse(a)); - a.Clear(); - continue; - } - - a.Add(line); + if (byr is < 1920 or > 2002) return false; } + else return false; - if (a.Any()) _passports.Add(Passport.Parse(a)); + // issuance year + if (int.TryParse(d["iyr"], out var iyr)) + { + if (iyr is < 2010 or > 2020) return false; + } + else return false; + + // expiration year + if (int.TryParse(d["eyr"], out var eyr)) + { + if (eyr is < 2020 or > 2030) return false; + } + else return false; + + // height + if (d["hgt"].EndsWith("cm")) + { + if (int.TryParse(d["hgt"][..3], out var hgt)) + { + if (hgt is < 150 or > 193) return false; + } + else return false; + } + else if (d["hgt"].EndsWith("in")) + { + if (int.TryParse(d["hgt"][..2], out var hgt)) + { + if (hgt is < 59 or > 76) return false; + } + else return false; + } + else return false; + + // hair color + if (!HexColor().IsMatch(d["hcl"])) return false; + + // eye color + if (!new[] { "amb", "blu", "brn", "gry", "grn", "hzl", "oth" }.Contains(d["ecl"])) + return false; + + // passport id + return !d.ContainsKey("pid") || d["pid"].Length == 9; } - public override object Part1() => _passports!.Count(p => p.IsValid); - - public override object Part2() => _passports!.Count(p => p.ExtendedValidation()); - - private partial class Passport - { - private string? _byr; - private string? _cid; - private string? _ecl; - private string? _eyr; - private string? _hcl; - private string? _hgt; - private string? _iyr; - private string? _pid; - - public bool IsValid => - _byr != null && - _iyr != null && - _eyr != null && - _hgt != null && - _hcl != null && - _ecl != null && - _pid != null; - - public bool ExtendedValidation() - { - if (!IsValid) return false; - - // birth year - if (int.TryParse(_byr, out var byr)) - { - if (byr is < 1920 or > 2002) - return false; - } - else - { - return false; - } - - // issuance year - if (int.TryParse(_iyr, out var iyr)) - { - if (iyr is < 2010 or > 2020) - return false; - } - else - { - return false; - } - - // expiration year - if (int.TryParse(_eyr, out var eyr)) - { - if (eyr is < 2020 or > 2030) - return false; - } - else - { - return false; - } - - // height - if (_hgt!.EndsWith("cm")) - { - var h = _hgt[..3]; - if (int.TryParse(h, out var hgt)) - { - if (hgt is < 150 or > 193) - return false; - } - else - { - return false; - } - } - else if (_hgt.EndsWith("in")) - { - var h = _hgt[..2]; - if (int.TryParse(h, out var hgt)) - { - if (hgt is < 59 or > 76) - return false; - } - else - { - return false; - } - } - else - { - return false; - } - - // hair color - if (!HexColor().IsMatch(_hcl!)) - return false; - - // eye color - if (!new[] { "amb", "blu", "brn", "gry", "grn", "hzl", "oth" }.Contains(_ecl)) - return false; - - // passport id - return _pid == null || _pid.Length == 9; - } - - public static Passport Parse(IEnumerable list) - { - var passport = new Passport(); - foreach (var entry in string.Join(' ', list).Split(' ', StringSplitOptions.TrimEntries)) - { - var spl = entry.Split(':', 2); - switch (spl[0]) - { - case "byr": - passport._byr = spl[1]; - break; - case "iyr": - passport._iyr = spl[1]; - break; - case "eyr": - passport._eyr = spl[1]; - break; - case "hgt": - passport._hgt = spl[1]; - break; - case "hcl": - passport._hcl = spl[1]; - break; - case "ecl": - passport._ecl = spl[1]; - break; - case "pid": - passport._pid = spl[1]; - break; - case "cid": - passport._cid = spl[1]; - break; - } - } - - return passport; - } - - [GeneratedRegex("#[0-9a-f]{6}")] - private static partial Regex HexColor(); - } -} + public override object Part1() => _passports!.Count(IsValid); + public override object Part2() => _passports!.Count(ExtendedValidation); +} \ No newline at end of file