|
|
using System; using static System.Console; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using Xunit;
namespace AdventOfCode {
public class Day04 {
static string[] requiredFields = { // "cid" not required because we are hackers
"byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid" };
static string[] validEyeColors = { "amb", "blu", "brn", "gry", "grn", "hzl", "oth" };
static bool IsValidPassport1(string input) { string[] fields = input.Split(' '); var fieldsPresent = new HashSet<string>(); foreach (string field in fields) { string[] tokens = field.Split(':'); string key = tokens[0]; fieldsPresent.Add(key); } return fieldsPresent.IsSupersetOf(requiredFields); }
static int ParseInt(string value) { int result; if (!int.TryParse(value, out result)) { return -1; } return result; }
static bool ValidateYear(string value, int min, int max) { int year = ParseInt(value); return year >= min && year <= max; }
static bool ValidateHeight(string value) { string unit = value.Substring(value.Length - 2); int amount = ParseInt(value.Substring(0, value.Length - 2)); if (unit == "cm") { return amount >= 150 && amount <= 193; } else if (unit == "in") { return amount >= 59 && amount <= 76; } else { // not cm or in
return false; } }
static bool IsValidPassport2(string input) { string[] fields = input.Split(' '); var fieldsPresent = new HashSet<string>(); foreach (string field in fields) { if (field.Length == 0) { continue; } string[] tokens = field.Split(':'); string key = tokens[0]; string value = tokens[1]; bool valid = key switch { "byr" => ValidateYear(value, 1920, 2002), "iyr" => ValidateYear(value, 2010, 2020), "eyr" => ValidateYear(value, 2020, 2030), "hgt" => ValidateHeight(value), "hcl" => Regex.IsMatch(value, @"^#[0-9a-f]{6}$"), "ecl" => validEyeColors.Contains(value), "pid" => Regex.IsMatch(value, @"^[0-9]{9}$"), _ => false }; if (valid) { fieldsPresent.Add(key); } } return fieldsPresent.IsSupersetOf(requiredFields); }
static List<string> ParsePassports(string[] input) { var result = new List<string>(); string passport = ""; foreach (string line in input) { if (line == "") { result.Add(passport); passport = ""; } else { passport += line + " "; } } result.Add(passport); return result; }
static int CountValidPassports1(string[] input) { return ParsePassports(input).Count(IsValidPassport1); }
static int CountValidPassports2(string[] input) { return ParsePassports(input).Count(IsValidPassport2); }
static int Part1() { string[] input = File.ReadAllLines(Util.RootDir + "day04.txt"); return CountValidPassports1(input); }
static int Part2() { string[] input = File.ReadAllLines(Util.RootDir + "day04.txt"); return CountValidPassports2(input); }
[Fact] public static void Test() { string[] example = @"ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
byr:1937 iyr:2017 cid:147 hgt:183cm
iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 hcl:#cfa07d byr:1929
hcl:#ae17e1 iyr:2013 eyr:2024 ecl:brn pid:760753108 byr:1931 hgt:179cm
hcl:#cfa07d eyr:2025 pid:166559648 iyr:2011 ecl:brn hgt:59in".Split('\n');
Assert.Equal(2, CountValidPassports1(example)); Assert.Equal(256, Part1());
string[] invalidPassports = @"eyr:1972 cid:100
hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926
iyr:2019 hcl:#602927 eyr:1967 hgt:170cm ecl:grn pid:012533040 byr:1946
hcl:dab227 iyr:2012 ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277
hgt:59cm ecl:zzz eyr:2038 hcl:74454a iyr:2023 pid:3556412378 byr:2007".Split('\n');
string[] validPassports = @"pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
hcl:#623a2f
eyr:2029 ecl:blu cid:129 byr:1989 iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm
hcl:#888785 hgt:164cm byr:2001 iyr:2015 cid:88 pid:545766238 ecl:hzl eyr:2022
iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719".Split('\n');
List<string> invalid = ParsePassports(invalidPassports); Assert.Equal(4, invalid.Count); Assert.All(invalid, item => Assert.False(IsValidPassport2(item)));
List<string> valid = ParsePassports(validPassports); Assert.Equal(4, valid.Count); Assert.All(valid, item => Assert.True(IsValidPassport2(item)));
Assert.Equal(198, Part2()); } } }
|