-4
\$\begingroup\$

I have created a custom class (Generic) in C# for the Hanoi problem. and I am not sure I did the correct thing.

[DebuggerDisplay("Count = {Count}")]
    [System.Runtime.InteropServices.ComVisible(false)]
    public class HanoiStack<T> : IEnumerable<T>, ICollection, IEnumerable where T : IHanoiStack
    {
        private T[] _array;     // Storage for stack elements
        private int _size;           // Number of items in the stack.
        private int _version;        // Used to keep enumerator in sync w/ collection.
        private Object _syncRoot;

        private const int _defaultCapacity = 4;
        static T[] _emptyArray = new T[0];

        public HanoiStack()
        {
            _array = _emptyArray;
            _size = 0;
            _version = 0;
        }

        public HanoiStack(int capacity)
        {
            if (capacity < 0)
                throw new ArgumentOutOfRangeException("Negative Value Exception");
            _array = new T[capacity];
            _size = 0;
            _version = 0;
        }

        public HanoiStack(IEnumerable<T> collection)
        {
            if (collection == null)
                throw new ArgumentException("Null Collection");

            ICollection<T> c = collection as ICollection<T>;
            if (c != null)
            {
                int count = c.Count;
                _array = new T[count];
                c.CopyTo(_array, 0);
                _size = count;
            }
            else
            {
                _size = 0;
                _array = new T[_defaultCapacity];

                using (IEnumerator<T> en = collection.GetEnumerator())
                {
                    while (en.MoveNext())
                    {
                        Push(en.Current);
                    }
                }
            }
        }

        public int Count
        {
            get { return _size; }
        }

        bool System.Collections.ICollection.IsSynchronized
        {
            get { return false; }
        }

        Object System.Collections.ICollection.SyncRoot
        {
            get
            {
                if (_syncRoot == null)
                {
                    System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
                }
                return _syncRoot;
            }
        }

        public void Clear()
        {
            Array.Clear(_array, 0, _size);
            _size = 0;
            _version++;
        }

        public bool Contains(T item)
        {
            int count = _size;

            EqualityComparer<T> c = EqualityComparer<T>.Default;
            while (count-- > 0)
            {
                if (((Object)item) == null)
                {
                    if (((Object)_array[count]) == null)
                        return true;
                }
                else if (_array[count] != null && c.Equals(_array[count], item))
                {
                    return true;
                }
            }
            return false;
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            if (array == null)
            {
                throw new ArgumentNullException("Null Array");
            }

            if (arrayIndex < 0 || arrayIndex > array.Length)
            {
                throw new ArgumentOutOfRangeException("Negative Argument Exception");
            }

            if (array.Length - arrayIndex < _size)
            {
                throw new ArgumentException("Invalid Argument");
            }

            Array.Copy(_array, 0, array, arrayIndex, _size);
            Array.Reverse(array, arrayIndex, _size);
        }

        void System.Collections.ICollection.CopyTo(Array array, int arrayIndex)
        {
            if (array == null)
            {
                throw new ArgumentNullException("Array Null Exception");
            }

            if (array.Rank != 1)
            {
                throw new ArgumentException("Rank Multiple Supported");
            }

            if (array.GetLowerBound(0) != 0)
            {
                throw new ArgumentException("Negative Value Exception");
            }

            if (arrayIndex < 0 || arrayIndex > array.Length)
            {
                throw new ArgumentOutOfRangeException("Negative Value Exception");
            }

            if (array.Length - arrayIndex < _size)
            {
                throw new ArgumentException("Invalid Argument");
            }

            try
            {
                Array.Copy(_array, 0, array, arrayIndex, _size);
                Array.Reverse(array, arrayIndex, _size);
            }
            catch (ArrayTypeMismatchException)
            {
                throw new ArgumentException("Argument Invalid Exception");
            }
        }

        public Enumerator GetEnumerator()
        {
            return new Enumerator(this);
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            return new Enumerator(this);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }

        public void TrimExcess()
        {
            int threshold = (int)(((double)_array.Length) * 0.9);
            if (_size < threshold)
            {
                T[] newarray = new T[_size];
                Array.Copy(_array, 0, newarray, 0, _size);
                _array = newarray;
                _version++;
            }
        }

        public T Peek()
        {
            if (_size == 0)
                throw new Exception("Stack Hanoi is Empty");
            return _array[_size - 1];
        }

        public T Pop()
        {
            if (_size == 0)
                throw new InvalidOperationException("Stack Hanoi is Empty");
            _version++;
            T item = _array[--_size];
            _array[_size] = default(T);     // Free memory quicker.
            return item;
        }

        public void Push(T item)
        {
            if (_size > 0)
            {
                var _newItem = (IHanoiStack)item;
                var _currentItem = (IHanoiStack)this.Peek();
                if (_currentItem.Height > _newItem.Height)
                {
                    throw new InvalidOperationException("Height of the previous item is lesser than the new item.");
                }
                if (_currentItem.Weigth > _newItem.Weigth)
                {
                    throw new InvalidOperationException("Weigth of the previous item is lesser than the new item.");
                }
            }
            if (_size == _array.Length)
            {

                T[] newArray = new T[(_array.Length == 0) ? _defaultCapacity : 2 * _array.Length];
                Array.Copy(_array, 0, newArray, 0, _size);
                _array = newArray;
            }
            _array[_size++] = item;
            _version++;
        }

        public T[] ToArray()
        {
            T[] objArray = new T[_size];
            int i = 0;
            while (i < _size)
            {
                objArray[i] = _array[_size - i - 1];
                i++;
            }
            return objArray;
        }

        public struct Enumerator : IEnumerator<T>,
            System.Collections.IEnumerator
        {
            private HanoiStack<T> _stack;
            private int _index;
            private int _version;
            private T currentElement;

            internal Enumerator(HanoiStack<T> stack)
            {
                _stack = stack;
                _version = _stack._version;
                _index = -2;
                currentElement = default(T);
            }

            public void Dispose()
            {
                _index = -1;
            }

            public bool MoveNext()
            {
                bool retval;
                if (_version != _stack._version) throw new InvalidOperationException("Stack Hanoi is Empty");
                if (_index == -2)
                {  // First call to enumerator.
                    _index = _stack._size - 1;
                    retval = (_index >= 0);
                    if (retval)
                        currentElement = _stack._array[_index];
                    return retval;
                }
                if (_index == -1)
                {  // End of enumeration.
                    return false;
                }

                retval = (--_index >= 0);
                if (retval)
                    currentElement = _stack._array[_index];
                else
                    currentElement = default(T);
                return retval;
            }

            public T Current
            {
                get
                {
                    if (_index == -2) throw new InvalidOperationException("EnumNotStarted");
                    if (_index == -1) throw new InvalidOperationException("EnumEnded");
                    return currentElement;
                }
            }

            Object System.Collections.IEnumerator.Current
            {
                get
                {
                    if (_index == -2) throw new InvalidOperationException("EnumNotStarted");
                    if (_index == -1) throw new InvalidOperationException("EnumEnded");
                    return currentElement;
                }
            }

            void System.Collections.IEnumerator.Reset()
            {
                if (_version != _stack._version) throw new InvalidOperationException("EnumFailedVersion");
                _index = -2;
                currentElement = default(T);
            }
        }
    }

    public interface IHanoiStack
    {
        double Height { get; }
        double Weigth { get; }
    }

