Пример #1
0
 private NailNumber CheckSplit(ref bool split)
 {
     if (IsNumber)
     {
         if (_value > 9)
         {
             var node = new NailNumber(new NailNumber(_value / 2), new NailNumber((_value + 1) / 2));
             node._left.SetPrevious(_previous);
             _previous?.SetNext(node._left);
             node._right.SetNext(_next);
             _next?.SetPrevious(node._right);
             split = true;
             return(node);
         }
     }
     else
     {
         _left = _left.CheckSplit(ref split);
         if (split)
         {
             return(this);
         }
         _right = _right.CheckSplit(ref split);
     }
     return(this);
 }
Пример #2
0
 private NailNumber(NailNumber left, NailNumber right)
 {
     _left  = left;
     _right = right;
     _left.SetNext(_right.Left());
     _right.SetPrevious(_left.Right());
 }
Пример #3
0
            public static NailNumber Parse(CharEnumerator enumerator)
            {
                NailNumber result = null;

                if (!enumerator.MoveNext())
                {
                    return(null);
                }
                switch (enumerator.Current)
                {
                case '[':
                    var left = NailNumber.Parse(enumerator);
                    enumerator.MoveNext();
                    if (enumerator.Current != ',')
                    {
                        throw new InvalidOperationException("Failed to parse");
                    }
                    var right = NailNumber.Parse(enumerator);
                    enumerator.MoveNext();
                    if (enumerator.Current != ']')
                    {
                        throw new InvalidOperationException("Failed to parse");
                    }

                    result = new NailNumber(left, right);
                    break;

                case >= '0' and <= '9':
                    result = new NailNumber(enumerator.Current - '0');
                    break;
                }
                return(result);
            }
Пример #4
0
            private NailNumber CheckExplode(ref bool explode, int depth = 0)
            {
                if (IsNumber)
                {
                    return(this);
                }

                if (depth == 4)
                {
                    // too deep
                    explode = true;
                    var node = new NailNumber(0);
                    if (_left._previous != null)
                    {
                        _left._previous._value += _left._value;
                        node.SetPrevious(_left._previous);
                        _left._previous.SetNext(node);
                    }

                    if (_right._next == null)
                    {
                        return(node);
                    }
                    _right._next._value += _right._value;
                    node.SetNext(_right._next);
                    _right._next.SetPrevious(node);
                    return(node);
                }

                _left  = _left.CheckExplode(ref explode, depth + 1);
                _right = _right.CheckExplode(ref explode, depth + 1);
                return(this);
            }
Пример #5
0
 private void SetPrevious(NailNumber previous)
 {
     if (IsNumber)
     {
         _previous = previous;
     }
     else
     {
         Left().SetPrevious(previous);
     }
 }
Пример #6
0
 private void SetNext(NailNumber next)
 {
     if (IsNumber)
     {
         _next = next;
     }
     else
     {
         Right().SetNext(next);
     }
 }
Пример #7
0
 private NailNumber(NailNumber other)
 {
     if (other.IsNumber)
     {
         _value = other._value;
     }
     else
     {
         _left  = new NailNumber(other._left);
         _right = new NailNumber(other._right);
         _left.SetNext(_right.Left());
         _right.SetPrevious(_left.Right());
     }
 }
Пример #8
0
            public NailNumber Add(NailNumber a)
            {
                var  result = new NailNumber(new NailNumber(this), new NailNumber(a));
                bool redo;

                do
                {
                    redo = false;
                    result.CheckExplode(ref redo);
                    if (!redo)
                    {
                        result.CheckSplit(ref redo);
                    }
                } while (redo);

                return(result);
            }