BMSTU/04-tss-01-lab-report.tex

272 lines
14 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\documentclass[a4paper,fontsize=14bp]{article}
\input{settings/common-preamble}
\input{settings/fancy-listings-preamble}
\input{settings/bmstu-preamble}
%\setcounter{secnumdepth}{0}
\numerationTop
\begin{document}
\thispagestyle{empty}
\makeBMSTUHeader
% ... работе, номер, тема, предмет, ?а, кто
\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}
\end{document}