\documentclass[a4paper, final]{article}
%\usepackage{literat} % Нормальные шрифты
\usepackage[14pt]{extsizes} % для того чтобы задать нестандартный 14-ый размер шрифта
\usepackage[T2A]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[russian]{babel}
\usepackage{amsmath}
\usepackage[left=25mm, top=20mm, right=20mm, bottom=20mm, footskip=10mm]{geometry}
\usepackage{ragged2e} %для растягивания по ширине
\usepackage{setspace} %для межстрочного интервала
\usepackage{moreverb} %для работы с листингами
\usepackage{indentfirst} % для абзацного отступа
\usepackage{moreverb} %для печати в листинге исходного кода программ
\usepackage{graphicx}
\usepackage{tabularx}

\usepackage{array}
\usepackage{multirow}

\renewcommand\verbatimtabsize{4\relax}
\renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге
\renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице
\usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы
\usepackage{listings} %листинги
\usepackage{xcolor} % цвета
\usepackage{hyperref}% для гиперссылок
\usepackage{enumitem} %для перечислений
\newtheorem{theorem}{Теорема} % Создание нового окружения для теорем
\setlist[enumerate,itemize]{leftmargin=1.2cm} %отступ в перечислениях

\hypersetup{colorlinks,
    allcolors=[RGB]{010 090 200}} %красивые гиперссылки (не красные)

