// #define Day18 #if Day18 var lines = File.ReadAllLines("day18/input"); var numbers = lines.Select(Node.Parse).ToList(); var cur = numbers.First(); foreach (var toAdd in numbers.Skip(1)) { cur = Node.Add(cur,toAdd); ExplodeAndSplit(cur); } Console.WriteLine(cur); Console.WriteLine(cur.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 = Node.Add(Node.Parse(lines[i]), Node.Parse(lines[j])); ExplodeAndSplit(test); magnitudes.Add(test.Magnitude()); var testReverse = Node.Add(Node.Parse(lines[j]), Node.Parse(lines[i])); ExplodeAndSplit(testReverse); magnitudes.Add(testReverse.Magnitude()); } } Console.WriteLine(magnitudes.Max()); sw.Stop(); Console.WriteLine(sw.Elapsed); void ExplodeAndSplit(Node number) { bool changed = false; do { changed = number.Explode(1); if (!changed) { changed = number.Split(); } } while (changed); } 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 Add(Node left, Node right) { var top = new Node() {Left = left, Right = right}; left.Parent = top; right.Parent = top; return top; } public bool Explode(int depth) { if (depth >= 4 && Leaf == null && (Left.Leaf == null || Right.Leaf == null)) { if (Left.Leaf == null) { var oldLeft = Left; Left = new Node() {Leaf = 0, Parent = this}; if (oldLeft.Left.Leaf == null || oldLeft.Right.Leaf == null) { throw new ArgumentException("left or right was null"); } else { Parent?.AddValueLeftParent(oldLeft.Left.Leaf ?? -9999, this); Right.AddValueLeftChild(oldLeft.Right.Leaf ?? -9999); } return true; } if (Right.Leaf == null) { var oldRight = Right; Right = new Node() {Leaf = 0, Parent = this}; if (oldRight.Left.Leaf == null || oldRight.Right.Leaf == null) { throw new ArgumentException("left or right was null"); } else { Left.AddValueRightChild(oldRight.Left.Leaf ?? -9999); Parent?.AddValueRightParent(oldRight.Right.Leaf ?? -9999, this); } return true; } } else if (Leaf == null) { if (Left.Explode(depth + 1)) { return true; } else if (Right.Explode(depth + 1)) { return true; } } return false; } public bool AddValueLeftParent(int value, Node from) { if (Leaf != null) { Leaf += value; return true; } if (Left == from) { if (Parent == null) { return false; } return Parent.AddValueLeftParent(value, this); } if (Right == from) { return Left.AddValueRightChild(value); } return AddValueRightChild(value); } public bool AddValueRightParent(int value, Node from) { if (Leaf != null) { Leaf += value; return true; } if (Right == from) { if (Parent == null) { return false; } return Parent.AddValueRightParent(value, this); } if (Left == from) { return Right.AddValueLeftChild(value); } return AddValueLeftChild(value); } public bool AddValueLeftChild(int value) { if (Leaf != null) { Leaf += value; return true; } return Left.AddValueLeftChild(value); } public bool AddValueRightChild(int value) { if (Leaf != null) { Leaf += value; return true; } return Right.AddValueRightChild(value); } public bool Split() { if (Leaf == null) { if (Left.Split()) { return true; } if (Right.Split()) { return true; } return false; } else if (Leaf > 9){ var leftValue = Leaf / 2; var rightValue = Leaf - leftValue; Leaf = null; Left = new Node() {Leaf = leftValue, Parent = this}; Right = new Node() {Leaf = rightValue, Parent = this}; return true; } return false; } 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