// #define Day18_2 #if Day18_2 using System.Text.RegularExpressions; var lines = File.ReadAllLines("day18/input"); var numberToSplit = new Regex(@"\d{2,}"); var numbersToMatch = new Regex(@"\d+"); var cur = lines.First(); foreach (var l in lines.Skip(1)) { cur = Add(cur, l); cur = Reduce(cur); } var bla = Node.Parse(cur); Console.WriteLine(bla); Console.WriteLine(bla.Magnitude()); List magnitudes = new List(); for (int i = 0; i < lines.Length; i++) { for (int j = 0; j < lines.Length; j++) { if (i == j) {continue;} var test = Add(lines[i], lines[j]); var reducedTest = Reduce(test); magnitudes.Add(Node.Parse(reducedTest).Magnitude()); var testReverse = Add(lines[j], lines[i]); var reducedTestReverse = Reduce(testReverse); magnitudes.Add(Node.Parse(reducedTestReverse).Magnitude()); } } Console.WriteLine(magnitudes.Max()); string Reduce(string number) { bool changed = false; do { (changed, number) = Explode(number); if (!changed) { (changed, number) = Split(number); } } while (changed); return number; } Changed Explode(string number) { int depth = 0; int pos = 0; while (depth < 5 && pos < number.Length) { if (number[pos] == '[') { depth++; } else if (number[pos] == ']'){ depth--; } pos++; } if (depth < 5) { return new Changed(false, number); } int startOfExplode = pos; while (number[pos] != ']') { pos++; } int endOfExplode = pos; var exploded = number.Substring(startOfExplode, endOfExplode - startOfExplode); var explodedNumbers = exploded.Split(",").Select(int.Parse).ToList(); var matches = numbersToMatch.Matches(number); var leftAddMatch = matches.Where(m => m.Index < startOfExplode).MaxBy(m => m.Index); var rightAddMatch = matches.Where(m => m.Index > endOfExplode).MinBy(m => m.Index); if (leftAddMatch != null && rightAddMatch != null) { var before = number.Substring(0, leftAddMatch.Index); var after = number.Substring(rightAddMatch.Index + rightAddMatch.Length, number.Length - rightAddMatch.Index - rightAddMatch.Length); var beforeExplosion = number.Substring(leftAddMatch.Index + leftAddMatch.Length, startOfExplode - leftAddMatch.Index - leftAddMatch.Length - 1); var afterExplosion = number.Substring(endOfExplode + 1, rightAddMatch.Index - endOfExplode - 1); var leftAdded = int.Parse(leftAddMatch.Value) + explodedNumbers[0]; var rightAdded = int.Parse(rightAddMatch.Value) + explodedNumbers[1]; return new Changed(true, $"{before}{leftAdded}{beforeExplosion}0{afterExplosion}{rightAdded}{after}"); } else if (leftAddMatch == null) { var before = number.Substring(0, startOfExplode - 1); var after = number.Substring(rightAddMatch.Index + rightAddMatch.Length, number.Length - rightAddMatch.Index - rightAddMatch.Length); var afterExplosion = number.Substring(endOfExplode + 1, rightAddMatch.Index - endOfExplode - 1); var rightAdded = int.Parse(rightAddMatch.Value) + explodedNumbers[1]; return new Changed(true, $"{before}0{afterExplosion}{rightAdded}{after}"); } else if (rightAddMatch == null) { var before = number.Substring(0, leftAddMatch.Index); var after = number.Substring(endOfExplode + 1, number.Length - endOfExplode - 1); var beforeExplosion = number.Substring(leftAddMatch.Index + leftAddMatch.Length, startOfExplode - leftAddMatch.Index - leftAddMatch.Length - 1); var leftAdded = int.Parse(leftAddMatch.Value) + explodedNumbers[0]; return new Changed(true, $"{before}{leftAdded}{beforeExplosion}0{after}"); } throw new ArgumentException(); } Changed Split(string number) { var m = numberToSplit.Match(number); if (!m.Success) { return new Changed(false, number); } var before = number.Substring(0, m.Index); var after = number.Substring(m.Index + m.Length, number.Length - m.Index - m.Length); var value = int.Parse(m.Value); int first = value / 2; int second = value - first; return new Changed(true, $"{before}[{first},{second}]{after}"); } string Add(string first, string second) { return $"[{first},{second}]"; } record Changed(bool changed, string number); class Node { public Node? Parent { get; set; } public Node? Left { get; set; } public Node? Right { get; set; } public int? Leaf { get; set; } public string Print() { if (Leaf != null) { return $"{Leaf}"; } else { return $"[{Left.Print()},{Right.Print()}]"; } } public long Magnitude() { if (Leaf != null) { return Leaf ?? -9999; } return 3 * Left.Magnitude() + 2 * Right.Magnitude(); } public static Node Parse(string number) { int pos = 0; return Parse(ref pos, number, null); } public static Node Parse(ref int pos, string number, Node parent) { var cur = new Node() {Parent = parent}; if (number[pos] == '[') { pos++; cur.Left = Node.Parse(ref pos, number, cur); pos++; // ignore comma cur.Right = Node.Parse(ref pos, number, cur); pos++; // ignore closing bracket } else { // for debugging int i = 0; while ("1234567890".Contains(number[pos + i])) { i++; } cur.Leaf = int.Parse(number.Substring(pos, i)); pos += i; } return cur; } public override string ToString() { return Print(); } } #endif