% подгружаемые языки — подробнее в документации listings (это всё для листингов)
\lstloadlanguages{ C++}
% включаем кириллицу и добавляем кое−какие опции
\lstset{tabsize=2,
    breaklines,
    basicstyle=\footnotesize,
    columns=fullflexible,
    flexiblecolumns,
    numbers=left,
    numberstyle={\footnotesize},
    keywordstyle=\color{blue},
    inputencoding=cp1251,
    extendedchars=true
}
\lstdefinelanguage{MyC}{
    language=C++,
%    ndkeywordstyle=\color{darkgray}\bfseries,
%    identifierstyle=\color{black},
%    morecomment=[n]{/**}{*/},
%    commentstyle=\color{blue}\ttfamily,
%    stringstyle=\color{red}\ttfamily,
%    morestring=[b]",
%    showstringspaces=false,
%    morecomment=[l][\color{gray}]{//},
    keepspaces=true,
    escapechar=\%,
    texcl=true
}

\textheight=24cm % высота текста
\textwidth=16cm % ширина текста
\oddsidemargin=0pt % отступ от левого края
\topmargin=-1.5cm % отступ от верхнего края
\parindent=24pt % абзацный отступ
\parskip=5pt % интервал между абзацами
\tolerance=2000 % терпимость к "жидким" строкам
\flushbottom % выравнивание высоты страниц


% Настройка листингов
\lstset{
    language=C++,
    extendedchars=\true,
    inputencoding=utf8,
    keepspaces=true,
    % captionpos=b,
}

\begin{document} % начало документа
    
    % НАЧАЛО ТИТУЛЬНОГО ЛИСТА
    \begin{center}
        \hfill \break
        \hfill \break
        \normalsize{МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ\\
            федеральное государственное автономное образовательное учреждение высшего образования «Санкт-Петербургский политехнический университет Петра Великого»\\[10pt]}
        \normalsize{Институт компьютерных наук и кибербезопасности}\\[10pt] 
        \normalsize{Высшая школа технологий искусственного интеллекта}\\[10pt] 
        \normalsize{Направление: 02.03.01 <<Математика и компьютерные науки>>}\\
        
        \hfill \break
        \hfill \break
        \hfill \break
        \hfill \break
        \large{Отчет по лабораторной работе №1}\\
        \large{<<Реализация двумерного клеточного автомата>>}\\
        \large{по дисциплине <<Теория алгоритмов>>}\\
        \large{Вариант 25}\\
        
        \hfill \break
        \hfill \break
    \end{center}
    
    \small{ 
        \begin{tabular}{lrrl}
            \!\!\!Студент, & \hspace{2cm} & & \\
            \!\!\!группы 5130201/20102 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\
            \!\!\!Преподаватель & \hspace{2cm} &  \underline{\hspace{3cm}} &  Востров А. В. \\\\
            &&\hspace{4cm}
        \end{tabular}
        \begin{flushright}
            <<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2024г.
        \end{flushright}
    }
    
    \hfill \break
    % \hfill \break
    \begin{center} \small{Санкт-Петербург, 2024} \end{center}
    \thispagestyle{empty} % выключаем отображение номера для этой страницы
    
    % КОНЕЦ ТИТУЛЬНОГО ЛИСТА
    \newpage
    
    \tableofcontents
    
    \newpage
    
    \section*{Введение}
    \addcontentsline{toc}{section}{Введение}
    Данная лабораторная работа по дисциплине <<Теория алгоритмов>> заключается в разработке консольного приложения на языке C++, которое позволяет создавать и запускать двумерные клеточные автоматы с различными настройками и функцией переходов, заданной вариантом лабораторной работы. Также в этом отчёте к лабораторной работе проводится анализ заданного клеточного автомата.

    \newpage
    \section{Постановка задачи}
    Лабораторная работа заключалась в следующем:

    \begin{itemize}
        \item Реализовать двумерный клеточный автомат с окрестностью фон Неймана в соответствии с полученным номером (№109063350), который задаёт функцию перехода автомата.
        \item Предложить самостоятельно граничные условия (тороидальные, нулевые, единичные).
        \item Обеспечить возможность пользователю задавать ширину поля и количество итераций.
        \item Учесть возможность ввода различных начальных условий (как вручную, так и случайным образом) по выбору пользователя.
        \item Реализовать автомат в консольном или графическом интерфейсе.
        \item Проанализировать поведение клеточного автомата, выявить паттерны, оценить "сходимость" и другие характеристики в отчете.
    \end{itemize}


    \newpage
    \section {Математическое описание}
    \subsection{Клеточные автоматы}
    Клеточные автоматы~\cite{vostrov} – это регулярная структура динамических объектов (клеток), функционирующих синхронно. Клеточные автоматы моделируют процессы, разворачивающиеся в дискретном пространстве и в дискретном времени. Клеточный автомат имеет состояние, определяемое как набор (вектор или матрица) состояний компонентных автоматов. Каждый автомат функционирует как автомат Мура, т.е. это автомат без выхода, выходом является его состояние. Вход на каждом шаге клеточного автомата – состояния его соседей. На следующем шаге (в следующем такте) новое состояние каждого автомата определяется как функция его текущего состояния и текущих состояний его соседей. Обычно правила изменения состояний всех автоматов (кроме крайних) идентичны (однородность системы), множество состояний каждого автомата – конечно. Изменение состояния системы во всех клетках происходит синхронно: состояния клеток меняются одновременно, в каждом такте.

    \subsection{Двумерные клеточные автоматы}
    Двумерные клеточные автоматы являются расширением одномерных клеточных автоматов, описанных ранее. В одномерных автоматах состояние каждой клетки определяется её собственным состоянием и состояниями соседних клеток на линии. В двумерных клеточных автоматах клетки расположены на двумерной сетке, и их состояние зависит от собственных состояний и состояний соседних клеток в двух измерениях, что позволяет моделировать более сложные пространственные взаимодействия.


Основные элементы клеточного автомата:
\begin{enumerate}
    \item \textbf{Сетка клеток:} Двумерный массив клеток $C(i, j)$, где $i, j \in Z$ обозначают индексы клетки в сетке.
    \item \textbf{Состояния:} Каждая клетка может находиться в одном из $k$ возможных состояний: $S = \{s_0, s_1, \dots, s_{k-1}\}$. В данной лабораторной работе рассматриваются автоматы с двумя возможными состояниями '0' и '1'.
    \item \textbf{Тип окрестности:} Для клетки $C(i, j)$ задаётся множество соседей $\mathcal{N}(i, j)$. Окрестность фон Неймана (см. Рис.~\ref{fig:fon}) задаётся следующим образом (включает 4 соседа):
    \[
    \mathcal{N}_N(i, j) = \{C(i-1, j), C(i+1, j), C(i, j-1), C(i, j+1)\}.
    \]
    \item \textbf{Функция перехода:} Функция $f$ определяет состояние клетки $C(i, j)$ на следующем шаге:
    \[
    C'(i, j) = f\left(C(i, j), \{C(x, y) \mid (x, y) \in \mathcal{N}(i, j)\}\right),
    \]
    где $C'(i, j)$ — состояние клетки после обновления.
    \item \textbf{Граничные условия:} Определяют, как будет выглядеть окрестность клеток на границах сетки. Основные типы:
    \begin{itemize}
        \item \textit{Нулевые граничные условия:} За пределами сетки клетки считаются находящимися в нулевом состоянии.
        \item \textit{Единичные граничные условия:} За пределами сетки клетки считаются находящимися в единичном состоянии.
        \item \textit{Тороидальные граничные условия:} Сетка рассматривается как тор, то есть клетки на одной границе соединены с противоположной границей.
    \end{itemize}
\end{enumerate}

\begin{figure}[h!]
   \centering
   \includegraphics[width=0.3\linewidth]{img/fon.png}
   \caption{Двумерная окрестность фон Неймана.}
   \label{fig:fon}
\end{figure}

    \subsection{Функция перехода}
    Рассматриваемому варианту лабораторной работы соответствует №109063350. В двоичном виде, после добавления ведущих нулей до 32 разрядов, это число выглядит следующим образом: 
    $$
    00000110100000000010110010110110_2
    $$

    Битовое представление этого числа в обратном порядке задаёт вектор значений для булевой функции переходов от пяти переменных ($2^5 = 32$). Каждая переменная соответствует состоянию клетки из окресности фон Неймана в определённом порядке, который указан на Рис.~\ref{fig:fon2}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.3\linewidth]{img/fon2.png}
       \caption{Окрестность фон Неймана с метками для соседей.}
       \label{fig:fon2}
    \end{figure}

    \subsection{Паттерны, сходимость и классификация клеточных автоматов}
    Паттерны -- это устойчивые структуры, которые формируются в процессе эволюции клеточного автомата. В зависимости от правил, эти структуры могут быть статичными (не изменяются с течением времени), циклическими (повторяются через несколько итераций), или распространяющимися (разрастаются в пространстве).

    Сходимость -- это поведение клеточного автомата, при котором его состояние стабилизируется спустя некоторое количество итераций. Это может быть достижение статического состояния, циклического паттерна или полное угасание активности (все клетки становятся "мёртвыми").

    Стивен Вольфрам в своей книге A New Kind of Science~\cite{wolfram} предложил 4 класса, на которые все клеточные автоматы могут быть разделены в зависимости от типа их эволюции:
    \begin{itemize}
    \item Класс 1: Результатом эволюции начальных условий является быстрый переход к гомогенной стабильности. Любые негомогенные конструкции быстро исчезают.
    \item Класс 2: Результатом эволюции начальных условий является быстрый переход в неизменяемое негомогенное состояние либо возникновение циклической последовательности. Большинство структур начальных условий быстро исчезает, но некоторые остаются. Локальные изменения в начальных условиях оказывают локальный характер на дальнейший ход эволюции системы.
    \item Класс 3: Результатом эволюции почти всех начальных условий являются псевдо-случайные, хаотические последовательности. Любые стабильные структуры, которые возникают почти сразу же уничтожаются окружающим их шумом. Локальные изменения в начальных условиях оказывают неопределяемое влияние на ход эволюции системы.
    \item Класс 4: Результатом эволюции являются структуры, которые взаимодействуют сложным образом с формированием локальных, устойчивых структур. В результате эволюции могут получаться некоторые последовательности Класса 2, описанного выше. Локальные изменения в начальных условиях оказывают неопределяемое влияние на ход эволюции системы. Некоторые клеточные автоматы этого класса обладают свойством универсальности по Тьюрингу.
    \end{itemize}
    

    \newpage
\section{Особенности реализации}
\subsection{Класс CellularAutomaton}
В листинге~\ref{lst:CellularAutomaton} представлен код объявления класса \texttt{CellularAutomaton}.

Класс содержит следующие атрибуты:
\begin{itemize}
    \item \texttt{static const unsigned int m\_functionValues} -- хранит число, соответствующее номеру варианта лабораторной работы, его битовое представление соответствует функции переходов двумерного клеточного автомата;
    \item \texttt{int m\_fieldWidth} -- ширина поля клеточного автомата;
    \item \texttt{int m\_fieldHeight} -- высота поля клеточного автомата;
    \item \texttt{std::vector<std::vector<int> > m\_field} -- двумерный вектор, представляющий текущее состояние клеточного автомата;
    \item \texttt{std::vector<std::vector<int> > m\_fieldNextState} -- двумерный вектор для хранения следующего состояния клеточного автомата;
    \item \texttt{BoundaryCondition m\_boundaryCondition} -- граничные условия, задаются значением из перечисления \texttt{BoundaryCondition}.
\end{itemize}

Перечисление \texttt{BoundaryCondition} имеет три возможных значения:
\begin{itemize}
    \item \texttt{BOUNDARY\_ONES} -- единичные граничные условия;
    \item \texttt{BOUNDARY\_ZEROS} -- нулевые граничные условия;
    \item \texttt{BOUNDARY\_TOROIDAL} -- тороидальные граничные условия.
