diff --git a/homework/01.md b/homework/01.md new file mode 100644 index 0000000..35e2d1c --- /dev/null +++ b/homework/01.md @@ -0,0 +1,11 @@ +# Домашнее задание №1 + +📗 В домашнем задании нужно реализовать функцию по конвертации числа из прямого порядка следования байт (Big Endian) в обратный порядок следования байт (Little Endian). + +Например, число 0x01020304 при вызове функции должно быть сконвертировано в число 0x04030201, а число 0x0000FFFF в 0xFFFF0000. Поподробнее про порядки следования байт можно прочитать здесь. + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + +### Задание со звездочкой + +Выполнять необязательно, но если вы уже знакомы с дженериками в Go, то попробуйте реализовать обобщенную функцию конвертации, которая сможет работать не только с uint32, но еще и с uint16 и uint64 типами данных. \ No newline at end of file diff --git a/homework/02.md b/homework/02.md new file mode 100644 index 0000000..d48b672 --- /dev/null +++ b/homework/02.md @@ -0,0 +1,33 @@ +# Домашнее задание №2 + +📗 В домашнем задании нужно реализовать кольцевую очередь (Circular Queue). + +Кольцевая очередь (Circular Queue) — это структура данных, которая представляет собой очередь (FIFO) фиксированного размера. Кольцевая очередь использует буфер фиксированного размера таким образом, как будто бы после последнего элемента сразу же снова идет первый (как представлено на картинке справа). Подробнее можно прочитать здесь. + +Такая структура много где используется, например для организации различных очередей сообщений и а также буффер в буфферезированных каналах Go реализован в виде кольцевой очереди. + +![alt text](image-02-1.png) + +API для кольцевой очереди будет выглядеть следующим образом: + +```go +// Предположим, что эта очередь будет оперировать только положительными +// числами (отрицательные числа ей никогда не поступят на вход) +type CircularQueue struct { ... } + +func NewCircularQueue(size int) // создать очередь с определенным размером буффера +func (q *CircularQueue) Push(value int) bool // добавить значение в конец очереди (false, если очередь заполнена) +func (q *CircularQueue) Pop() bool // удалить значение из начала очереди (false, если очередь пустая) +func (q *CircularQueue) Front() int // получить значение из начала очереди (-1, если очередь пустая) +func (q *CircularQueue) Back() int // получить значение из конца очереди (-1, если очередь пустая) +func (q *CircularQueue) Empty() bool // проверить пустая ли очередь +func (q *CircularQueue) Full() bool // проверить заполнена ли очередь +``` + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но если вы уже знакомы с дженериками в Go, то попробуйте реализовать обобщенную CircularQueue, которая сможет работать не только с int, но еще и с int8, int16, int32 и int64 типами данных. + diff --git a/homework/03.md b/homework/03.md new file mode 100644 index 0000000..e42494b --- /dev/null +++ b/homework/03.md @@ -0,0 +1,32 @@ +# Домашнее задание №3 + +📗 В домашнем задании нужно реализовать COW (Copy-On-Write) буффер. + + +Идея подхода copy-on-write заключается в том, что при чтении данных используется общая копия данных буффера, но в случае изменения данных — создается новая копия данных буффера. Для реализации такого подхода можно использовать разделяемый счетчик ссылок - если при изменении данных буффера кто-то еще ссылается на этот буффер, то нужно будет сначала произвести копию данных буффера, изменить счетчик ссылок и только затем произвести изменение (если никто не ссылается на буффер, то копировать данные буффера не нужно при изменении данных). + +Дополнительно еще нужно реализовать метод конвертации данных буффера в строку без копирования и дополнительного выделения памяти. + + + +API для COW буффера будет выглядеть следующим образом: + + +```go +// Предположим, что все будут производить копирование +// буффера только с использованием метода Clone() +type COWBuffer struct { ... } + +func NewCOWBuffer(data []byte) // создать буффер с определенными данными +func (b *COWBuffer) Clone() COWBuffer // создать новую копию буфера +func (b *COWBuffer) Close() // перестать использовать копию буффера +func (b *COWBuffer) Update(index int, value byte) bool // изменить определенный байт в буффере +func (b *COWBuffer) String() string // сконвертировать буффер в строку +``` + +📌 Для выполнения домашнего задания подготовлен шаблон кодаи основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но если вы уже знакомы c финализатора в Go, то попробуйте реализовать дополнительный вызов метода Close() - на случай того, если вдруг какой-то программист забудет его вызвать явно в коде (в такой реализаци множественный вызов Close() должен отрабатывать корректно). diff --git a/homework/04.md b/homework/04.md new file mode 100644 index 0000000..cf416a4 --- /dev/null +++ b/homework/04.md @@ -0,0 +1,35 @@ +# Домашнее задание №4 + +📗 В домашнем задании нужно реализовать упорядоченный словарь. + + + +Идея упорядоченного словаря заключается в том, что он будет реализован на основе бинарного дерева поиска (BST). Дерево будет строиться только по ключам элементов, значения элементов при построении дерева не учитываются. Элементы с одинаковыми ключами в упорядоченном словаре хранить нельзя. + + + +Поподробнее с бинарными деревьями поиска можно познакомиться здесь. + + + +API для упорядоченного словаря будет выглядеть следующим образом: + + +```go +type OrderedMap struct { ... } + +func NewOrderedMap() OrderedMap // создать упорядоченный словарь +func (m *OrderedMap) Insert(key, value int) // добавить элемент в словарь +func (m *OrderedMap) Erase(key int) // удалить элемент из словари +func (m *OrderedMap) Contains(key int) bool // проверить существование элемента в словаре +func (m *OrderedMap) Size() int // получить количество элементов в словаре +func (m *OrderedMap) ForEach(action func(int, int)) // применить функцию к каждому элементу словаря от меньшего к большему +``` + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но если вы уже знакомы c дженериками в Go, то попробуйте реализовать обобщенную OrderedMap, которая сможет работать с любыми comparable типами данных в качестве ключей и абсолютно любыми типами данных в качестве значений. + diff --git a/homework/05.md b/homework/05.md new file mode 100644 index 0000000..59fbbe7 --- /dev/null +++ b/homework/05.md @@ -0,0 +1,20 @@ +# Домашнее задание №5 + +📗 В домашнем задании нужно реализовать функции `Map`, `Filter` и `Reduce`. + + + +1. Реализуйте функцию `func Map(data []int, action func(int) int) []int`, которая принимает функцию `action` и срез данных `data`. Функция `Map` должна применить функцию `action` к каждому элементу среза `data` и вернуть новый срез с результатами. + +2. Реализуйте функцию `func Filter(data []int, action func(int) bool) []int`, которая принимает функцию `action` и срез данных `data`. Функция `Filter` должна вернуть новый срез, содержащий только те элементы `data`, для которых функция `action` возвращает `true`. + +3. Реализуйте функцию `func Reduce(data []int, initial int, action func(int, int) int) int`, которая принимает функцию `action` (функцию двух аргументов), срез данных `data` и начальное значение `initial`. Функция `Reduce` должна применить функцию `action` к каждому элементу `data` и начальному значению `initial`, накапливая результат. + + + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но если вы уже знакомы c дженериками в Go, то попробуйте реализовать обобщенные функции Map, Filter и Reduce. \ No newline at end of file diff --git a/homework/06.md b/homework/06.md new file mode 100644 index 0000000..e5383da --- /dev/null +++ b/homework/06.md @@ -0,0 +1,56 @@ +# Домашнее задание №6 + +📗 В домашнем задании нужно упаковать данные игрока в структуру таким образом, чтобы ее размер был не более, чем 64 байта. + + + +Представим, что мы разрабатываем игру и наша задача упаковать данные игрока в структуру таким образом, чтобы ее размер был не более, чем 64 байта (представим, что размер кэш линии на компьютерах будет 64 байта). + + + +Данные пользователя: + +Имя пользователя [0…42] символов латиницы + + нельзя ссылаться на символы строки по указателю (нужно мапить символы строки в объект структуры, чтобы они находились рядом с другими данными) + +Координата по оси X [-2_000_000_000…2_000_000_000] значений + +Координата по оси Y [-2_000_000_000…2_000_000_000] значений + +Координата по оси Z [-2_000_000_000…2_000_000_000] значений + +Золото [0…2_000_000_000] значений + +Магическая сила (мана) [0…1000] значений + +Здоровье [0…1000] значений + +Уважение [0…10] значений + +Сила [0…10] значений + +Опыт [0…10] значений + +Уровень [0…10] значений + +Есть ли у игрока дом [true/false] значения + +Есть ли у игрока оружие [true/false] значения + +Есть ли у игрока семья [true/false] значения + +Тип игрока [строитель/кузнец/воин] значения + + + +Чтобы успешно справиться с заданием - вам потребуется вспомнить темы выравнивания структур данных и побитовых операций. + + + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +###Задание со звездочкой +Выполнять необязательно, но если вы уже знакомы c рефлексией в Go, то попробуйте реализовать сериализацию этой структуры данных в YAML, XML или JSON формат с использованием тегов структур. \ No newline at end of file diff --git a/homework/07.md b/homework/07.md new file mode 100644 index 0000000..e1c6121 --- /dev/null +++ b/homework/07.md @@ -0,0 +1,27 @@ +# Домашнее задание №7 + +📗 В домашнем задании нужно реализовать простой Dependency Injection (DI) контейнер. + + + +DI-контейнер (контейнер внедрения зависимостей) представляет собой шаблон проектирования, который помогает управлять зависимостями в программном приложении. Поподробнее с DI контейнерами можно познакомиться здесь, а также можно посмотреть реализации уже готовых DI контейнеров на Go. + + + +API для DI контейнера будет выглядеть следующим образом: + + +```go +type Container struct { ... } + +func NewContainer() *Container // создать DI контейнер +func (c *Container) RegisterType(name string, constructor interface{}) // зарегистрировать конструктор по созданию типа +func (c *Container) Resolve(name string) (interface{}, error) // создать объект с использованием конструктора +``` + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но если вы хотите, можете попробовать дополнительно реализовать метод RegisterSingletonType, который будет возвращать объекты одиночки, а также, если вы уже знакомы c рефлексией и дженериками в Go, то можете их тоже использовать в реализации. \ No newline at end of file diff --git a/homework/08.md b/homework/08.md new file mode 100644 index 0000000..e6fa77b --- /dev/null +++ b/homework/08.md @@ -0,0 +1,27 @@ +# Домашнее задание №8 + +📗 В домашнем задании нужно реализовать собственный тип ошибки MultiError. + + + +Это позволяет функции возвращать ошибку, которая на самом деле может быть списком ошибок. Если вызывающая сторона знает это, она может развернуть список и получить доступ к ошибкам. Если вызывающая сторона не знает, ошибка преобразуется в удобный для чтения человеком формат. Поподробнее с таким типом ошибок можно ознакомиться здесь. + + + +API для собственного типа ошибки будет выглядеть следующим образом: + + +```go +type MultiError struct { ... } + +func (e *MultiError) Error() string // вернуть текст ошибки +func Append(err error, errs ...error) *MultiError // добавить ошибку к существующей +``` + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но если вы хотите, можете попробовать дополнительно сделать собственный тип ошибки совместимым с функциями errors.Is, errors.As и errors.Unwrap из стандартной библиотеки. + diff --git a/homework/09.md b/homework/09.md new file mode 100644 index 0000000..0e90105 --- /dev/null +++ b/homework/09.md @@ -0,0 +1,28 @@ +# Домашнее задание №9 + +📗 В домашнем задании нужно реализовать сериализацию объекта структуры данных в .properties формат с использованием тегов структур и рефлексии. + + + +При сериализации данных в некоторых случаях могут возникнуть проблемы с пустыми значениями. Например, если у вас есть структура, в которой некоторые поля могут быть не заполнены, и вы сериализуете, то в результате получится объект с пустыми полями. Если это не является ожидаемым поведением, то в нашей реализации можно будет использовать тег omitempty, чтобы пропустить пустые поля при сериализации. + + + +Стуктура для сериализации в .properties формат (поподробнее с .properties форматом можно ознакомиться здесь): + + +```go +type Person struct { + Name string `properties:"name"` + Address string `properties:"address,omitempty"` + Age int `properties:"age"` + Married bool `properties:"married"` +} +``` + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но если вы хотите, можете попробовать реализовать обощенную функцию сериализации, которая сможет работать не только со структорой Person. \ No newline at end of file diff --git a/homework/10.md b/homework/10.md new file mode 100644 index 0000000..3bb04ee --- /dev/null +++ b/homework/10.md @@ -0,0 +1,16 @@ +# Домашнее задание №10 + +📗 В домашнем задании нужно реализовать функцию дефрагментации памяти. + + + +Дефрагментацию нужно будет проводить in-place (без копирования в новое место), а также вместе с обновлением указателей, которые уже ссылаются на фрагментированные участки памяти. Указатели будут указывать только на однобайтовые значения в памяти, а различать свободные и занятые участки памяти нужно будет при помощи указателей, но не при помощи значений в памяти. Поподробнее о дефрагментации можно прочитать здесь. + + + +📌 Для выполнения домашнего задания подготовлен шаблон кода и основные тесты, которую помогут проверить корректность реализации конвертации. Шаблона доступен по ссылке. + + + +### Задание со звездочкой +Выполнять необязательно, но можно попробовать реализовать функцию дефрагментации, которая будет уметь работать не только с однобайтовыми значениями в памяти, но еще и с 2-4-8 байтовыми значениями. \ No newline at end of file diff --git a/homework/image-02-1.png b/homework/image-02-1.png new file mode 100644 index 0000000..a6d71ab Binary files /dev/null and b/homework/image-02-1.png differ