diff --git a/04-tss-01-lab-report.tex b/04-tss-01-lab-report.tex index 1ec5551..478ce2a 100644 --- a/04-tss-01-lab-report.tex +++ b/04-tss-01-lab-report.tex @@ -13,13 +13,259 @@ % ... работе, номер, тема, предмет, ?а, кто \makeReportTitle{лабораторной}{1}{Введение}{Программное обеспечение телекоммуникационных систем}{}{И.М.Сидякин} \newpage +\sloppy \thispagestyle{empty} \tableofcontents \newpage \pagestyle{fancy} \section{Цель} +Знакомство с языком Erlang, средой исполнения программ на языке. + +\section{Задание на часть 1} +\begin{enumerate} +\item Сделайте модуль с именем \code{fib}, в файле \code{fib.erl}. +\item Создайте, не используя хвостовую рекурсию, функцию \code{fib_p} которая получает один аргумент \code{N}, и возвращает \code{N}-е значение последовательности Фибоначчи. +\item Создайте другую функцию без хвостовой рекурсии \code{fib_g} по той же спецификации, используя сторожевые последовательности. +\item Создайте третью функцию \code{tail_fib} по той же спецификации, но с хвостовой рекурсией. (Для хвостовой рекурсии понадобится вспомогательная функция). +\end{enumerate} + +\section{Выполнение} +\subsection{Сопоставление с образцом} +Код выполненной лабораторной работы возможно найти по ссылке на \href{https://git.iovchinnikov.ru/ivan-igorevich/erlang-labs}{репозиторий}. Работа выполнена на двух устройствах (с синхронизацией работы через репозиторий): +\begin{verbatim} +Debian 11: +- IDEA 2022.3.1 CE +- ErlangPlugin 0.11.1162. +- Erlang/OTP 23 [erts-11.1.8] [64-bit] + +Mac OS X (уточнить): +- IDEA 2022.3.1 CE +- ErlangPlugin 0.11.1162. +- Erlang/OTP 23 [erts-11.1.8] [64-bit] +\end{verbatim} + +Основные синтаксические конструкции, использованные при написании функций взяты из материалов к лабораторной работе, со слайда 1-27 презентации. Код написанного модуля, вычисляющего число Фибоначчи приведён в листинге \hrf{lst:fib-p}, код юнит-теста написанного модуля в листинге \hrf{lst:fib-p-test}, а снимок экрана, демонстрирующий успешность пройденных тестов на рисунке \hrf{pic:fib-p-pow}. + +\begin{lstlisting}[language=Erlang, style=CCodeStyle, caption={Код модуля}, label={lst:fib-p}] +-module(fib). +-export([fib_p/1]). + +% <@\lh{dkgreen}{Сопоставление с образцом}@> +fib_p(0) -> 0; +fib_p(1) -> 1; +fib_p(N) -> fib_p(N - 1) + fib_p(N - 2). + +\end{lstlisting} + +\begin{lstlisting}[language=Erlang, style=CCodeStyle, caption={Код тестов модуля}, label={lst:fib-p-test}] +-module(fib_test). +-include_lib("eunit/include/eunit.hrl"). + +fib_test_() -> [ + {"Test fib_p", fun test_fib_p/0 } +]. + +test_fib_p() -> + ?assertEqual(0, fib:fib_p(0)), + ?assertEqual(1, fib:fib_p(1)), + ?assertEqual(1, fib:fib_p(2)), + ?assertEqual(2, fib:fib_p(3)), + ?assertEqual(3, fib:fib_p(4)), + ?assertEqual(5, fib:fib_p(5)), + ?assertEqual(8, fib:fib_p(6)), + ?assertEqual(13, fib:fib_p(7)), + ?assertEqual(21, fib:fib_p(8)), + ?assertEqual(34, fib:fib_p(9)), + ?assertEqual(55, fib:fib_p(10)). + +\end{lstlisting} + +\begin{figure}[H] + \centering + \includegraphics[width=16cm]{04-tss-01-lab-fib-p.png} + \caption{Запуск и успешное выполнение тестов} + \label{pic:fib-p-pow} +\end{figure} + +\subsection{Сторожевая последовательность и ключевое слово \code{when}} +Основные синтаксические конструкции, использованные при написании функций взяты из материалов к лабораторной работе, со слайда 1-28 презентации и из \href{https://www.erlang.org/doc/getting_started/seq_prog.html#matching,-guards,-and-scope-of-variables}{документации} к языку. + +Код написанного модуля, вычисляющего число Фибоначчи с помощью сторожевой последовательности приведён в листинге \hrf{lst:fib-g}, код юнит-теста написанного модуля в листинге \hrf{lst:fib-g-test}, а снимок экрана, демонстрирующий успешность пройденных тестов для обеих функций на рисунке \hrf{pic:fib-g-pow}. + +\begin{lstlisting}[language=Erlang, style=CCodeStyle, caption={Код модуля}, label={lst:fib-g}] +-module(fib). +-export([fib_p/1, fib_g/1]). + +% <@\lh{dkgreen}{Сопоставление с образцом}@> +% ... + +% <@\lh{dkgreen}{Сторожевая последовательность}@> +fib_g(N) when N < 1 -> 0; +fib_g(N) when N < 2 -> 1; +fib_g(N) -> fib_g(N - 1) + fib_g(N - 2). + +\end{lstlisting} + +\begin{lstlisting}[language=Erlang, style=CCodeStyle, caption={Код тестов функции}, label={lst:fib-g-test}] +-module(fib_test). +-include_lib("eunit/include/eunit.hrl"). + +fib_test_() -> [ + {"Test fib_p", fun test_fib_p/0 }, + {"Test fib_g", fun test_fib_g/0 } +]. + +% test_fib_p()/0 -> ... + +test_fib_g() -> + ?assertEqual(0, fib:fib_g(0)), + ?assertEqual(1, fib:fib_g(1)), + ?assertEqual(1, fib:fib_g(2)), + ?assertEqual(2, fib:fib_g(3)), + ?assertEqual(3, fib:fib_g(4)), + ?assertEqual(5, fib:fib_g(5)), + ?assertEqual(8, fib:fib_g(6)), + ?assertEqual(13, fib:fib_g(7)), + ?assertEqual(21, fib:fib_g(8)), + ?assertEqual(34, fib:fib_g(9)), + ?assertEqual(55, fib:fib_g(10)). + +\end{lstlisting} + +\begin{figure}[H] + \centering + \includegraphics[width=10cm]{04-tss-01-lab-fib-g.png} + \caption{Запуск и успешное выполнение тестов} + \label{pic:fib-g-pow} +\end{figure} + +\subsection{Использование хвостовой рекурсии} +Основные синтаксические конструкции, использованные при написании функций взяты из материалов к лабораторной работе, со слайда 1-31 презентации и из \href{https://ru.wikipedia.org/wiki/Хвостовая_рекурсия}{статьи} в Wikipedia. + +Код написанного модуля, вычисляющего число Фибоначчи с помощью сторожевой последовательности приведён в листинге \hrf{lst:fib-g}, код юнит-теста написанного модуля в листинге \hrf{lst:fib-g-test}, а снимок экрана, демонстрирующий успешность пройденных тестов трёх функций на рисунке \hrf{pic:fib-g-pow}. + +\begin{lstlisting}[language=Erlang, style=CCodeStyle, caption={Код модуля}, label={lst:fib-t}] +-module(fib). +-export([fib_p/1, fib_g/1, tail_fib/1]). + +% <@\lh{dkgreen}{Сопоставление с образцом}@> +% ... + +% <@\lh{dkgreen}{Сторожевая последовательность}@> +% ... + +% <@\lh{dkgreen}{Хвостовая рекурсия}@> +tail_fib(N) -> tfib(N, 0, 1). +tfib(0, Result, Next) -> Result; +tfib(N, Result, Next) -> tfib(N - 1, Next, Result + Next). + +\end{lstlisting} + +\begin{lstlisting}[language=Erlang, style=CCodeStyle, caption={Код тестов функции}, label={lst:fib-t-test}] +-module(fib_test). +-include_lib("eunit/include/eunit.hrl"). + +fib_test_() -> [ + {"Test fib_p", fun test_fib_p/0 }, + {"Test fib_g", fun test_fib_g/0 }, + {"Test tail_fib", fun test_tail_fib/0 } +]. + +% test_fib_p()/0 -> ... + +% test_fib_g()/0 -> ... + +test_tail_fib() -> + ?assertEqual(0, fib:tail_fib(0)), + ?assertEqual(1, fib:tail_fib(1)), + ?assertEqual(1, fib:tail_fib(2)), + ?assertEqual(2, fib:tail_fib(3)), + ?assertEqual(3, fib:tail_fib(4)), + ?assertEqual(5, fib:tail_fib(5)), + ?assertEqual(8, fib:tail_fib(6)), + ?assertEqual(13, fib:tail_fib(7)), + ?assertEqual(21, fib:tail_fib(8)), + ?assertEqual(34, fib:tail_fib(9)), + ?assertEqual(55, fib:tail_fib(10)). + +\end{lstlisting} + +\begin{figure}[H] + \centering + \includegraphics[width=10cm]{04-tss-01-lab-fib-t.png} + \caption{Запуск и успешное выполнение тестов} + \label{pic:fib-t-pow} +\end{figure} + +\subsection{Проверка времени выполнения} +Основные синтаксические конструкции, использованные при написании функций взяты из \href{https://www.erlang.org/doc/man/timer.html#tc-3}{документации} к языку и \href{https://www.tutorialspoint.com/erlang/erlang_loops.htm}{статьи}. + +Код функций, вычисляющих время исполнения функций приведён в листинге \hrf{lst:fib-time}, снимки экрана, демонстрирующие время выполнения функций рисунке \hrf{pic:fib-t-time}. + +\begin{lstlisting}[language=Erlang, style=CCodeStyle, caption={Время выполнения}, label={lst:fib-time}] +say() -> io:format("The result is: ~p~n", [tail_fib(10)]). + +exec_time(Depth) -> Start = os:timestamp(), + tail_fib(Depth), + io:format("Depth = ~p, Time ~f sec~n", [Depth, (timer:now_diff(os:timestamp(), Start) / 1000)]). + +for(0, _, _) -> []; +for(N, Term, Step) when N > 0 -> + exec_time(N), + [Term | for(N - Step, Term, Step)]. + +start_time_chack() -> + for(50000, 5000, 5000). + +\end{lstlisting} + +\begin{figure}[H] + \centering + \begin{subfigure}[b]{0.47\textwidth} + \centering + \includegraphics[width=\textwidth]{04-tss-01-lab-fib-time-p.png} + \caption{\code{fib_p}} + \label{pic:fib-p-time} + \end{subfigure} + \hfill + \begin{subfigure}[b]{0.47\textwidth} + \centering + \includegraphics[width=\textwidth]{04-tss-01-lab-fib-time-t.png} + \caption{\code{tail_fib}} + \label{pic:fib-tail-time} + \end{subfigure} + \caption{Время выполнения функций} + \label{pic:fib-t-time} +\end{figure} + +\subsection{Контрольные вопросы} + +\begin{enumerate} +\item Начиная с \code{N = 20} увеличивать \code{N} с шагом \code{5} до тех пор, пока вычисление \code{fib_p(N)} будет занимать меньше пяти секунд. При каком \code{N} это условие перестает выполняться? Почему так происходит? + +Время исполнения превышает \code{5} секунд при подсчёте 30-го значения Фибоначчи. Это происходит, потому что при прямом подсчёте чисел Фибоначчи рекурсивным способом происходит повторное вычисление каждого числа, входящего в состав вычисляемого и дерево рекурсивных вызовов разрастается квадратично. + +\item Сколько времени тратится на вычисление \code{tail_fib(10000)}? Почему? + +На вычисление 10000-го значения Фибоначчи функцией с хвостовой рекурсией тратится значительно меньше времени (1,371 сек), поскольку функция переиспользует вычисленные на ранних этапах значения для вычисления каждого следующего, что делает её больше похожей на простой цикл в процедурном программировании. +\end{enumerate} + +\section{Задание на часть 2} +Квадраты простых чисел и функция Мёбиуса + +\begin{enumerate} +\item Создайте модуль с именем \code{mobius}, в файле \code{mobius.erl}. +\item Создайте функцию \code{is_prime}, которая получает аргумент \code{N} и возвращает \code{true}, если число простое или \code{false}, если число не является простым. +\item Сделайте функцию \code{prime_factors}, которая получает аргумент \code{N} и возвращает список простых сомножителей \code{N}. +\item Сделайте функцию \code{is_square_multiple}, которая получает аргумент \code{N}, и возвращает \code{true}, если аргумент делится на квадрат простого числа или \code{false}, если не длится. +\item Наконец, сделайте функцию \code{find_square_multiples(Count, MaxN)}. Эта функция получает \code{Count} -- длину последовательности чисел делящихся на квадрат простого числа, и \code{MaxN} -- максимальное значение, после которого надо прекратить поиск. + \begin{itemize} + \item Если функция находит \code{Count} чисел подряд, делящихся на квадрат простого числа в диапазоне \code{[2, MaxN]}, она должна вернуть первое число из этой последовательности. + \item Если функция не находит серию из \code{Count} чисел делящихся на квадрат простого числа в этом диапазоне, она должна вернуть атом fail. + \end{itemize} +\item Найдите первый ряд из чисел делящихся на квадрат простого числа длиной 4, длиной 5, и длиной 6. Нужно выбрать значение \code{MaxN} равное 30000. Программа должна завершить вычисления в пределах одной минуты. +\end{enumerate} -\href{https://git.iovchinnikov.ru/ivan-igorevich/erlang-labs}{репозиторий} \end{document} diff --git a/pics/04-tss-01-lab-fib-g.png b/pics/04-tss-01-lab-fib-g.png new file mode 100644 index 0000000..2a51b48 Binary files /dev/null and b/pics/04-tss-01-lab-fib-g.png differ diff --git a/pics/04-tss-01-lab-fib-p.png b/pics/04-tss-01-lab-fib-p.png new file mode 100644 index 0000000..05443c1 Binary files /dev/null and b/pics/04-tss-01-lab-fib-p.png differ diff --git a/pics/04-tss-01-lab-fib-t.png b/pics/04-tss-01-lab-fib-t.png new file mode 100644 index 0000000..e5df4e7 Binary files /dev/null and b/pics/04-tss-01-lab-fib-t.png differ diff --git a/pics/04-tss-01-lab-fib-time-p.png b/pics/04-tss-01-lab-fib-time-p.png new file mode 100644 index 0000000..0631fec Binary files /dev/null and b/pics/04-tss-01-lab-fib-time-p.png differ diff --git a/pics/04-tss-01-lab-fib-time-t.png b/pics/04-tss-01-lab-fib-time-t.png new file mode 100644 index 0000000..e6b299b Binary files /dev/null and b/pics/04-tss-01-lab-fib-time-t.png differ