diff options
Diffstat (limited to 'pkg/stack')
-rw-r--r-- | pkg/stack/min.go | 8 | ||||
-rw-r--r-- | pkg/stack/stack.go | 105 | ||||
-rw-r--r-- | pkg/stack/stack_test.go | 83 |
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 +} |