generated from sindrekjr/AdventOfCodeBase
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Solution.cs
134 lines (109 loc) · 3.67 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
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
using System.Text.RegularExpressions;
namespace AdventOfCode.Solutions.Year2021.Day18;
class Solution : SolutionBase
{
public Solution() : base(18, 2021, "Snailfish") { }
protected override string SolvePartOne() =>
CalculateMagnitude(Input.SplitByNewline().Aggregate(Add)).ToString();
protected override string SolvePartTwo()
{
var sums = new List<string>();
var lines = Input.SplitByNewline();
for (int i = 0; i < lines.Length; i++) for (int j = i + 1; j < lines.Length; j++)
{
sums.Add(Add(lines[i], lines[j]));
sums.Add(Add(lines[j], lines[i]));
}
return sums.Max(sum => CalculateMagnitude(sum)).ToString();
}
long CalculateMagnitude(string sum)
{
if (!sum.Contains('[') && !sum.Contains(']') && sum.Any())
{
var nums = sum.Split(",").Select(int.Parse).ToArray();
if (nums.Length == 1) return nums[0];
return 3 * nums[0] + 2 * nums[1];
}
var depth = 0;
var first = "";
for (int i = 0; i < sum.Length; i++)
{
var ch = sum[i];
first += ch;
if (ch == '[') depth++;
if (ch == ']') depth--;
if (depth <= 0) break;
}
if (first.Length == sum.Count()) return CalculateMagnitude(first.Skip(1).SkipLast(1).JoinAsStrings());
depth = 0;
var second = "";
for (int i = first.Length + 1; i < sum.Length; i++)
{
var ch = sum[i];
second += ch;
if (ch == '[') depth++;
if (ch == ']') depth--;
if (depth <= 0) break;
}
return 3 * CalculateMagnitude(first) + 2 * CalculateMagnitude(second);
}
string Add(string first, string second) => ReduceLine($"[{first},{second}]");
string ReduceLine(string line)
{
while (true)
{
var prev = line;
var exploded = ExplodeOne(line);
if (exploded != prev)
{
line = exploded;
continue;
}
var split = SplitOne(line);
if (split != prev)
{
line = split;
continue;
}
return prev;
}
}
Regex ExStaRx = new Regex(@"(\d+)(\D+)$");
Regex ExEndRx = new Regex(@"(\d+)");
string ExplodeOne(string line)
{
var depth = 0;
for (int i = 0; i < line.Length; i++)
{
var ch = line[i];
if (ch == '[') depth++;
if (ch == ']') depth--;
if (depth > 4)
{
var match = Regex.Match(line.Substring(i), @"(\d+),(\d+)");
var full = match.Value;
var (left, right, _) = full.Split(",");
var start = line.Substring(0, i);
start = ExStaRx.Replace(start, m =>
{
var (_, d, p) = m.Groups.Values.Select(v => v.Value).ToArray();
return $"{int.Parse(d) + int.Parse(left)}{p.JoinAsStrings()}";
}, 1);
var end = line.Substring(i + full.Length + 2);
end = ExEndRx.Replace(end, m =>
{
var val = m.Value;
return $"{int.Parse(val) + int.Parse(right)}";
}, 1);
return $"{start}0{end}";
}
}
return line;
}
Regex SplitRx = new Regex(@"(\d\d+)");
string SplitOne(string line) => SplitRx.Replace(line, match =>
{
var value = int.Parse(match.Value);
return $"[{Math.Floor(value / 2d)},{Math.Ceiling(value / 2d)}]";
}, 1);
}