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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
using System;
using System.Collections.Generic;
using System.Linq;
namespace aoc2019
{
internal class Day15 : Day
{
public override int DayNumber => 15;
private Dictionary<string, long>? available;
private readonly Dictionary<string, Reaction>? reactions;
private struct Component
{
public string Name { get; set; }
public int Quantity { get; set; }
}
private class Reaction
{
public Component product;
public Component[] reactants;
public Reaction(Component[] reactants, Component product)
{
this.reactants = reactants;
this.product = product;
}
public static Reaction Parse(string s)
{
var ss = s.Split(new[] { ", ", " => " }, System.StringSplitOptions.None);
return new Reaction(
ss.Take(ss.Length - 1).Select(ParseComponent).ToArray(),
ParseComponent(ss[^1])
);
static Component ParseComponent(string s)
{
var i = s.IndexOf(' ');
return new Component
{
Name = s[(i + 1)..],
Quantity = int.Parse(s.Substring(i))
};
}
}
}
private bool Consume(string chem, long quantity)
{
if (quantity <= 0)
throw new ArgumentOutOfRangeException();
if (!available!.ContainsKey(chem))
available[chem] = 0;
if (available[chem] < quantity && !Produce(chem, quantity - available[chem]))
return false;
available[chem] -= quantity;
return true;
}
private bool Produce(string chem, long quantity)
{
if (chem == "ORE")
return false;
var reaction = reactions[chem];
var reactionCount = (long)Math.Ceiling((double)quantity / reaction.product.Quantity);
foreach (var reactant in reaction.reactants)
if (!Consume(reactant.Name, reactionCount * reactant.Quantity))
return false;
available![chem] = available.GetValueOrDefault(chem) + reactionCount * reaction.product.Quantity;
return true;
}
public Day15()
{
reactions = Input
.Select(Reaction.Parse)
.ToDictionary(r => r.product.Name);
}
public override string Part1()
{
available = new Dictionary<string, long> { { "ORE", long.MaxValue } };
Consume("FUEL", 1);
return $"{long.MaxValue - available["ORE"]}";
}
public override string Part2()
{
return "";
}
}
}
|