-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay7.cs
151 lines (122 loc) · 4.4 KB
/
Day7.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace AdventOfCode2018
{
class Day7 : Day
{
SortedDictionary<char, Step> steps = new SortedDictionary<char, Step>();
public override bool Test()
{
return Utils.Test(Part1, testInput, "CABDFE") &&
Utils.Test(Part2, testInput, "15", new { basetime = 0, elves = 2 });
}
public override dynamic Options => new { basetime = 60, elves = 5 };
public override string Part1(string input, dynamic options)
{
parseInput(input);
string result = "";
while (true)
{
var next = steps.Values.Where(s => !s.Complete && s.dependencies.Count == 0).FirstOrDefault();
if (next == null)
{
return result;
}
next.MarkComplete();
result += next.ID;
}
}
private void parseInput(string input)
{
var dependencies = Utils.splitLines((string)input).Select(l => (l[5], l[36]));
steps.Clear();
foreach (var pair in dependencies)
{
var step1 = GetStep(pair.Item1);
var step2 = GetStep(pair.Item2);
step2.dependencies.Add(step1);
step1.dependants.Add(step2);
}
}
private Step GetStep(char ID)
{
if (!steps.ContainsKey(ID))
{
steps.Add(ID, new Step() { ID = ID });
}
return steps[ID];
}
public override string Part2(string input, dynamic options)
{
parseInput(input);
string output = "";
for (int tick = 0; true; tick++)
{
foreach (var step in steps.Values)
{
step.Tick(tick);
if (step.CompleteAtStartOfTick == tick)
{
output += step.ID;
}
}
var available = steps.Values.Where(s => !s.Complete && !s.InProgress(tick) && s.dependencies.Count == 0).ToList();
var workers = options.elves - steps.Values.Where(s => s.InProgress(tick)).Count();
for (int i = 0; i < workers && i < available.Count; i++)
{
available[i].Start(tick, options.basetime);
}
if (steps.Values.All(s => s.Complete))
{
return tick.ToString();
}
}
}
private string testInput =
@"Step C must be finished before step A can begin.
Step C must be finished before step F can begin.
Step A must be finished before step B can begin.
Step A must be finished before step D can begin.
Step B must be finished before step E can begin.
Step D must be finished before step E can begin.
Step F must be finished before step E can begin.";
private class Step
{
public char ID;
public int Duration => (ID - 'A') + 1;
public List<Step> dependencies = new List<Step>();
public List<Step> dependants = new List<Step>();
public bool Complete;
public int CompleteAtStartOfTick = int.MaxValue;
public void Tick(int currentTick)
{
if (currentTick == CompleteAtStartOfTick)
{
MarkComplete();
}
}
public void Start(int currentTick, int tickBase)
{
CompleteAtStartOfTick = currentTick + tickBase + Duration;
}
public bool InProgress(int currentTick)
{
return CompleteAtStartOfTick < int.MaxValue && CompleteAtStartOfTick > currentTick;
}
public void MarkComplete()
{
Complete = true;
foreach (var step in dependants)
{
step.dependencies.Remove(this);
}
}
}
}
}