Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module main

go 1.23.12
go 1.25.5

require github.com/stretchr/testify v1.11.1

Expand Down
32 changes: 32 additions & 0 deletions homeworks/10_allocator/homework.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package homework10

import "unsafe"

func Defragment(memory []byte, pointers []unsafe.Pointer) {
if len(memory) == 0 || len(pointers) == 0 {
return
}

base := uintptr(unsafe.Pointer(&memory[0]))

ptrmap := make(map[int]int)
for i, v := range pointers {
ptrmap[int(uintptr(v)-base)] = i
}

write := 0
for read := range memory {
if i, ok := ptrmap[read]; ok {
if write != read {
memory[write] = memory[read]
}
pointers[i] = unsafe.Pointer(&memory[write])
write++
}
}

// Clear tail data
for i := write; i < len(memory); i++ {
memory[i] = 0
}
}
31 changes: 1 addition & 30 deletions homeworks/10_allocator/homework_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package homework10

import (
"reflect"
Expand All @@ -10,35 +10,6 @@ import (

// go test -v homework_test.go

func Defragment(memory []byte, pointers []unsafe.Pointer) {
if len(memory) == 0 || len(pointers) == 0 {
return
}

base := uintptr(unsafe.Pointer(&memory[0]))

ptrmap := make(map[int]int)
for i, v := range pointers {
ptrmap[int(uintptr(v)-base)] = i
}

write := 0
for read := range memory {
if i, ok := ptrmap[read]; ok {
if write != read {
memory[write] = memory[read]
}
pointers[i] = unsafe.Pointer(&memory[write])
write++
}
}

// Clear tail data
for i := write; i < len(memory); i++ {
memory[i] = 0
}
}

func TestDefragmentation(t *testing.T) {
var fragmentedMemory = []byte{
0xF3, 0x00, 0x00, 0x00,
Expand Down
41 changes: 41 additions & 0 deletions homeworks/11_garbage_collector/homework.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package homework11

import "unsafe"

func Trace(stacks [][]uintptr) []uintptr {
seen := map[uintptr]bool{}
result := []uintptr{}

var dfs func(ptr uintptr)
dfs = func(ptr uintptr) {
if ptr == 0 || seen[ptr] {
return
}
seen[ptr] = true
result = append(result, ptr)

//nolint:govet
uptr := *(*uintptr)(unsafe.Pointer(ptr))
dfs(uptr)
}

for _, row := range stacks {
for _, ptr := range row {
dfs(ptr)
}
}
return result

}

// For test purpose we want to allocate this globally
var heapObjects = []int{
0x00, 0x00, 0x00, 0x00, 0x00,
}

var (
heapPointer1 = &heapObjects[1]
heapPointer2 = &heapObjects[2]
heapPointer3 = (*int)(nil)
heapPointer4 = &heapPointer3
)
40 changes: 1 addition & 39 deletions homeworks/11_garbage_collector/homework_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package homework11

import (
"testing"
Expand All @@ -9,44 +9,6 @@ import (

// go test -v homework_test.go

func Trace(stacks [][]uintptr) []uintptr {
seen := map[uintptr]bool{}
result := []uintptr{}

var dfs func(ptr uintptr)
dfs = func(ptr uintptr) {
if ptr == 0 || seen[ptr] {
return
}
seen[ptr] = true
result = append(result, ptr)

//nolint:govet
uptr := *(*uintptr)(unsafe.Pointer(ptr))
dfs(uptr)
}

for _, row := range stacks {
for _, ptr := range row {
dfs(ptr)
}
}
return result

}

// For test purpose we want to allocate this globally
var heapObjects = []int{
0x00, 0x00, 0x00, 0x00, 0x00,
}

var (
heapPointer1 = &heapObjects[1]
heapPointer2 = &heapObjects[2]
heapPointer3 = (*int)(nil)
heapPointer4 = &heapPointer3
)

func TestTrace(t *testing.T) {

var stacks = [][]uintptr{
Expand Down
31 changes: 31 additions & 0 deletions homeworks/1_types/homework.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package homework1

type Number interface {
~uint16 | ~uint32 | ~uint64
}

func ToLittleEndian[T Number](number T) T {
switch v := any(number).(type) {
case uint16:
return T(
(v & 0x00FF << 8) | (v & 0xFF00 >> 8),
)
case uint32:
return T(
(v & 0x000000FF << 24) | (v & 0x0000FF00 << 8) | (v & 0x00FF0000 >> 8) | (v & 0xFF000000 >> 24),
)
case uint64:
return T(
(v & 0x00000000000000FF << 56) |
(v & 0x000000000000FF00 << 40) |
(v & 0x0000000000FF0000 << 24) |
(v & 0x00000000FF000000 << 8) |
(v & 0x000000FF00000000 >> 8) |
(v & 0x0000FF0000000000 >> 24) |
(v & 0x00FF000000000000 >> 40) |
(v & 0xFF00000000000000 >> 56),
)
default:
panic("unsupported type")
}
}
32 changes: 1 addition & 31 deletions homeworks/1_types/homework_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package homework1

import (
"testing"
Expand All @@ -8,36 +8,6 @@ import (

// go test -v homework_test.go

type Number interface {
~uint16 | ~uint32 | ~uint64
}

func ToLittleEndian[T Number](number T) T {
switch v := any(number).(type) {
case uint16:
return T(
(v & 0x00FF << 8) | (v & 0xFF00 >> 8),
)
case uint32:
return T(
(v & 0x000000FF << 24) | (v & 0x0000FF00 << 8) | (v & 0x00FF0000 >> 8) | (v & 0xFF000000 >> 24),
)
case uint64:
return T(
(v & 0x00000000000000FF << 56) |
(v & 0x000000000000FF00 << 40) |
(v & 0x0000000000FF0000 << 24) |
(v & 0x00000000FF000000 << 8) |
(v & 0x000000FF00000000 >> 8) |
(v & 0x0000FF0000000000 >> 24) |
(v & 0x00FF000000000000 >> 40) |
(v & 0xFF00000000000000 >> 56),
)
default:
panic("unsupported type")
}
}

func TestConversion16(t *testing.T) {
tests := map[string]struct {
number uint16
Expand Down
76 changes: 76 additions & 0 deletions homeworks/2_slices_and_arrays/homework.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package homework2

type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}

type CircularQueue[T Number] struct {
values []T
size int
count int
front int
rear int
}

func NewCircularQueue[T Number](size int) *CircularQueue[T] {
if size <= 0 {
panic("size must be > 0")
}

return &(CircularQueue[T]{
values: make([]T, size),
size: size,
rear: -1,
})
}

func (q *CircularQueue[T]) Push(value T) bool {
if q.Full() {
return false
}

// Increase rear
q.rear = (q.rear + 1) % q.size

// Set value
q.values[q.rear] = value

q.count++
return true
}

func (q *CircularQueue[T]) Pop() bool {
if q.Empty() {
return false
}

// Take value - not implemented

// Increase front
q.front = (q.front + 1) % q.size

q.count--
return true
}

func (q *CircularQueue[T]) Front() T {
if !q.Empty() {
return q.values[q.front]
}
return T(-1)
}

func (q *CircularQueue[T]) Back() T {
if !q.Empty() {
return q.values[q.rear]
}
return T(-1)
}

func (q *CircularQueue[T]) Empty() bool {
return q.count == 0
}

func (q *CircularQueue[T]) Full() bool {
return q.count == q.size
}
Loading