I am trying to use a Generic class for the Hanoi problem. it might be simple for some of you. but I have created this in learning the C# Generics. Please help me to validate the code.

  1. The Hanoi problem. This will have a stack of disks of size (n) on a pole and it should be shifted to another among the 3 poles available. But the disks should be in the same order as they were on the previous pole. (Correct?)

  2. I kind of thought that the "STACK" would help me but it will allow the user to add items in any order. So I created an interface that has Width and Height of the Disk so that I could validate the order based on that Interface.

  3. I have a question here, is this the correct way to do this or I was wrong.

\$\endgroup\$

closed as off-topic by VisualMelon, yuri, Peilonrayz, t3chb0t, Mathias Ettinger May 28 at 14:54

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Authorship of code: Since Code Review is a community where programmers improve their skills through peer review, we require that the code be posted by an author or maintainer of the code, that the code be embedded directly, and that the poster know why the code is written the way it is." – VisualMelon, yuri, Peilonrayz, t3chb0t, Mathias Ettinger
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 3
    \$\begingroup\$ Am I incorrect to assume that this is a slightly modified version of the .NET BCL class System.Collections.Generic.Stack<T>? I don't believe we should provide a review for this code, because you are not in a position to justify the design decisions that lead to most all of it. \$\endgroup\$ – VisualMelon May 28 at 14:06
  • \$\begingroup\$ @VisualMelon To me it looked like a java version trying to be ported to C#. \$\endgroup\$ – dfhwze May 28 at 14:09
  • 1
    \$\begingroup\$ @dfhwze see the reference source. It's essentially the same. (Which the OP has just confirmed) \$\endgroup\$ – VisualMelon May 28 at 14:11
  • 2
    \$\begingroup\$ @VisualMelon wow, that's a lame thing to do. \$\endgroup\$ – dfhwze May 28 at 14:12
  • 4
    \$\begingroup\$ @NavinKumarKSubramanian it's fine to do whatever you want to aid your learning; however, not everything should be posted on CodeReview. You might want to visit the help centre to see how best to use the site. \$\endgroup\$ – VisualMelon May 28 at 14:35
1
\$\begingroup\$

I would have created a simpler version. I have removed my review of the code not written by you.

 public class HanoiStack<T> : Stack<T> where T : IHanoiElement
    {
        public new void Push(T item)
        {
            // null checks ..
            if (Count != 0)
            {
                var top = this.Peek();
                if (item.Height > top.Height || item.Weigth > top.Weigth)
                {
                    throw new InvalidOperationException("The item is too big");
                }
            }
            base.Push(item);
        }
    }

    public interface IHanoiElement
    {
        double Height { get; }
        double Weigth { get; }
    }

Naming Conventions

I would not call the element type IHanoiStack a stack, rather an element IHanoiElement.

 public interface IHanoiStack
    {
        double Height { get; }
        double Weigth { get; }
    }
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.