From 12170458e0f46fec23b74a0c55932cdf50d2da02 Mon Sep 17 00:00:00 2001 From: Vladislav Sevryukov Date: Fri, 23 Jan 2026 23:15:11 +0300 Subject: [PATCH 1/3] +=template for lesson_3 --- Lesson_3/homework_test.go | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Lesson_3/homework_test.go 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() +} From abcfc439c5a760aa8b0a589b4e667b93f35db44a Mon Sep 17 00:00:00 2001 From: Vladislav Sevryukov Date: Wed, 21 Jan 2026 23:18:25 +0300 Subject: [PATCH 2/3] +=circular queue --- Lesson_2/homework_test.go | 90 ++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/Lesson_2/homework_test.go b/Lesson_2/homework_test.go index de417bb..d1de3d5 100644 --- a/Lesson_2/homework_test.go +++ b/Lesson_2/homework_test.go @@ -9,48 +9,89 @@ 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 } -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), + front: -1, + } } -func (q *CircularQueue) Pop() bool { - return false // need to implement +func (q *CircularQueue[T]) Push(value T) bool { + if q.Full() { + return false + } + + if q.Empty() { + q.front = 0 + q.rear = 0 + q.values[0] = value + return true + } + + q.rear = (q.rear + 1) % len(q.values) + q.values[q.rear] = value + return true } -func (q *CircularQueue) Front() int { - return -1 // need to implement +func (q *CircularQueue[T]) Pop() bool { + if q.Empty() { + return false + } + + if q.front == q.rear { + q.front = -1 + return true + } + + q.front = (q.front + 1) % len(q.values) + return true +} + +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] } -func (q *CircularQueue) Empty() bool { - return false // need to implement +func (q *CircularQueue[T]) Empty() bool { + return q.front == -1 } -func (q *CircularQueue) Full() bool { - return false // need to implement +func (q *CircularQueue[T]) Full() bool { + return !q.Empty() && (q.rear+1)%len(q.values) == q.front } 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 +104,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()) From 15565441ad503399e72937d826dc5dee9479c81b Mon Sep 17 00:00:00 2001 From: Vladislav Sevryukov Date: Fri, 23 Jan 2026 17:08:06 +0300 Subject: [PATCH 3/3] fix: use size field --- Lesson_2/homework_test.go | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/Lesson_2/homework_test.go b/Lesson_2/homework_test.go index d1de3d5..b165d1a 100644 --- a/Lesson_2/homework_test.go +++ b/Lesson_2/homework_test.go @@ -17,6 +17,7 @@ type CircularQueue[T QueueType] struct { values []T front int rear int + size int } func NewCircularQueue[T QueueType](size int) CircularQueue[T] { @@ -25,7 +26,6 @@ func NewCircularQueue[T QueueType](size int) CircularQueue[T] { } return CircularQueue[T]{ values: make([]T, size), - front: -1, } } @@ -34,15 +34,9 @@ func (q *CircularQueue[T]) Push(value T) bool { return false } - if q.Empty() { - q.front = 0 - q.rear = 0 - q.values[0] = value - return true - } - - q.rear = (q.rear + 1) % len(q.values) q.values[q.rear] = value + q.rear = (q.rear + 1) % len(q.values) + q.size++ return true } @@ -51,12 +45,8 @@ func (q *CircularQueue[T]) Pop() bool { return false } - if q.front == q.rear { - q.front = -1 - return true - } - q.front = (q.front + 1) % len(q.values) + q.size-- return true } @@ -71,15 +61,15 @@ func (q *CircularQueue[T]) Back() T { if q.Empty() { return -1 } - return q.values[q.rear] + return q.values[(q.rear-1+len(q.values))%len(q.values)] } func (q *CircularQueue[T]) Empty() bool { - return q.front == -1 + return q.size == 0 } func (q *CircularQueue[T]) Full() bool { - return !q.Empty() && (q.rear+1)%len(q.values) == q.front + return q.size == len(q.values) } func TestCircularQueue(t *testing.T) {