tidy 2020 day 4 using a dict
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
8006ba69bd
commit
3479122a05
|
@ -26,4 +26,8 @@
|
||||||
<ProjectReference Include="..\AOC.Common\AOC.Common.csproj" />
|
<ProjectReference Include="..\AOC.Common\AOC.Common.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="morelinq" Version="3.3.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
228
AOC2020/Day04.cs
228
AOC2020/Day04.cs
|
@ -1,3 +1,5 @@
|
||||||
|
using MoreLinq;
|
||||||
|
|
||||||
namespace AOC2020;
|
namespace AOC2020;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -5,176 +7,80 @@ namespace AOC2020;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class Day04 : Day
|
public sealed partial class Day04 : Day
|
||||||
{
|
{
|
||||||
private List<Passport>? _passports;
|
private List<Dictionary<string, string>>? _passports;
|
||||||
|
|
||||||
public Day04() : base(2020, 4, "Passport Processing")
|
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<string, string> Parse(IEnumerable<string> list) =>
|
||||||
|
string.Join(' ', list).Split(' ', StringSplitOptions.TrimEntries)
|
||||||
|
.ToDictionary(k => k.Split(':', 2)[0], v => v.Split(':', 2)[1]);
|
||||||
|
|
||||||
|
private static bool IsValid(Dictionary<string, string> d) =>
|
||||||
|
new[] { "byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid" }.All(d.ContainsKey);
|
||||||
|
|
||||||
|
private static bool ExtendedValidation(Dictionary<string, string> d)
|
||||||
{
|
{
|
||||||
_passports = new();
|
if (!IsValid(d)) return false;
|
||||||
|
|
||||||
var a = new List<string>();
|
// birth year
|
||||||
foreach (var line in Input)
|
if (int.TryParse(d["byr"], out var byr))
|
||||||
{
|
{
|
||||||
if (line == "")
|
if (byr is < 1920 or > 2002) return false;
|
||||||
{
|
|
||||||
_passports.Add(Passport.Parse(a));
|
|
||||||
a.Clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Add(line);
|
|
||||||
}
|
}
|
||||||
|
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 Part1() => _passports!.Count(IsValid);
|
||||||
|
public override object Part2() => _passports!.Count(ExtendedValidation);
|
||||||
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<string> 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();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue