Skip to content

Commit

Permalink
day 443: cleaned up day 53
Browse files Browse the repository at this point in the history
  • Loading branch information
vaskoz committed Feb 8, 2020
1 parent 04a49a1 commit f1b408a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
70 changes: 70 additions & 0 deletions day443/problem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package day443

import "errors"

var errEmpty = errors.New("empty")

// ErrEmpty is the error returned for an empty data structure.
func ErrEmpty() error {
return errEmpty
}

// Stack represents a LIFO data structure.
type Stack interface {
Push(val interface{})
Pop() (interface{}, error)
}

// Queue represents a FIFO data structure.
type Queue interface {
Enqueue(item interface{})
Dequeue() (interface{}, error)
}

type stack struct {
values []interface{}
}

func (s *stack) Push(val interface{}) {
s.values = append(s.values, val)
}

func (s *stack) Pop() (interface{}, error) {
if len(s.values) == 0 {
return nil, ErrEmpty()
}

var x interface{}
x, s.values = s.values[len(s.values)-1], s.values[:len(s.values)-1]

return x, nil
}

type twoStacksQueue struct {
enqueue, dequeue *stack
}

func (tsq twoStacksQueue) Enqueue(item interface{}) {
tsq.enqueue.Push(item)
}

func (tsq twoStacksQueue) Dequeue() (interface{}, error) {
if val, err := tsq.dequeue.Pop(); err == nil {
return val, nil
}

for val, err := tsq.enqueue.Pop(); err == nil; val, err = tsq.enqueue.Pop() {
tsq.dequeue.Push(val)
}

if val, err := tsq.dequeue.Pop(); err == nil {
return val, nil
}

return nil, ErrEmpty()
}

// NewQueue returns a queue. FIFO.
func NewQueue() Queue {
return &twoStacksQueue{&stack{}, &stack{}}
}
50 changes: 50 additions & 0 deletions day443/problem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package day443

import "testing"

// nolint
var testcases = []struct {
inserts []interface{}
}{
{[]interface{}{"foo", "bar", 1, 3, 5, 6}},
}

func TestQueue(t *testing.T) {
t.Parallel()

for _, tc := range testcases {
q := NewQueue()

for _, v := range tc.inserts {
q.Enqueue(v)
}

for _, v := range tc.inserts {
if res, err := q.Dequeue(); err != nil {
t.Errorf("Expected no errors while dequeuing")
} else if res != v {
t.Errorf("Expected results in FIFO order. Expected %v, got %v", v, res)
}
}

if _, err := q.Dequeue(); err == nil {
t.Errorf("Dequeue on empty queue should return an error")
}
}
}

func BenchmarkQueue(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
q := NewQueue()

for _, v := range tc.inserts {
q.Enqueue(v)
}

for range tc.inserts {
q.Dequeue() // nolint
}
}
}
}

0 comments on commit f1b408a

Please sign in to comment.