\end{itemize}

Методы класса описываются в последующих разделах.

\begin{lstlisting}[caption={Код объявления класса CellularAutomaton.}, label={lst:CellularAutomaton}]
enum BoundaryCondition {
    BOUNDARY_ONES,
    BOUNDARY_ZEROS,
    BOUNDARY_TOROIDAL
};

class CellularAutomaton
{
    static const unsigned int m_functionValues = 25 * 11 * 2003 * 18 * 11;

    int m_fieldWidth, m_fieldHeight;
    std::vector<std::vector<int>> m_field;
    std::vector<std::vector<int>> m_fieldNextState;
    BoundaryCondition m_boundaryCondition;

    void initializeRandom();
    void initializeManual();

    int getCellState(int x, int y) const;
    int getNeighborhoodIndex(int x, int y) const;
public:
    CellularAutomaton(int width, int height, bool fillWithRandom, BoundaryCondition boundaryCondition);
    
    void update();
    void displayField() const;
};   
\end{lstlisting}

\subsubsection{Конструктор CellularAutomaton}

Конструктор класса CellularAutomaton, код которого представлен в листиге~\ref{lst:CellularAutomatonConstructor}, принимает следующие параметры:
\begin{itemize}
    \item \texttt{int width} -- ширина поля клеточного автомата;
    \item \texttt{int height} -- высота поля клеточного автомата;
    \item \texttt{bool fillWithRandom} -- флаг, определяющий, инициализировать ли поле случайными значениями;
    \item \texttt{BoundaryCondition boundaryCondition} -- условие на границе поля.
\end{itemize}

Конструктор создает объект \texttt{CellularAutomaton} с заданными размерами и граничными условиями. Если \texttt{fillWithRandom} равно \texttt{true}, то поле инициализируется случайным образом с помощью метода \texttt{initializeRandom}, иначе пользователь может вручную ввести начальное состояние с помощью метода \texttt{initializeManual}.

\begin{lstlisting}[caption={Код конструктора CellularAutomaton.}, label={lst:CellularAutomatonConstructor}]
CellularAutomaton::CellularAutomaton(int width, int height, bool fillWithRandom, BoundaryCondition boundaryCondition)
    : m_fieldWidth(width), m_fieldHeight(height), m_boundaryCondition(boundaryCondition)
{
    m_field.resize(m_fieldHeight, std::vector<int>(m_fieldWidth, 0));
    m_fieldNextState.resize(m_fieldHeight, std::vector<int>(m_fieldWidth, 0));

    if (fillWithRandom) initializeRandom();
    else initializeManual();
}
\end{lstlisting}

\subsubsection{Метод initializeRandom}
В листинге~\ref{lst:initializeRandom} представлен код метода \texttt{initializeRandom}. Метод явно ничего не принимает и не возвращает, а работает только с атрибутами класса \texttt{CellularAutomaton}. В результате его работы атрибут \texttt{m\_field} заполняется нулями и единицами случайным образом, для этого используется равномерное распределение.

\begin{lstlisting}[caption={Код метода initializeRandom.}, label={lst:initializeRandom}]
void CellularAutomaton::initializeRandom()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 1);

    for (int y = 0; y < m_fieldHeight; ++y)
    {
        for (int x = 0; x < m_fieldWidth; ++x)
        {
            m_field[y][x] = dis(gen);
        }
    }
}
\end{lstlisting}    

