2020-12-07 19:34:10 +00:00
|
|
|
using System;
|
|
|
|
using static System.Console;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
namespace AdventOfCode {
|
|
|
|
|
|
|
|
struct Contains {
|
|
|
|
public Contains(string outer, string inner, int count) {
|
|
|
|
Outer = outer;
|
|
|
|
Inner = inner;
|
|
|
|
Count = count;
|
|
|
|
}
|
|
|
|
public string Outer;
|
|
|
|
public string Inner;
|
|
|
|
public int Count;
|
|
|
|
|
|
|
|
public override string ToString() {
|
|
|
|
return $"{Outer} contains {Count} {Inner}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class Day07 {
|
|
|
|
|
|
|
|
static void AddRules(string rule, List<Contains> contains) {
|
|
|
|
string[] tokens = rule.Split(" bags contain ");
|
|
|
|
string color = tokens[0];
|
|
|
|
string[] otherBags = tokens[1].Split(", ");
|
|
|
|
foreach (var s in otherBags) {
|
|
|
|
Match m = Regex.Match(s, @"^(\d+) (\w+ \w+) bag");
|
|
|
|
if (!m.Success) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int count = int.Parse(m.Groups[1].Value);
|
|
|
|
Contains c = new Contains(color, m.Groups[2].Value, count);
|
|
|
|
contains.Add(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-07 19:40:23 +00:00
|
|
|
static List<Contains> ParseRules(string[] rules) {
|
2020-12-07 19:34:10 +00:00
|
|
|
var contains = new List<Contains>();
|
|
|
|
rules.ToList().ForEach(rule => AddRules(rule, contains));
|
2020-12-07 19:40:23 +00:00
|
|
|
return contains;
|
|
|
|
}
|
2020-12-07 19:34:10 +00:00
|
|
|
|
2020-12-07 19:40:23 +00:00
|
|
|
static int ComputePart1(List<Contains> contains) {
|
2020-12-07 19:34:10 +00:00
|
|
|
int setSize = 0;
|
|
|
|
var result = new HashSet<string>();
|
|
|
|
result.Add("shiny gold");
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
foreach (Contains c in contains) {
|
|
|
|
if (result.Contains(c.Inner)) {
|
|
|
|
result.Add(c.Outer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (result.Count() == setSize) { // nothing new to add, we're done
|
|
|
|
return result.Count() - 1; // shiny gold doesn't contain itself
|
|
|
|
}
|
|
|
|
setSize = result.Count();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-07 19:47:24 +00:00
|
|
|
static int CountBags(List<Contains> rules, string target) {
|
|
|
|
int total = 1;
|
|
|
|
foreach (Contains rule in rules) {
|
|
|
|
if (rule.Outer == target) {
|
|
|
|
total += rule.Count * CountBags(rules, rule.Inner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
2020-12-07 19:34:10 +00:00
|
|
|
static int Part1() {
|
2020-12-07 19:40:23 +00:00
|
|
|
List<Contains> contains = ParseRules(File.ReadAllLines(Util.RootDir + "day07.txt"));
|
|
|
|
return ComputePart1(contains);
|
2020-12-07 19:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int Part2() {
|
2020-12-07 19:40:23 +00:00
|
|
|
List<Contains> contains = ParseRules(File.ReadAllLines(Util.RootDir + "day07.txt"));
|
2020-12-07 19:47:24 +00:00
|
|
|
return CountBags(contains, "shiny gold") - 1;
|
2020-12-07 19:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
public static void Test() {
|
|
|
|
string[] example =
|
|
|
|
@"light red bags contain 1 bright white bag, 2 muted yellow bags.
|
|
|
|
dark orange bags contain 3 bright white bags, 4 muted yellow bags.
|
|
|
|
bright white bags contain 1 shiny gold bag.
|
|
|
|
muted yellow bags contain 2 shiny gold bags, 9 faded blue bags.
|
|
|
|
shiny gold bags contain 1 dark olive bag, 2 vibrant plum bags.
|
|
|
|
dark olive bags contain 3 faded blue bags, 4 dotted black bags.
|
|
|
|
vibrant plum bags contain 5 faded blue bags, 6 dotted black bags.
|
|
|
|
faded blue bags contain no other bags.
|
|
|
|
dotted black bags contain no other bags.".Split('\n');
|
|
|
|
|
2020-12-07 19:40:23 +00:00
|
|
|
Assert.Equal(4, ComputePart1(ParseRules(example)));
|
2020-12-07 19:34:10 +00:00
|
|
|
Assert.Equal(213, Part1());
|
2020-12-07 19:47:24 +00:00
|
|
|
|
|
|
|
string[] example2 =
|
|
|
|
@"shiny gold bags contain 2 dark red bags.
|
|
|
|
dark red bags contain 2 dark orange bags.
|
|
|
|
dark orange bags contain 2 dark yellow bags.
|
|
|
|
dark yellow bags contain 2 dark green bags.
|
|
|
|
dark green bags contain 2 dark blue bags.
|
|
|
|
dark blue bags contain 2 dark violet bags.
|
|
|
|
dark violet bags contain no other bags.".Split('\n');
|
|
|
|
Assert.Equal(127, CountBags(ParseRules(example2), "shiny gold"));
|
|
|
|
|
|
|
|
Assert.Equal(38426, Part2());
|
2020-12-07 19:34:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|