aboutsummaryrefslogtreecommitdiff
path: root/pkg/stack
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/stack')
-rw-r--r--pkg/stack/min.go8
-rw-r--r--pkg/stack/stack.go105
-rw-r--r--pkg/stack/stack_test.go83
3 files changed, 196 insertions, 0 deletions
diff --git a/pkg/stack/min.go b/pkg/stack/min.go
new file mode 100644
index 0000000..e97aaed
--- /dev/null
+++ b/pkg/stack/min.go
@@ -0,0 +1,8 @@
+package stack
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
diff --git a/pkg/stack/stack.go b/pkg/stack/stack.go
new file mode 100644
index 0000000..c307133
--- /dev/null
+++ b/pkg/stack/stack.go
@@ -0,0 +1,105 @@
+package stack
+
+type Stack struct {
+ size int
+ height int
+ data []int
+ next *Stack // Pointer to the next element in the stack stack
+}
+
+func NewStack(size int, next *Stack) *Stack {
+ return &Stack{
+ size: size,
+ height: 0,
+ data: make([]int, size),
+ next: next,
+ }
+}
+
+func (s *Stack) Clear() {
+ s.height = 0
+}
+
+func (s *Stack) Duplicate() {
+ if s.height > 0 {
+ s.Push(s.data[s.height-1])
+ } else {
+ s.Push(0)
+ s.Push(0)
+ }
+}
+
+func (s *Stack) Pop() int {
+ if s.height > 0 {
+ s.height--
+ return s.data[s.height]
+ }
+ return 0
+}
+
+func (s *Stack) Push(value int) {
+ if s.height >= s.size {
+ s.size += 32
+ s.data = append(s.data, make([]int, 32)...)
+ }
+ s.data[s.height] = value
+ s.height++
+}
+
+func (s *Stack) Swap() {
+ a := s.Pop()
+ b := s.Pop()
+ s.Push(a)
+ s.Push(b)
+}
+
+func (s Stack) GetHeights() []int {
+ if s.next != nil {
+ return append(s.next.GetHeights(), s.height)
+ } else {
+ return []int{s.height}
+ }
+}
+
+func (toss *Stack) Transfert(soss *Stack, n int) {
+ // Implements a value transfert between two stacks, intended for use with the '{'
+ // (aka begin) and '}' (aka end) stackstack commands
+ toss.height += n
+ if toss.height > toss.size {
+ toss.data = append(toss.data, make([]int, toss.height-toss.size)...)
+ toss.size = toss.height
+ }
+ for i := 1; i <= min(soss.height, n); i++ {
+ toss.data[toss.height-i] = soss.data[soss.height-i]
+ for i := min(soss.height, n) + 1; i <= n; i++ {
+ toss.data[toss.height-i] = 0
+ }
+ }
+ soss.height -= n
+ if soss.height < 0 {
+ soss.height = 0
+ }
+}
+
+func (s Stack) Next() *Stack {
+ return s.next
+}
+
+func (s *Stack) Discard(n int) {
+ // Implements a discard mechanism intended for use with the '}'(aka end) stackstack command
+ s.height -= n
+ if s.height < 0 {
+ s.height = 0
+ }
+}
+
+func (s *Stack) YCommandPick(n int, h int) {
+ if n > s.height {
+ s.height = 1
+ s.data[0] = 0
+ } else {
+ v := s.data[s.height-n]
+ s.height = h
+ s.Push(v)
+ }
+}
diff --git a/pkg/stack/stack_test.go b/pkg/stack/stack_test.go
new file mode 100644
index 0000000..2f15d3a
--- /dev/null
+++ b/pkg/stack/stack_test.go
@@ -0,0 +1,83 @@
+package stack
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestClear(t *testing.T) {
+ s := NewStack(32, nil)
+ s.Clear()
+ require.Equal(t, 0, s.height)
+}
+
+func TestDupicate(t *testing.T) {
+ expected := NewStack(32, nil)
+ expected.height = 2
+ s := NewStack(32, nil)
+ s.Duplicate()
+ require.Equal(t, expected.height, s.height)
+ s.Push(12)
+ s.Duplicate()
+ expected.Push(12)
+ expected.Push(12)
+ require.Equal(t, expected.height, s.height)
+ require.Equal(t, expected.data, s.data)
+}
+
+func TestPop(t *testing.T) {
+ s := NewStack(32, nil)
+ v := s.Pop()
+ require.Equal(t, 0, v)
+ s.Push(12)
+ s.Push(14)
+ v = s.Pop()
+ require.Equal(t, 14, v)
+ v = s.Pop()
+ require.Equal(t, 12, v)
+ v = s.Pop()
+ require.Equal(t, 0, v)
+}
+
+func TestPush(t *testing.T) {
+ s := NewStack(32, nil)
+ for i := 0; i < 32; i++ {
+ s.Push(i)
+ }
+ require.Equal(t, 32, s.size)
+ s.Push(-1)
+ require.Equal(t, 64, s.size)
+}
+
+func TestSwap(t *testing.T) {
+ s := NewStack(32, nil)
+ s2 := NewStack(32, nil)
+ s.Swap()
+ s2.Push(0)
+ s2.Push(0)
+ require.Equal(t, s2, s)
+ s.Clear()
+ s.Push(1)
+ s.Swap()
+ s2.Clear()
+ s2.Push(1)
+ s2.Push(0)
+ require.Equal(t, s2, s)
+ s.Clear()
+ s.Push(1)
+ s.Push(2)
+ s2.Clear()
+ s2.Push(2)
+ s2.Push(1)
+ s.Swap()
+ require.Equal(t, s2, s)
+}
+
+func TestHeights(t *testing.T) {
+ // TODO
+}
+
+func TestTransfert(t *testing.T) {
+ // TODO
+}