\subsubsection{Метод initializeManual}
В листинге~\ref{lst:initializeManual} представлен код метода \texttt{initializeManual}. Метод не принимает аргументов и ничего не возвращает. Он позволяет пользователю вручную ввести начальное состояние поля клеточного автомата. Для каждой клетки запрашивается значение 0 или 1, которые сохраняются в атрибуте \texttt{m\_field}.

\begin{lstlisting}[caption={Код метода initializeManual.}, label={lst:initializeManual}]
void CellularAutomaton::initializeManual()
{
    std::cout << "Введите начальное состояние поля (" << m_fieldWidth << " x " << m_fieldHeight << ").\n";
    std::cout << "Введите 0 или 1 для каждой клетки.\n";

    for (int y = 0; y < m_fieldHeight; ++y)
    {
        for (int x = 0; x < m_fieldWidth; ++x)
        {
            std::cout << "Клетка (" << x << ", " << y << "): ";
            int cellValue = inputNumber(0, 1);

            m_field[y][x] = cellValue;
        }
    }
}
\end{lstlisting}
    
\subsubsection{Метод getCellState}
В листинге~\ref{lst:getCellState} представлен код метода \texttt{getCellState}. Метод принимает на вход координаты клетки \texttt{int x} и \texttt{int y}. Возвращает \texttt{int} -- состояние клетки по указанным координатам. Если координаты выходят за пределы поля, то поведение определяется граничными условиями, заданными атрибутом \texttt{m\_boundaryCondition}. 

\begin{lstlisting}[caption={Код метода getCellState.}, label={lst:getCellState}]
int CellularAutomaton::getCellState(int x, int y) const
{
    if (x < 0 || x >= m_fieldWidth || y < 0 || y >= m_fieldHeight)
    {
        switch (m_boundaryCondition)
        {
        case BOUNDARY_ONES:
            return 1;
        case BOUNDARY_ZEROS:
            return 0;
        case BOUNDARY_TOROIDAL:
            x = (x + m_fieldWidth) % m_fieldWidth;
            y = (y + m_fieldHeight) % m_fieldHeight;
            return m_field[y][x];
        default:
            return 0;
        }
    }
    return m_field[y][x];
}
\end{lstlisting}

\subsubsection{Метод getNeighborhoodIndex}
В листинге~\ref{lst:getNeighborhoodIndex} представлен код метода \texttt{getNeighborhoodIndex}. Метод принимает на вход координаты клетки \texttt{int x} и \texttt{int y}. Возвращает \texttt{int} -- индекс конфигурации окрестности фон Неймана клетки. Индекс вычисляется на основе состояний центральной клетки и её четырёх соседей (сверху, снизу, слева и справа), где каждый сосед соответствует одному биту в индексе. Этот индекс используется для определения следующего состояния клетки по функции переходов в методе \texttt{update}.

\begin{lstlisting}[caption={Код метода getNeighborhoodIndex.}, label={lst:getNeighborhoodIndex}]
int CellularAutomaton::getNeighborhoodIndex(int x, int y) const
{
    int s0 = getCellState(x, y);
    int s1 = getCellState(x, y - 1);
    int s2 = getCellState(x, y + 1);
    int s3 = getCellState(x - 1, y);
    int s4 = getCellState(x + 1, y);

    int index = (s0 << 4) | (s1 << 3) | (s2 << 2) | (s3 << 1) | s4;

    return index;
}
\end{lstlisting}

\subsubsection{Метод update}
В листинге~\ref{lst:update} представлен код метода \texttt{update}. Метод не принимает аргументов и ничего не возвращает. Он обновляет состояние клеточного автомата на следующий временной шаг. Для каждой клетки вычисляется новое состояние на основе текущего состояния и функции переходов, значения которой хранятся в битах числа \texttt{m\_functionValues}. После вычисления новое состояние сохраняется в \texttt{m\_fieldNextState}, а затем происходит обмен содержимого \texttt{m\_field} и \texttt{m\_fieldNextState}.

\begin{lstlisting}[caption={Код метода update.}, label={lst:update}]
void CellularAutomaton::update()
{
    for (int y = 0; y < m_fieldHeight; ++y)
    {
        for (int x = 0; x < m_fieldWidth; ++x)
        {
            int neighborhood = getNeighborhoodIndex(x, y);
            m_fieldNextState[y][x] = (m_functionValues >> neighborhood) & 1;
        }
    }

    m_field.swap(m_fieldNextState);
}
\end{lstlisting}

