К содержимому
ИС30

Поиск по сайту

Конспекты, лабы, квизы, ЧаВо и страницы

Войти
Основы программирования
ПрогаЛаба 3

SandPile

Модель песчаной кучи: обвалы по итерациям на растущей сетке и сохранение состояний в 4-битные BMP. Своя динамическая память под сетку и своя запись BMP — без сторонних библиотек и контейнеров.

Моисеенко Артём Ярославовичдо 12 баллов
Дедлайн
понедельник, 9 ноября
до 23:59
Через 14 днейДедлайн мягкий: сдать можно и позже, но лучше не тянуть

Дальше мягкие дедлайны: deadline_1 до 16.11 (×0.85), deadline_2 до 23.11 (×0.65), deadline_3 с 24.11 (×0.5).

Войти, чтобы записаться на сдачу
Войдите

Задание

Консольное приложение, которое моделирует абелеву песчаную кучу: читает начальное состояние из TSV-файла, шаг за шагом обваливает кучи на растущей сетке и сохраняет состояния картинками в BMP. Сетку храните в своей динамической памяти, BMP пишете сами — без сторонних библиотек и стандартных контейнеров.

Репозиторий
У каждого свой: организация is-itmo-c-26, репозиторий labwork3-<ваш GitHub-логин>. Каркаса нет — в репозитории только условие, примеры входных данных в input/ и CI. Структуру проекта и сборку на CMake придумываете сами.

Аргументы командной строки

КороткийДлинныйЧто задаётПо умолчанию
-i--inputTSV-файл с начальным состояниемобязательный
-o--outputпапка для картинок; если её нет, программа создаёт её самаобязательный
-m--max-iterмаксимум итераций; при 0 итерации не выполняются, начальное состояние сохраняется как итоговоедо стабилизации
-f--freqчерез сколько итераций сохранять картинку0 — только последнее состояние

--max-iter и --freq — целые неотрицательные числа. На неизвестный аргумент, отсутствие обязательного или некорректное значение программа пишет сообщение об ошибке и завершается с ненулевым кодом.

cmake -B build
cmake --build build
./build/labwork3 --input input/fractal.tsv --output out

Путь к бинарнику зависит от вашего CMakeLists.txt, здесь — для примера.

Начальное состояние

Каждая строка TSV — одна непустая ячейка: координата x, координата y и число песчинок, через табуляцию. Координаты помещаются в int16_t и бывают отрицательными, число песчинок — в uint64_t.

input/multiple-piles.tsv
0	0	4
-2	-1	16
2	1	12

Начальная сетка — минимальный прямоугольник, в который попадают все перечисленные ячейки; остальные ячейки внутри него пустые. Для файла выше это x∈[−2,2]x \in [-2, 2], y∈[−1,1]y \in [-1, 1], то есть 5 × 3.

Правила модели

  1. Песчинки добавляются только при инициализации.
  2. За одну итерацию каждая ячейка, в которой в начале итерации было не меньше 4 песчинок, обваливается ровно один раз: теряет 4 песчинки и отдаёт по одной соседям сверху, снизу, слева и справа.
  3. Состояние после итерации зависит только от состояния в начале итерации. Песчинки, пришедшие от соседей, учитываются только на следующей итерации.
  4. Если при обвале песчинка выходит за край сетки, сетка расширяется в эту сторону.
  5. Модель стабильна, когда в каждой ячейке меньше 4 песчинок.

Программа останавливается, когда модель стабильна или выполнено --max-iter итераций.

Все обвалы одновременные
Если обваливать ячейки по одной и тут же учитывать песчинки у соседей, сосед может обвалиться в той же итерации — это нарушает правило 3. Сначала определите, какие ячейки обваливаются по состоянию на начало итерации, и только потом раздавайте песчинки. Ячейка с 8 песчинками за итерацию тоже обваливается один раз.

Самый маленький пример — single-pile.tsv, 4 песчинки в точке (0, 0). За одну итерацию сетка 1 × 1 расширяется во все стороны до 3 × 3 и становится стабильной:

до:  4        после:  0 1 0
                      1 0 1
                      0 1 0

Сохранение состояний

  • Итерации нумеруются с 1. При freq > 0 картинки сохраняются после итераций freq, 2 · freq, 3 · freq и так далее.
  • Последнее состояние сохраняется всегда, даже если остановка пришлась между сохранениями. Если оно уже сохранено на последней итерации, второй раз его писать не нужно.
  • При freq = 0 сохраняется только последнее состояние.
  • Начальное состояние отдельно не сохраняется. Но если не выполнено ни одной итерации (стабильный вход или --max-iter 0), оно и есть последнее — его нужно сохранить.

Например, при --max-iter 10 --freq 3 картинки появятся после итераций 3, 6, 9 и 10. Как называть файлы, условие не задаёт: удобно по номеру итерации.

Формат картинки

Одна ячейка — один пиксель, размер картинки равен размеру сетки. Цвет зависит от числа песчинок:

ПесчинокЦвет
0чёрный
1зелёный
2фиолетовый
3жёлтый
больше 3белый

На пиксель отводится не больше 4 бит, поэтому подходит BMP с палитрой и глубиной цвета 4 бита.

Как устроен 4-битный BMP
  • Файл: заголовок файла (14 байт, начинается с BM), информационный заголовок BITMAPINFOHEADER (40 байт), палитра из 16 цветов по 4 байта (синий, зелёный, красный, ноль), затем пиксели. Пиксели начинаются со смещения 14 + 40 + 64 = 118 байт.
  • Все многобайтовые поля — little-endian. Пишите заголовок по полю, а не write всей структурой: компилятор добавляет в структуры выравнивание, и в памяти они не совпадают с форматом файла.
  • В одном байте два пикселя: левый — в старших 4 битах.
  • Длина каждой строки пикселей в файле дополняется нулями до кратной 4 байтам.
  • При положительной высоте в заголовке строки идут снизу вверх: первой в файле записана нижняя строка картинки.

Примеры

Готовые файлы лежат в input/. Маленькие удобно проверять руками:

ФайлНачальная сеткаЧто происходит
stable.tsv2 × 2уже стабильно, итераций нет — сохраняется начальное состояние
single-pile.tsv1 × 1одна итерация, итог 3 × 3
multiple-piles.tsv5 × 3кучи с отрицательными координатами, итог 8 × 6 за 6 итераций

Крупные рисуют фрактальные узоры, как на иллюстрациях в Википедии. Запускайте их без --max-iter:

ФайлНачальное состояниеИтоговая сеткаИтераций
fractal.tsv65 536 песчинок в (0, 0)189 × 18962 118
twin-piles.tsvпо 32 768 в (-48, 0) и (48, 0)233 × 14331 148
four-piles.tsvпо 16 384 в углах квадрата x,y∈{−40,40}x, y \in \{-40, 40\}181 × 18116 460
square.tsvквадрат 65 × 65 от -32 до 32, по 6 песчинок в каждой ячейке113 × 1133 165

Теормин

  1. Виртуальное адресное пространство
  2. Сегменты памяти программы. Стек и куча
  3. Стек вызовов. Длительность хранения и время жизни объектов
  4. Динамическая память: malloc, calloc, realloc, free, new, delete, new[] и delete[]
  5. Placement new
  6. Ошибки работы с памятью
  7. Ссылки и константные ссылки. Отличия от указателей
  8. Передача аргументов и возврат значений. Время жизни временных объектов
  9. Перегрузка функций
  10. Аргументы функций по умолчанию
  11. Инициализация и присваивание. Виды инициализации

Мягкие дедлайны

ВеткаСрокКоэффициент
deadline_0до 09.11, 23:591.0
deadline_110.11 — 16.11, 23:590.85
deadline_217.11 — 23.11, 23:590.65
deadline_3с 24.110.5

Максимум 12 баллов.

Требования

  • Только стандартная библиотека C++, сторонние библиотеки запрещены. Чтение аргументов и запись BMP — свои.
  • В приложении запрещены стандартные контейнеры (std::vector, std::deque, std::map и другие), строки (std::string), умные указатели, аллокаторы, std::pmr, строковые потоки (std::stringstream и родня) и std::valarray.
  • C-функции управления памятью (malloc, calloc, realloc, free) тоже запрещены: память под сетку выделяйте через new[] и освобождайте через delete[], расширение — новый блок, копирование и освобождение старого.
  • Сетка хранится в динамической памяти и растёт по мере надобности. Массив заранее заданного максимального размера не подходит.
  • std::filesystem разрешён — пригодится, чтобы создать папку для картинок.
  • В собственных тестах можно GoogleTest и всю стандартную библиотеку.
  • Сборка — только CMake.
  • CI собирает решение clang++-21 с санитайзерами (-fsanitize=address,undefined), но готовых тестов нет, так что ловят они ошибки только в ваших тестах. Перед сдачей прогоните программу на примерах из input/ с AddressSanitizer, UndefinedBehaviorSanitizer и LeakSanitizer: выход за границы, утечки и чтение неинициализированной памяти всплывут там.
  • Стиль проверяет clang-tidy: функции, классы и структуры в CamelCase, переменные в lower_case, поля классов с _ на конце, константы и элементы перечислений в kCamelCase.

Как сдавать

  1. Создайте ветку deadline_0 от main в своём репозитории.
  2. Решайте в этой ветке, коммитьте небольшими логичными порциями.
  3. Откройте Pull Request из deadline_0 в main.
  4. Дождитесь отчёта CI в комментарии к PR: там результат сборки с санитайзерами и проверки стиля.
  5. Если сдаёте после первого дедлайна, ветка называется по дедлайну (deadline_1, deadline_2, deadline_3), и балл умножается на его коэффициент.

Материалы

Комментарии0

Пока никто ничего не написал.

Войдите, чтобы оставить комментарий