-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.cs
88 lines (73 loc) · 2.8 KB
/
Solution.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace AdventOfCode2020.Day21
{
internal class Solution
{
private readonly IReadOnlyCollection<Food> _foods;
public Solution(IEnumerable<string> input)
{
_foods = input.Select(ParseFood).ToList();
}
public int PartOne()
{
var ingredientsByAllergen = GetIngredientsByAllergen();
return _foods
.SelectMany(food => food.Ingredients)
.Count(ingredient => ingredientsByAllergen.All(pair => !pair.Value.Contains(ingredient)));
}
public string PartTwo()
{
var allergenToPossibleIngredients = GetIngredientsByAllergen();
var ingredientToAllergen = new Dictionary<string, string>();
while (allergenToPossibleIngredients.Count > 0)
{
foreach (var (allergen, ingredients) in allergenToPossibleIngredients)
{
var ingredientsLeft = ingredients.Except(ingredientToAllergen.Keys).ToList();
if (ingredientsLeft.Count != 1)
continue;
ingredientToAllergen[ingredientsLeft.Single()] = allergen;
allergenToPossibleIngredients.Remove(allergen);
break;
}
}
var result = ingredientToAllergen.OrderBy(x => x.Value).Select(x => x.Key);
return string.Join(",", result);
}
private static Food ParseFood(string line)
{
var ingredientsAndAllergens = line.Split(" (contains ");
var ingredients = ingredientsAndAllergens[0].Split(" ");
var allergens = ingredientsAndAllergens[1].TrimEnd(')').Split(", ");
return new Food(ingredients, allergens);
}
private IDictionary<string, ISet<string>> GetIngredientsByAllergen()
{
var result = new Dictionary<string, ISet<string>>();
foreach (var food in _foods)
{
foreach (var allergen in food.Allergens)
{
if (!result.ContainsKey(allergen))
result[allergen] = food.Ingredients.ToHashSet();
else
result[allergen].IntersectWith(food.Ingredients);
}
}
return result;
}
}
internal class Food
{
public Food(IReadOnlyCollection<string> ingredients, IReadOnlyCollection<string> allergens)
{
Ingredients = ingredients;
Allergens = allergens;
}
public IReadOnlyCollection<string> Ingredients { get; }
public IReadOnlyCollection<string> Allergens { get; }
}
}