diff --git a/Lesson_2/homework_test.go b/Lesson_2/homework_test.go index de417bb..b165d1a 100644 --- a/Lesson_2/homework_test.go +++ b/Lesson_2/homework_test.go @@ -9,48 +9,79 @@ import ( // go test -v homework_test.go -type CircularQueue struct { - values []int - // need to implement +type QueueType interface { + int | int8 | int16 | int32 | int64 } -func NewCircularQueue(size int) CircularQueue { - return CircularQueue{} // need to implement +type CircularQueue[T QueueType] struct { + values []T + front int + rear int + size int } -func (q *CircularQueue) Push(value int) bool { - return false // need to implement +func NewCircularQueue[T QueueType](size int) CircularQueue[T] { + if size <= 0 { + return CircularQueue[T]{} + } + return CircularQueue[T]{ + values: make([]T, size), + } } -func (q *CircularQueue) Pop() bool { - return false // need to implement +func (q *CircularQueue[T]) Push(value T) bool { + if q.Full() { + return false + } + + q.values[q.rear] = value + q.rear = (q.rear + 1) % len(q.values) + q.size++ + return true +} + +func (q *CircularQueue[T]) Pop() bool { + if q.Empty() { + return false + } + + q.front = (q.front + 1) % len(q.values) + q.size-- + return true } -func (q *CircularQueue) Front() int { - return -1 // need to implement +func (q *CircularQueue[T]) Front() T { + if q.Empty() { + return -1 + } + return q.values[q.front] } -func (q *CircularQueue) Back() int { - return -1 // need to implement +func (q *CircularQueue[T]) Back() T { + if q.Empty() { + return -1 + } + return q.values[(q.rear-1+len(q.values))%len(q.values)] } -func (q *CircularQueue) Empty() bool { - return false // need to implement +func (q *CircularQueue[T]) Empty() bool { + return q.size == 0 } -func (q *CircularQueue) Full() bool { - return false // need to implement +func (q *CircularQueue[T]) Full() bool { + return q.size == len(q.values) } func TestCircularQueue(t *testing.T) { const queueSize = 3 - queue := NewCircularQueue(queueSize) + + queue := NewCircularQueue[int](queueSize) assert.True(t, queue.Empty()) assert.False(t, queue.Full()) - assert.Equal(t, -1, queue.Front()) - assert.Equal(t, -1, queue.Back()) + assert.Equal(t, int(-1), queue.Front()) + assert.Equal(t, int(-1), queue.Back()) assert.False(t, queue.Pop()) assert.True(t, queue.Push(1)) @@ -63,18 +94,17 @@ func TestCircularQueue(t *testing.T) { assert.False(t, queue.Empty()) assert.True(t, queue.Full()) - assert.Equal(t, 1, queue.Front()) - assert.Equal(t, 3, queue.Back()) + assert.Equal(t, int(1), queue.Front()) + assert.Equal(t, int(3), queue.Back()) assert.True(t, queue.Pop()) assert.False(t, queue.Empty()) assert.False(t, queue.Full()) assert.True(t, queue.Push(4)) - assert.True(t, reflect.DeepEqual([]int{4, 2, 3}, queue.values)) - assert.Equal(t, 2, queue.Front()) - assert.Equal(t, 4, queue.Back()) + assert.Equal(t, int(2), queue.Front()) + assert.Equal(t, int(4), queue.Back()) assert.True(t, queue.Pop()) assert.True(t, queue.Pop()) diff --git a/Lesson_3/homework_test.go b/Lesson_3/homework_test.go new file mode 100644 index 0000000..d2175bd --- /dev/null +++ b/Lesson_3/homework_test.go @@ -0,0 +1,74 @@ +package main + +import ( + "reflect" + "testing" + "unsafe" + + "github.com/stretchr/testify/assert" +) + +type COWBuffer struct { + data []byte + refs *int + // need to implement +} + +func NewCOWBuffer(data []byte) COWBuffer { + return COWBuffer{} // need to implement +} + +func (b *COWBuffer) Clone() COWBuffer { + return COWBuffer{} // need to implement +} + +func (b *COWBuffer) Close() { + // need to implement +} + +func (b *COWBuffer) Update(index int, value byte) bool { + return false // need to implement +} + +func (b *COWBuffer) String() string { + return "" // need to implement +} + +func TestCOWBuffer(t *testing.T) { + data := []byte{'a', 'b', 'c', 'd'} + buffer := NewCOWBuffer(data) + defer buffer.Close() + + copy1 := buffer.Clone() + copy2 := buffer.Clone() + + assert.Equal(t, unsafe.SliceData(data), unsafe.SliceData(buffer.data)) + assert.Equal(t, unsafe.SliceData(buffer.data), unsafe.SliceData(copy1.data)) + assert.Equal(t, unsafe.SliceData(copy1.data), unsafe.SliceData(copy2.data)) + + assert.True(t, (*byte)(unsafe.SliceData(data)) == unsafe.StringData(buffer.String())) + assert.True(t, (*byte)(unsafe.StringData(buffer.String())) == unsafe.StringData(copy1.String())) + assert.True(t, (*byte)(unsafe.StringData(copy1.String())) == unsafe.StringData(copy2.String())) + + assert.True(t, buffer.Update(0, 'g')) + assert.False(t, buffer.Update(-1, 'g')) + assert.False(t, buffer.Update(4, 'g')) + + assert.True(t, reflect.DeepEqual([]byte{'g', 'b', 'c', 'd'}, buffer.data)) + assert.True(t, reflect.DeepEqual([]byte{'a', 'b', 'c', 'd'}, copy1.data)) + assert.True(t, reflect.DeepEqual([]byte{'a', 'b', 'c', 'd'}, copy2.data)) + + assert.NotEqual(t, unsafe.SliceData(buffer.data), unsafe.SliceData(copy1.data)) + assert.Equal(t, unsafe.SliceData(copy1.data), unsafe.SliceData(copy2.data)) + + copy1.Close() + + previous := copy2.data + copy2.Update(0, 'f') + current := copy2.data + + // 1 reference - don't need to copy buffer during update + assert.Equal(t, unsafe.SliceData(previous), unsafe.SliceData(current)) + + copy2.Close() +}