Files
2020/Q07.cs

128 lines
3.4 KiB
C#

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<Tuple<string, int>> ValidContents = new List<Tuple<string, int>>();
}
static readonly Regex bagRegex = new Regex(@"(?: contain |, )?(?<numBags>[0-9]+ )?(?<bagType>.+?) bags?", RegexOptions.Compiled);
static readonly List<BagType> list = new List<BagType>();
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<string, int>(matches[i].Groups["bagType"].Value, Convert.ToInt32(matches[i].Groups["numBags"].Value)));
}
list.Add(bag);
}
}
static List<BagType> GetBagsCanContain(BagType checkBag)
{
var retval = new List<BagType>();
foreach (var bag in list)
{
if (bag.ValidContents.FirstOrDefault(x => x.Item1 == checkBag.BagName) != null)
{
retval.Add(bag);
}
}
return retval;
}
static List<BagType> GetCanContainAny(List<BagType> others)
{
var retval = new List<BagType>();
foreach (var other in others)
{
retval.AddRange(GetBagsCanContain(other));
}
return retval;
}
static void Part1()
{
static List<string> bagAgg(List<string> accum, BagType bagType)
{
accum.Add(bagType.BagName);
return accum;
}
var directContain = GetBagsCanContain(new BagType() { BagName = "shiny gold" });
var totalContain = directContain.Aggregate(new List<string>(), bagAgg);
var recursiveContain = GetCanContainAny(directContain);
while (recursiveContain.Count > 0)
{
totalContain.AddRange(recursiveContain.Aggregate(new List<string>(), 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}");
}
}
}