예제 #1
0
            //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);
            }
예제 #2
0
                public SnailfishValue Copy(Snailfish parent) =>
                IsFish
                                        ? new SnailfishValue
                {
                    Fish = Fish.Copy(parent)
                }

                                        : new SnailfishValue {
                    Value = Value
                };
예제 #3
0
 public Snailfish(Snailfish parent, int leftValue, int rightValue)
 {
     Parent = parent;
     Left   = new SnailfishValue {
         Value = leftValue
     };
     Right = new SnailfishValue {
         Value = rightValue
     };
 }
예제 #4
0
 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;
 }
예제 #5
0
            private Snailfish Copy(Snailfish parent = null)
            {
                var copy = new Snailfish
                {
                    Parent = parent
                };

                copy.Left  = Left.Copy(copy);
                copy.Right = Right.Copy(copy);
                return(copy);
            }
예제 #6
0
            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);
                    }
                }
            }
예제 #7
0
 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);
 }
예제 #8
0
            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);
            }
예제 #9
0
            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);
                }
            }
예제 #10
0
            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);
                }
            }
예제 #11
0
            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;
                }
            }