\subsubsection{Метод displayField}
В листинге~\ref{lst:displayField} представлен код метода \texttt{displayField}. Метод не принимает аргументов и ничего не возвращает. Он выводит текущее состояние поля клеточного автомата в консоль, отображая каждую клетку как '0' или '1'.

\begin{lstlisting}[caption={Код метода displayField.}, label={lst:displayField}]
void CellularAutomaton::displayField() const
{
    for (const auto& row : m_field)
    {
        for (const auto& cell : row)
        {
            std::cout << (cell ? '1' : '0') << ' ';
        }
        std::cout << '\n';
    }
}
\end{lstlisting}


    \subsection{Функция main}
    В функции main, код которой представлен в листинге~\ref{lst:main}, содержится бесконечный цикл, который обрабатывает пользовательский ввод. На каждой итерации цикла, пользователю предлагается выбрать конфигурацию конечного двумерного автомата и количество итераций. Затем внутри функции создаётся объект класса \texttt{CellularAutomaton}, с заданными пользователем параметрами, и у него вызывается метод \texttt{update} согласно указанному количеству итераций. Функция \texttt{main} возвращает целое число, которое является кодом завершения программы - 0, если программа выполнилась успешно, и ненулевое значение, если произошла какая-либо ошибка.


\begin{lstlisting}[caption={Код функции main.}, label={lst:main}]
int main()
{
    setlocale(LC_ALL, "Russian");

    while (true) {
        clear();

        cout << "Выберите граничные условия:\n"
            "Единичные (0)\n"
            "Нулевые (1)\n"
            "Тороидальные (2)\n"
            "Завершить работу (3)\n\n";
        int actionId = inputNumber(0, 3);

        clear();

        if (actionId == 3) {
            cout << "Выйти из программы? (yes/no)\n";
            if (userApprove()) return 0;
            continue;
        }

        BoundaryCondition boundaryCondition = static_cast<BoundaryCondition>(actionId);

        cout << "Укажите ширину поля (min 1): ";
        int fieldWidth = inputNumber(1);

        cout << "Укажите высоту поля (min 1): ";
        int fieldHeight = inputNumber(1);

        cout << "Укажите количество итераций (min 1): ";
        int iterationsCount = inputNumber(1);

        cout << "Заполнить поле случайными значениями? (yes/no)\n";
        bool fillWithRandom = userApprove();

        CellularAutomaton ca(fieldWidth, fieldHeight, fillWithRandom, boundaryCondition);
        clear();

        cout << "\nИтерация 0:\n";
        ca.displayField();

        for (int i = 0; i < iterationsCount; ++i)
        {
            cout << "\nИтерация " << i + 1 << ":\n";
            ca.update();
            ca.displayField();
        }

        cout << "\nНажмите на enter, чтобы продолжить...";
        waitForEnter();
    }
}
\end{lstlisting}

    \subsection{Пользовательский ввод}
    Одним из требований к лабораторным работам являлась защита от некорректного пользовательского ввода. Для реализации такой защиты и большей читаемости кода все функции связанные с пользовательским вводом были вынесены в отдельный файл. Все функции проверяют данные вводимые пользователем и, если что-то не так, печатают информацию о неверном выводе.

    \begin{itemize}
        \item {\tt int inputNumber(int minVal, int maxVal)} - принимает два числа, которые указывают диапозон возможных для ввода значений. Возвращает введённое пользователем число.
        \item {\tt char* inputString(int maxLen)} - принимает число, максимальную длину строки, возвращает указатель на строку введённую пользователем. Не позволяет вводить строки больше указанной длины.
        \item {\tt bool userApprove()} - возвращает true, если пользователь ввёл <<yes>> или <<y>> и false, если пользователь ввёл <<no>> или <<n>>.
        \item {\tt void waitForEnter()} - останавливает выполнение программы пока пользователь не нажмёт на клавишу <<Enter>>.
    \end{itemize}
    

    \newpage
    \section{Анализ клеточного автомата}
    \subsection{Паттерны}

    В ходе работы были исследованы паттерны клеточного автомата на поле размером $5 \times 5$ клеток в течение 25 итераций с различными начальными конфигурациями и граничными условиями. Краткие результаты для каждой комбинации граничных условий и начальных конфигураций представлены в таблице~\ref{tbl:patters}. Начальные конфигурации представлены на Рис.~\ref{fig:start_zeros}-\ref{fig:start_ones}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.14\linewidth]{img/start_zeros.png}
       \caption{Начальная конфигурация <<Пустое поле>>.}
       \label{fig:start_zeros}
    \end{figure}
    
    \begin{figure}[h!]
        \centering
        \includegraphics[width=0.14\linewidth]{img/start_hline.png}
        \caption{Начальная конфигурация <<Горизонтальная палочка>>.}
        \label{fig:start_hline}
    \end{figure}
    
    \begin{figure}[h!]
        \centering
        \includegraphics[width=0.14\linewidth]{img/start_vline.png}
        \caption{Начальная конфигурация <<Вертикальная палочка>>.}
        \label{fig:start_vline}
    \end{figure}
    
    \begin{figure}[h!]
        \centering
        \includegraphics[width=0.14\linewidth]{img/start_square.png}
        \caption{Начальная конфигурация <<Квадратик>>.}
        \label{fig:start_square}
    \end{figure}
    
        \begin{figure}[h!]
           \centering
           \includegraphics[width=0.14\linewidth]{img/start_ones.png}
           \caption{Начальная конфигурация <<Единичное поле>>.}
           \label{fig:start_ones}
        \end{figure}

    \begin{table}[h!]
        \centering
        \caption{Результаты анализа клеточного автомата при различных начальных конфигурациях и граничных условиях.}
        \label{tbl:patters}
        \footnotesize
        \begin{tabularx}{\textwidth}{|X|X|X|}
        \hline
        \textbf{Исходная конфигурация} & \textbf{Граничные условия} & \textbf{Результат} \\
        \hline
        \multirow{3}{*}{Пустое поле} & Единичные & Случайные паттерны \\
        \cline{2-3}
                                     & Нулевые & Пустое поле \\
        \cline{2-3}
                                     & Тороидальные & Пустое поле \\
        \hline
        \multirow{3}{*}{Горизонтальная палочка} & Единичные & Случайные паттерны \\
        \cline{2-3}
                                                & Нулевые & Движение вверх и нулевое поле \\
        \cline{2-3}
                                                & Тороидальные & Циклическое движение вверх \\
        \hline
        \multirow{3}{*}{Вертикальная палочка} & Единичные & Случайные паттерны \\
        \cline{2-3}
                                              & Нулевые & Зацикливание \\
        \cline{2-3}
                                              & Тороидальные & Зацикливание \\
        \hline
        \multirow{3}{*}{Квадратик} & Единичные & Случайные паттерны \\
        \cline{2-3}
                                    & Нулевые & Зацикливание \\
        \cline{2-3}
                                    & Тороидальные & Случайные паттерны \\
        \hline
        \multirow{3}{*}{Единичное поле} & Единичные & Случайные паттерны \\
        \cline{2-3}
                                        & Нулевые & Зацикливание \\
        \cline{2-3}
                                        & Тороидальные & Превратилось в нулевое поле \\
        \hline
        \end{tabularx}
    \end{table}
    
    


    \subsection{Сходимость}
    
    \subsection{Классификация}
    

    \newpage
    \section {Результаты работы программы}

    В данном разделе представлены скриншоты с примерами ввода-вывода, демонстрирующие работу программы и её основной функционал.

    На Рис.~\ref{fig:menu1} показано основное меню программы, в котором перечислены доступные пользователю действия.


    \newpage
    \section*{Заключение}
    
    \addcontentsline{toc}{section}{Заключение}
    
    В результате выполнения лабораторной работы было разработано консольное приложение, ...


    \newpage
    \section*{Список литературы}
    \addcontentsline{toc}{section}{Список литературы}
    
    \vspace{-1.5cm}
    \begin{thebibliography}{0}
        \bibitem{vostrov}
        Востров А. В, <<Теория алгоритмов>> URL: \url{https://tema.spbstu.ru/algorithm/}, Дата обращения: 01.12.2024
        \bibitem{wolfram}
        Wolfram, Stephen <<A New Kind of Science>>. — Wolfram Media (2002) — 1197 с.
    \end{thebibliography}
\end{document}