From 50f4b8350491446ce09a7571412139f722172d08 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Fri, 6 Jan 2023 11:42:00 +0100 Subject: [PATCH] Implemented Queue data structure --- pkg/collection/queue.go | 59 ++++++++++++++++++++++ pkg/collection/queue_test.go | 94 ++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 pkg/collection/queue.go create mode 100644 pkg/collection/queue_test.go diff --git a/pkg/collection/queue.go b/pkg/collection/queue.go new file mode 100644 index 0000000..4eec96b --- /dev/null +++ b/pkg/collection/queue.go @@ -0,0 +1,59 @@ +package collection + +import ( + "fmt" + "strings" +) + +var ( + ErrEmptyQueue = fmt.Errorf("empty queue") +) + +type Queue[E any] struct { + items []E +} + +func NewQueue[E any](items ...E) *Queue[E] { + if items == nil { + items = make([]E, 0) + } + return &Queue[E]{items} +} + +func (q *Queue[E]) Empty() bool { + return q.Size() == 0 +} + +func (q *Queue[E]) Size() int { + return len(q.items) +} + +func (q *Queue[E]) Enqueue(item E) { + q.items = append(q.items, item) +} + +func (q *Queue[E]) Dequeue() (E, error) { + if q.Empty() { + return *new(E), ErrEmptyQueue + } + item := q.items[0] + q.items = q.items[1:] + return item, nil +} + +func (q *Queue[E]) String() string { + var sb strings.Builder + sb.WriteString("[") + for i := 0; i < q.Size(); i++ { + var s string + item := q.items[i] + if i >= q.Size()-1 { + s = fmt.Sprintf("%v", item) + } else { + s = fmt.Sprintf("%v, ", item) + } + sb.WriteString(s) + } + sb.WriteString("]") + return sb.String() +} diff --git a/pkg/collection/queue_test.go b/pkg/collection/queue_test.go new file mode 100644 index 0000000..70f4728 --- /dev/null +++ b/pkg/collection/queue_test.go @@ -0,0 +1,94 @@ +package collection + +import ( + "reflect" + "testing" +) + +func TestQueue_Empty(t *testing.T) { + useCases := []struct { + description string + queue *Queue[int] + want bool + }{ + {description: "empty queue", queue: NewQueue[int](), want: true}, + {description: "non empty queue", queue: NewQueue(1), want: false}, + } + + for _, tt := range useCases { + result := tt.queue.Empty() + if result != tt.want { + t.Errorf("test: %s, want %v got %v", tt.description, tt.want, result) + } + } +} + +func TestQueue_Size(t *testing.T) { + useCases := []struct { + description string + queue *Queue[int] + want int + }{ + {description: "empty queue", queue: NewQueue[int](), want: 0}, + {description: "non empty queue", queue: NewQueue(1), want: 1}, + } + + for _, tt := range useCases { + result := tt.queue.Size() + if result != tt.want { + t.Errorf("test: %s, want %v got %v", tt.description, tt.want, result) + } + } +} + +func TestQueue_Enqueue(t *testing.T) { + useCases := []struct { + description string + original *Queue[int] + modified *Queue[int] + item int + }{ + {description: "enqueue one item in empty queue", original: NewQueue[int](), modified: NewQueue(1), item: 1}, + {description: "enqueue one item in full queue", original: NewQueue(1, 2, 3), modified: NewQueue(1, 2, 3, 4), item: 4}, + } + + for _, tt := range useCases { + tt.original.Enqueue(tt.item) + if !reflect.DeepEqual(tt.original.items, tt.modified.items) { + t.Errorf("test: %s, want %v got %v", tt.description, tt.modified, tt.original) + } + } +} + +func TestQueue_Dequeue(t *testing.T) { + useCases := []struct { + description string + original *Queue[int] + modified *Queue[int] + item int + err error + }{ + {description: "dequeue one item in empty queue", + original: NewQueue[int](), + modified: NewQueue[int](), + item: 0, + err: ErrEmptyQueue}, + {description: "dequeue one item in single item queue", + original: NewQueue(1), + modified: NewQueue[int](), + item: 1, + err: nil}, + {description: "dequeue one item in full queue", + original: NewQueue(1, 2, 3), + modified: NewQueue(2, 3), + item: 1, + err: nil}, + } + + for _, tt := range useCases { + _, err := tt.original.Dequeue() + if !reflect.DeepEqual(tt.original.items, tt.modified.items) || err != tt.err { + t.Errorf("test: %s, want %v got %v", tt.description, tt.modified, tt.original) + } + } +}