namespace HeuristicLab.Problems.ProgramSynthesis.Push.Stack { using System; using System.Collections; using System.Collections.Generic; using System.Linq; /// /// While Push's stacks are generally treated as genuine stacks---that is, inclassions take their arguments from the /// tops of /// the stacks and push their results onto the tops of the stacks---a few inclassions (like YANK and SHOVE) do allow /// direct access /// to "deep" stack elements by means of integer indices. To this extent the stacks can be used as general, random /// access memory /// classures. This is one of the features that ensures the Turing-completeness of Push (another being the arbitrary /// name/value /// bindings supported by the NAME data type and DEFINE methods; see below). /// /// The item type of the collection. public class PushStack : IPushStack { private const string Delimiter = " "; private readonly List data; public PushStack(int capacity = 0) { data = new List(capacity); IsEnabled = true; } public bool IsEnabled { get; set; } public int Capacity { get { return data.Capacity; } } public T Top { get { return data[Count - 1]; } } public T TopOrDefault { get { return Count > 0 ? Top : default(T); } } public T Bottom { get { return data[0]; } } public T BottomOrDefault { get { return Count > 0 ? Bottom : default(T); } } public int Count { get { return data.Count; } } public bool IsEmpty { get { return Count == 0; } } public bool IsReadOnly { get { return false; } } public void Add(T item) { Push(item); } public void Clear() { data.Clear(); } public bool Contains(T item) { return data.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { data.CopyTo(array, arrayIndex); } public IEnumerator GetEnumerator() { return data.GetEnumerator(); } public T ElementAt(int index) { return data[index]; } public T ReverseElementAt(int offset) { return data[offset]; } public void SetTop(T value) { data[Count - 1] = value; } public T this[int index] { get { return data[Count - 1 - index]; } set { data[Count - 1 - index] = value; } } public void Swap(int count) { var top = Top; var bottomIndex = Count - count; for (var i = Count - 1; i > bottomIndex; i--) data[i] = data[i - 1]; data[bottomIndex] = top; } public void Yank(int index) { if (index == Count - 1) return; var item = ReverseElementAt(index); data.RemoveAt(index); data.Add(item); } public T Pop() { var top = Top; data.RemoveAt(Count - 1); return top; } public T[] Pop(int count) { var items = Peek(count); Remove(count); return items; } public T Peek() { return Top; } public T[] Peek(int count) { var startIndex = Count - count; var items = new T[count]; data.CopyTo(startIndex, items, 0, count); return items; } public void Push(T item) { if (!IsEnabled) return; data.Add(item); } public void Push(T item1, T item2) { if (!IsEnabled) return; data.Add(item1); data.Add(item2); } public void Push(T item1, T item2, T item3) { if (!IsEnabled) return; data.Add(item1); data.Add(item2); data.Add(item3); } public void Push(T item1, T item2, T item3, T item4) { if (!IsEnabled) return; data.Add(item1); data.Add(item2); data.Add(item3); data.Add(item4); } public void PushResult(int count, Func templateFunc) { if (!IsEnabled) return; var startIndex = Count - count; var items = new T[count]; data.CopyTo(startIndex, items, 0, count); Remove(count - 1); data[Count - 1] = templateFunc(items); } public void Push(IReadOnlyList items, int startIndex) { if (!IsEnabled) return; for (var i = startIndex; i < items.Count; i++) data.Add(items[i]); } public void Push(IReadOnlyList items) { if (!IsEnabled) return; data.AddRange(items); } public void Insert(int index, T item) { if (!IsEnabled) return; data.Insert(Count - index, item); } public bool Remove(T item) { return this.data.Remove(item); } public void RemoveTop() { data.RemoveAt(Count - 1); } public void Remove(int count) { this.data.RemoveRange(this.Count - count, count); } public void RemoveAt(int index) { data.RemoveAt(index); } public void RemoveAt(int index, int count) { data.RemoveRange(index, count); } public bool TryPop(out T item) { if (Count > 0) { item = Pop(); return true; } item = default(T); return false; } IEnumerator IEnumerable.GetEnumerator() { return data.GetEnumerator(); } public override string ToString() { var data = this.data as IEnumerable; return string.Join(Delimiter, data.Reverse()); } } }