228 lines
5.9 KiB
C#
228 lines
5.9 KiB
C#
// #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<long> magnitudes = new List<long>();
|
|
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
|