//public Smallfish Reduce() //{ // var s = Dump(); // while (true) // { // var s2 = DoAnySplit(s); // var s3 = DoAnyExplode(s2); // if (s == s3) // { // return Parse(s); // } // } //} //private string DoAnySplit(string s) //{ // var match = Regex.Match(s, @"\d{2,}"); // if (!match.Success) // { // val = null; // return false; // } // val = match.Groups.Values.Skip(1).Select(g => g.Value).ToArray(); //} //private string DoAnyExplode(string s) //{ //} //public void Increaselevels() //{ // Level++; // Left?.Increaselevels(); // Right?.Increaselevels(); //} private static Snailfish FindRoot(Snailfish f) { while (f.Parent != null) { f = f.Parent; } return(f); }
public SnailfishValue Copy(Snailfish parent) => IsFish ? new SnailfishValue { Fish = Fish.Copy(parent) } : new SnailfishValue { Value = Value };
public Snailfish(Snailfish parent, int leftValue, int rightValue) { Parent = parent; Left = new SnailfishValue { Value = leftValue }; Right = new SnailfishValue { Value = rightValue }; }
public Snailfish(Snailfish left, Snailfish right) { Parent = null; Left = new SnailfishValue { Fish = left.Copy() }; Right = new SnailfishValue { Fish = right.Copy() }; Left.Fish.Parent = Right.Fish.Parent = this; }
private Snailfish Copy(Snailfish parent = null) { var copy = new Snailfish { Parent = parent }; copy.Left = Left.Copy(copy); copy.Right = Right.Copy(copy); return(copy); }
private static IEnumerable <Snailfish> GetAll(Snailfish root) { if (root.Left != null) { foreach (var f in GetAll(root.Left)) { yield return(f); } } yield return(root); if (root.Right != null) { foreach (var f in GetAll(root.Right)) { yield return(f); } } }
private bool Split(ref Snailfish child, ref int childval) { if (child == null && childval >= 10) { // split left value var leftval = childval / 2; var rightval = childval - leftval; childval = 0; child = new Snailfish { Parent = this, //Level = Level + 1, LeftValue = leftval, RightValue = rightval }; //Console.WriteLine($"after split: {FindRoot(this).Dump()}"); return(true); } return(false); }
private static Snailfish Parse(char[] s, Snailfish parent, int level, ref int index) { var fish = new Snailfish { Parent = parent, //Level = level, }; if (s[index] == '[') { index++; fish.Left = Parse(s, fish, level + 1, ref index); } else { fish.Left = null; fish.LeftValue = s[index++] - '0'; } if (s[index++] != ',') { throw new Exception(); } if (s[index] == '[') { index++; fish.Right = Parse(s, fish, level + 1, ref index); } else { fish.Right = null; fish.RightValue = s[index++] - '0'; } if (s[index++] != ']') { throw new Exception(); } return(fish); }
public static Snailfish Parse(string s) { var index = 1; return(Parse(s.ToCharArray(), null)); Snailfish Parse(char[] s, Snailfish parent) { var fish = new Snailfish(parent, 0, 0); if (s[index] == '[') { index++; fish.Left.Fish = Parse(s, fish); } else { fish.Left.Value = s[index++] - '0'; } if (s[index++] != ',') { throw new Exception(); } if (s[index] == '[') { index++; fish.Right.Fish = Parse(s, fish); } else { fish.Right.Value = s[index++] - '0'; } if (s[index++] != ']') { throw new Exception(); } return(fish); } }
private bool ReduceExplode() { if (Left.Fish?.ReduceExplode() ?? false) { return(true); } // Any pair nested inside four pairs shall explode if (Parent?.Parent?.Parent?.Parent != null) { // Find the left and right neighbors, if any, and add the exploding // values to them. Then remove this exploded fish from its parent. var(left, right) = FindNeighbors(); if (left != null) { var side = left.Right.IsValue ? left.Right : left.Left; side.Value += Left.Value; } if (right != null) { var side = right.Left.IsValue ? right.Left : right.Right; side.Value += Right.Value; } var explodee = this == Parent.Left.Fish ? Parent.Left : Parent.Right; explodee.Fish = null; explodee.Value = 0; return(true); } if (Right.Fish?.ReduceExplode() ?? false) { return(true); } return(false); (Snailfish, Snailfish) FindNeighbors() { Snailfish left = null; Snailfish right = null; Snailfish prev = null; bool foundSelf = false; var fishWithValue = FindRoot().GetAll().Where(f => f.Left.IsValue || f.Right.IsValue); foreach (var f in fishWithValue) { if (f == this) { left = prev; foundSelf = true; } else if (foundSelf) { right = f; break; } prev = f; } return(left, right); } }
public void Exploded(Snailfish fish) { var root = FindRoot(fish); var fishes = GetAll(root) .Where(f => f.Left == null || f.Right == null) .ToArray(); var leftval = fish.LeftValue; var prev = fishes.TakeWhile(f => f != fish).LastOrDefault(); if (prev != null) { if (prev.Right == null) { prev.RightValue += leftval; // prev.Explode(ref prev.Right, ref prev.RightValue); } else if (prev.Left == null) { prev.LeftValue += leftval; // prev.Explode(ref prev.Left, ref prev.LeftValue); } else { throw new Exception(); } } var rightval = fish.RightValue; var next = fishes.SkipWhile(f => f != fish).Skip(1).FirstOrDefault(); if (next != null) { if (next.Left == null) { next.LeftValue += rightval; // next.Explode(ref next.Left, ref next.LeftValue); } else if (next.Right == null) { next.RightValue += rightval; // next.Explode(ref next.Right, ref next.RightValue); } else { throw new Exception(); } } if (fish == Left) { Left = null; LeftValue = 0; } else { Right = null; RightValue = 0; } }