ben
/
aoc
1
0
Fork 0
aoc/AOC2020/Day07.cs

55 lines
1.7 KiB
C#

namespace AOC2020;
/// <summary>
/// Day 7: <see href="https://adventofcode.com/2020/day/7" />
/// </summary>
public sealed class Day07 : Day
{
private readonly Dictionary<string, IEnumerable<(int Weight, string Name)?>> _rules;
public Day07() : base(2020, 7, "Handy Haversacks") =>
_rules = Input
.Select(rule =>
{
var spl = rule.Split(" bags contain ", 2);
var outer = string.Join(' ', spl[0].Split(' ').Take(2));
var inner = spl[1].Split(", ").Select(ParseQuantity).Where(i => i != null);
return (outer, inner);
})
.ToDictionary(t => t.outer, t => t.inner);
private static (int, string)? ParseQuantity(string arg)
{
if (arg == "no other bags.") return null;
var words = arg.Split(' ');
return (int.Parse(words[0]), string.Join(' ', words[1..3]));
}
private int Weight(string node) =>
1 + _rules[node]
.Where(i => i.HasValue)
.Select(i => i!.Value)
.Sum(i => i.Weight * Weight(i.Name));
public override string Part1()
{
// breadth-first search with Queue
var start = new Queue<string>(new[] { "shiny gold" });
var p = new HashSet<string>();
string node;
while (true)
{
node = start.Dequeue();
foreach (var (container, contained) in _rules)
if (contained.Any(i => i.HasValue && i.Value.Name == node) && p.Add(container))
start.Enqueue(container);
if (!start.Any()) break;
}
return $"{p.Count}";
}
public override string Part2() => $"{Weight("shiny gold") - 1}";
}