using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; namespace _2020 { class Q07 { class BagType { public string BagName; public List> ValidContents = new List>(); } static readonly Regex bagRegex = new Regex(@"(?: contain |, )?(?[0-9]+ )?(?.+?) bags?", RegexOptions.Compiled); static readonly List list = new List(); public static void Go() { MakeList(); Part1(); Part2(); } static void MakeList() { var lines = File.ReadAllLines("07input.txt"); foreach (var line in lines) { var matches = bagRegex.Matches(line); if (matches.Count <= 1) { throw new Exception("Unexpected input line"); } var bag = new BagType() { BagName = matches[0].Groups["bagType"].Value, }; for (int i = 1; i < matches.Count; i++) { if (matches[i].Groups["bagType"].Value == "no other") { break; } bag.ValidContents.Add(new Tuple(matches[i].Groups["bagType"].Value, Convert.ToInt32(matches[i].Groups["numBags"].Value))); } list.Add(bag); } } static List GetBagsCanContain(BagType checkBag) { var retval = new List(); foreach (var bag in list) { if (bag.ValidContents.FirstOrDefault(x => x.Item1 == checkBag.BagName) != null) { retval.Add(bag); } } return retval; } static List GetCanContainAny(List others) { var retval = new List(); foreach (var other in others) { retval.AddRange(GetBagsCanContain(other)); } return retval; } static void Part1() { static List bagAgg(List accum, BagType bagType) { accum.Add(bagType.BagName); return accum; } var directContain = GetBagsCanContain(new BagType() { BagName = "shiny gold" }); var totalContain = directContain.Aggregate(new List(), bagAgg); var recursiveContain = GetCanContainAny(directContain); while (recursiveContain.Count > 0) { totalContain.AddRange(recursiveContain.Aggregate(new List(), bagAgg)); recursiveContain = GetCanContainAny(recursiveContain); } var result = totalContain.Distinct(); Util.Log($"Q07Part1: total contain={result.Count()}"); } static int GetNumBagsContainedIn(BagType bag) { int bagsNeeded = 0; foreach (var contain in bag.ValidContents) { var containBagRule = list.First(x => x.BagName == contain.Item1); bagsNeeded += contain.Item2; bagsNeeded += contain.Item2 * GetNumBagsContainedIn(containBagRule); } return bagsNeeded; } static void Part2() { var shinyGoldBag = list.First(x => x.BagName == "shiny gold"); int bagsNeeded = GetNumBagsContainedIn(shinyGoldBag); Util.Log($"Q07Part2: bags needed={bagsNeeded}"); } } }