|
|
% ===============================================
|
|
|
% ДЕМОНСТРАЦИЯ LAB9 TASK1
|
|
|
% Полная демонстрация всех предикатов
|
|
|
% ===============================================
|
|
|
|
|
|
% Главная демонстрация
|
|
|
demo :-
|
|
|
write('=== ДЕМОНСТРАЦИЯ LAB9 TASK1: ОСНОВНЫЕ ПРЕДИКАТЫ PROLOG ==='), nl, nl,
|
|
|
|
|
|
% 1. Демонстрация max/4
|
|
|
write('1. ПРЕДИКАТ MAX/4'), nl,
|
|
|
write('================'), nl,
|
|
|
demo_max,
|
|
|
nl,
|
|
|
|
|
|
% 2. Демонстрация факториалов
|
|
|
write('2. ФАКТОРИАЛЫ (РЕКУРСИЯ ВВЕРХ И ВНИЗ)'), nl,
|
|
|
write('===================================='), nl,
|
|
|
demo_factorial,
|
|
|
nl,
|
|
|
|
|
|
% 3. Демонстрация суммы цифр
|
|
|
write('3. СУММА ЦИФР ЧИСЛА (РЕКУРСИЯ ВВЕРХ И ВНИЗ)'), nl,
|
|
|
write('=========================================='), nl,
|
|
|
demo_digit_sum,
|
|
|
nl,
|
|
|
|
|
|
% 4. Демонстрация square_free
|
|
|
write('4. ПРОВЕРКА СВОБОДНОСТИ ОТ КВАДРАТОВ'), nl,
|
|
|
write('==================================='), nl,
|
|
|
demo_square_free,
|
|
|
nl,
|
|
|
|
|
|
% 5. Демонстрация операций со списками
|
|
|
write('5. ОПЕРАЦИИ СО СПИСКАМИ'), nl,
|
|
|
write('======================='), nl,
|
|
|
demo_list_operations,
|
|
|
nl,
|
|
|
|
|
|
% 6. Демонстрация удаления по сумме цифр
|
|
|
write('6. УДАЛЕНИЕ ЭЛЕМЕНТОВ ПО СУММЕ ЦИФР'), nl,
|
|
|
write('==================================='), nl,
|
|
|
demo_remove_by_digit_sum,
|
|
|
nl,
|
|
|
|
|
|
% 7. Сравнительный анализ рекурсий
|
|
|
write('7. СРАВНИТЕЛЬНЫЙ АНАЛИЗ РЕКУРСИЙ'), nl,
|
|
|
write('================================'), nl,
|
|
|
demo_recursion_comparison,
|
|
|
nl,
|
|
|
|
|
|
% 8. Практические примеры
|
|
|
write('8. ПРАКТИЧЕСКИЕ ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ'), nl,
|
|
|
write('===================================='), nl,
|
|
|
demo_practical_examples,
|
|
|
nl,
|
|
|
|
|
|
write('=== ДЕМОНСТРАЦИЯ ЗАВЕРШЕНА ==='), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация max/4
|
|
|
% -----------------------------------------------
|
|
|
demo_max :-
|
|
|
write('Предикат max(+X, +Y, +U, -Z) находит максимальное из трех чисел.'), nl, nl,
|
|
|
|
|
|
TestCases = [
|
|
|
(5, 3, 7),
|
|
|
(-5, -3, -1),
|
|
|
(10, 10, 10),
|
|
|
(0, -5, 3),
|
|
|
(100, 50, 75)
|
|
|
],
|
|
|
|
|
|
forall(member((X, Y, U), TestCases), demo_max_case(X, Y, U)),
|
|
|
|
|
|
write('Предикат также можно использовать для проверки:'), nl,
|
|
|
(max(10, 20, 15, 20) ->
|
|
|
write('✓ max(10, 20, 15, 20) - истина') ;
|
|
|
write('✗ max(10, 20, 15, 20) - ложь')), nl,
|
|
|
(max(10, 20, 15, 15) ->
|
|
|
write('✓ max(10, 20, 15, 15) - истина') ;
|
|
|
write('✗ max(10, 20, 15, 15) - ложь')), nl.
|
|
|
|
|
|
demo_max_case(X, Y, U) :-
|
|
|
max(X, Y, U, Z),
|
|
|
write('max('), write(X), write(', '), write(Y), write(', '), write(U),
|
|
|
write(') = '), write(Z), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация факториалов
|
|
|
% -----------------------------------------------
|
|
|
demo_factorial :-
|
|
|
write('Факториал реализован двумя способами:'), nl,
|
|
|
write('- fact_up(+N, -X) использует рекурсию вверх'), nl,
|
|
|
write('- fact_down(+N, -X) использует рекурсию вниз с аккумулятором'), nl, nl,
|
|
|
|
|
|
TestNumbers = [0, 1, 3, 5, 7, 10],
|
|
|
|
|
|
write('Сравнение результатов:'), nl,
|
|
|
write('N | Факториал (вверх) | Факториал (вниз) | Время (вверх) | Время (вниз)'), nl,
|
|
|
write('-----|-------------------|------------------|---------------|-------------'), nl,
|
|
|
|
|
|
forall(member(N, TestNumbers), demo_factorial_case(N)),
|
|
|
|
|
|
nl,
|
|
|
write('Демонстрация принципа работы:'), nl,
|
|
|
write('Рекурсия вверх: fact_up(3) = 3 * fact_up(2) = 3 * 2 * fact_up(1) = 3 * 2 * 1 = 6'), nl,
|
|
|
write('Рекурсия вниз: fact_down(3) вызывает helper(3,1) -> helper(2,3) -> helper(1,6) -> helper(0,6) = 6'), nl.
|
|
|
|
|
|
demo_factorial_case(N) :-
|
|
|
get_time(T1),
|
|
|
fact_up(N, F1),
|
|
|
get_time(T2),
|
|
|
fact_down(N, F2),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeUp is T2 - T1,
|
|
|
TimeDown is T3 - T2,
|
|
|
|
|
|
format('~w~4| | ~w~17| | ~w~16| | ~3f~13| | ~3f~n', [N, F1, F2, TimeUp, TimeDown]).
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация суммы цифр
|
|
|
% -----------------------------------------------
|
|
|
demo_digit_sum :-
|
|
|
write('Сумма цифр числа реализована двумя способами:'), nl,
|
|
|
write('- digit_sum_up(+N, -Sum) использует рекурсию вверх'), nl,
|
|
|
write('- digit_sum_down(+N, -Sum) использует рекурсию вниз с аккумулятором'), nl, nl,
|
|
|
|
|
|
TestNumbers = [0, 9, 123, 456, 999, 1000, 12345, 987654],
|
|
|
|
|
|
write('Сравнение результатов:'), nl,
|
|
|
write('Число | Сумма (вверх) | Сумма (вниз) | Время (вверх) | Время (вниз)'), nl,
|
|
|
write('--------|---------------|--------------|---------------|-------------'), nl,
|
|
|
|
|
|
forall(member(N, TestNumbers), demo_digit_sum_case(N)),
|
|
|
|
|
|
nl,
|
|
|
write('Демонстрация принципа работы для числа 123:'), nl,
|
|
|
write('Рекурсия вверх: digit_sum_up(123) = 3 + digit_sum_up(12) = 3 + 2 + digit_sum_up(1) = 3 + 2 + 1 = 6'), nl,
|
|
|
write('Рекурсия вниз: helper(123,0) -> helper(12,3) -> helper(1,5) -> helper(0,6) = 6'), nl.
|
|
|
|
|
|
demo_digit_sum_case(N) :-
|
|
|
get_time(T1),
|
|
|
digit_sum_up(N, S1),
|
|
|
get_time(T2),
|
|
|
digit_sum_down(N, S2),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeUp is T2 - T1,
|
|
|
TimeDown is T3 - T2,
|
|
|
|
|
|
format('~w~7| | ~w~12| | ~w~11| | ~6f~9| | ~6f~n', [N, S1, S2, TimeUp, TimeDown]).
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация square_free
|
|
|
% -----------------------------------------------
|
|
|
demo_square_free :-
|
|
|
write('Предикат square_free(+N) проверяет, свободно ли число от квадратов.'), nl,
|
|
|
write('Число свободно от квадратов, если оно не делится на квадрат простого числа > 1.'), nl, nl,
|
|
|
|
|
|
write('Примеры свободных от квадратов чисел:'), nl,
|
|
|
SquareFreeNumbers = [1, 2, 3, 5, 6, 7, 10, 11, 13, 14, 15, 17, 19, 21, 22],
|
|
|
demo_square_free_list(SquareFreeNumbers, 'свободны'),
|
|
|
|
|
|
nl,
|
|
|
write('Примеры НЕ свободных от квадратов чисел:'), nl,
|
|
|
NonSquareFreeNumbers = [4, 8, 9, 12, 16, 18, 20, 24, 25, 27, 28, 32, 36],
|
|
|
demo_square_free_list(NonSquareFreeNumbers, 'не свободны'),
|
|
|
|
|
|
nl,
|
|
|
write('Объяснения:'), nl,
|
|
|
write('- 12 не свободно от квадратов: 12 = 4 × 3, где 4 = 2²'), nl,
|
|
|
write('- 18 не свободно от квадратов: 18 = 9 × 2, где 9 = 3²'), nl,
|
|
|
write('- 15 свободно от квадратов: 15 = 3 × 5 (простые множители)'), nl.
|
|
|
|
|
|
demo_square_free_list([], _).
|
|
|
demo_square_free_list([N|Rest], Description) :-
|
|
|
(square_free(N) -> Status = '✓' ; Status = '✗'),
|
|
|
write(Status), write(' '), write(N),
|
|
|
(Rest = [] -> nl ; (write(', '), demo_square_free_list(Rest, Description))).
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация операций со списками
|
|
|
% -----------------------------------------------
|
|
|
demo_list_operations :-
|
|
|
write('Операции со списками включают ввод, вывод и вычисление суммы.'), nl, nl,
|
|
|
|
|
|
write('Демонстрация предикатов sum_list_down и sum_list_up:'), nl,
|
|
|
|
|
|
TestLists = [
|
|
|
[],
|
|
|
[5],
|
|
|
[1, 2, 3],
|
|
|
[10, 20, 30, 40],
|
|
|
[-1, 1, -2, 2],
|
|
|
[0, 0, 0, 0],
|
|
|
[100, -50, 25]
|
|
|
],
|
|
|
|
|
|
write('Список | Сумма (вниз) | Сумма (вверх) | Время (вниз) | Время (вверх)'), nl,
|
|
|
write('----------------------|--------------|---------------|--------------|-------------'), nl,
|
|
|
|
|
|
forall(member(List, TestLists), demo_list_sum_case(List)),
|
|
|
|
|
|
nl,
|
|
|
write('Принципы работы:'), nl,
|
|
|
write('sum_list_down([1,2,3]): sum_list_down([2,3]) + 1 = (sum_list_down([3]) + 2) + 1 = ((0 + 3) + 2) + 1 = 6'), nl,
|
|
|
write('sum_list_up([1,2,3]): helper([1,2,3], 0) -> helper([2,3], 1) -> helper([3], 3) -> helper([], 6) = 6'), nl,
|
|
|
|
|
|
nl,
|
|
|
write('Демонстрация write_list:'), nl,
|
|
|
TestListsForDisplay = [[], [1], [1,2,3], [a,b,c,d]],
|
|
|
forall(member(List, TestListsForDisplay),
|
|
|
(write('write_list('), write(List), write(') выводит: '), write_list(List))).
|
|
|
|
|
|
demo_list_sum_case(List) :-
|
|
|
get_time(T1),
|
|
|
sum_list_down(List, S1),
|
|
|
get_time(T2),
|
|
|
sum_list_up(List, S2),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeDown is T2 - T1,
|
|
|
TimeUp is T3 - T2,
|
|
|
|
|
|
format('~w~21| | ~w~11| | ~w~12| | ~6f~8| | ~6f~n', [List, S1, S2, TimeDown, TimeUp]).
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация удаления по сумме цифр
|
|
|
% -----------------------------------------------
|
|
|
demo_remove_by_digit_sum :-
|
|
|
write('Предикат remove_by_digit_sum(+List, +TargetSum, -Result) удаляет'), nl,
|
|
|
write('все элементы, сумма цифр которых равна заданной.'), nl, nl,
|
|
|
|
|
|
TestCases = [
|
|
|
([12, 21, 34, 43, 50], 3, 'элементы с суммой цифр 3: 12(1+2=3), 21(2+1=3)'),
|
|
|
([123, 456, 789, 111], 6, 'элементы с суммой цифр 6: 123(1+2+3=6)'),
|
|
|
([10, 20, 30, 101, 110], 2, 'элементы с суммой цифр 2: 20(2+0=2), 101(1+0+1=2), 110(1+1+0=2)'),
|
|
|
([999, 888, 777, 666], 27, 'элементы с суммой цифр 27: 999(9+9+9=27)'),
|
|
|
([1, 11, 111, 1111], 1, 'элементы с суммой цифр 1: 1(1=1)'),
|
|
|
([abc, 12, def, 21, -5], 3, 'целые элементы с суммой цифр 3 (нецелые сохраняются)')
|
|
|
],
|
|
|
|
|
|
forall(member((List, TargetSum, Description), TestCases),
|
|
|
demo_remove_case(List, TargetSum, Description)),
|
|
|
|
|
|
nl,
|
|
|
write('Особенности обработки:'), nl,
|
|
|
write('- Обрабатываются только неотрицательные целые числа'), nl,
|
|
|
write('- Нецелые и отрицательные элементы сохраняются в результате'), nl,
|
|
|
write('- Порядок элементов в результирующем списке сохраняется'), nl.
|
|
|
|
|
|
demo_remove_case(List, TargetSum, Description) :-
|
|
|
remove_by_digit_sum(List, TargetSum, Result),
|
|
|
write('Исходный список: '), write(List), nl,
|
|
|
write('Удаляем '), write(Description), nl,
|
|
|
write('Результат: '), write(Result), nl,
|
|
|
write('---'), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Сравнительный анализ рекурсий
|
|
|
% -----------------------------------------------
|
|
|
demo_recursion_comparison :-
|
|
|
write('Сравнение эффективности рекурсии вверх и вниз:'), nl, nl,
|
|
|
|
|
|
write('РЕКУРСИЯ ВВЕРХ (традиционная):'), nl,
|
|
|
write('+ Простота реализации и понимания'), nl,
|
|
|
write('+ Естественная математическая запись'), nl,
|
|
|
write('- Использует стек вызовов (может привести к переполнению)'), nl,
|
|
|
write('- Вычисления происходят при возврате из рекурсии'), nl, nl,
|
|
|
|
|
|
write('РЕКУРСИЯ ВНИЗ (с аккумулятором):'), nl,
|
|
|
write('+ Эффективнее по памяти (хвостовая рекурсия)'), nl,
|
|
|
write('+ Может быть оптимизирована компилятором'), nl,
|
|
|
write('+ Вычисления происходят при погружении в рекурсию'), nl,
|
|
|
write('- Менее интуитивная реализация'), nl, nl,
|
|
|
|
|
|
write('Практическое сравнение для больших значений:'), nl,
|
|
|
TestValues = [15, 20, 25],
|
|
|
forall(member(N, TestValues), demo_recursion_performance(N)).
|
|
|
|
|
|
demo_recursion_performance(N) :-
|
|
|
write('Тестирование для N = '), write(N), write(':'), nl,
|
|
|
|
|
|
% Факториал
|
|
|
get_time(T1),
|
|
|
fact_up(N, F1),
|
|
|
get_time(T2),
|
|
|
fact_down(N, F2),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeFactUp is T2 - T1,
|
|
|
TimeFactDown is T3 - T2,
|
|
|
|
|
|
write(' Факториал: рекурсия вверх = '), write(TimeFactUp), write('с, '),
|
|
|
write('рекурсия вниз = '), write(TimeFactDown), write('с'), nl,
|
|
|
|
|
|
% Сумма цифр
|
|
|
get_time(T4),
|
|
|
digit_sum_up(N, S1),
|
|
|
get_time(T5),
|
|
|
digit_sum_down(N, S2),
|
|
|
get_time(T6),
|
|
|
|
|
|
TimeSumUp is T5 - T4,
|
|
|
TimeSumDown is T6 - T5,
|
|
|
|
|
|
write(' Сумма цифр: рекурсия вверх = '), write(TimeSumUp), write('с, '),
|
|
|
write('рекурсия вниз = '), write(TimeSumDown), write('с'), nl, nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Практические примеры использования
|
|
|
% -----------------------------------------------
|
|
|
demo_practical_examples :-
|
|
|
write('Практические сценарии использования предикатов:'), nl, nl,
|
|
|
|
|
|
write('СЦЕНАРИЙ 1: Анализ числовых данных'), nl,
|
|
|
write('--------------------------------'), nl,
|
|
|
demo_scenario_analysis,
|
|
|
nl,
|
|
|
|
|
|
write('СЦЕНАРИЙ 2: Обработка списков чисел'), nl,
|
|
|
write('----------------------------------'), nl,
|
|
|
demo_scenario_list_processing,
|
|
|
nl,
|
|
|
|
|
|
write('СЦЕНАРИЙ 3: Математические вычисления'), nl,
|
|
|
write('------------------------------------'), nl,
|
|
|
demo_scenario_math,
|
|
|
nl.
|
|
|
|
|
|
demo_scenario_analysis :-
|
|
|
Numbers = [12, 45, 123, 7, 89, 456],
|
|
|
write('Анализируем числа: '), write(Numbers), nl,
|
|
|
|
|
|
% Анализ каждого числа
|
|
|
forall(member(N, Numbers), demo_number_analysis(N)),
|
|
|
|
|
|
% Фильтрация по сумме цифр
|
|
|
remove_by_digit_sum(Numbers, 9, FilteredNums),
|
|
|
write('После удаления чисел с суммой цифр 9: '), write(FilteredNums), nl.
|
|
|
|
|
|
demo_number_analysis(N) :-
|
|
|
digit_sum_up(N, DigitSum),
|
|
|
(square_free(N) -> SFStatus = 'свободно' ; SFStatus = 'не свободно'),
|
|
|
write(' '), write(N), write(': сумма цифр = '), write(DigitSum),
|
|
|
write(', '), write(SFStatus), write(' от квадратов'), nl.
|
|
|
|
|
|
demo_scenario_list_processing :-
|
|
|
OriginalList = [10, 25, 67, 123, 89, 456, 12, 78],
|
|
|
write('Исходный список: '), write(OriginalList), nl,
|
|
|
|
|
|
sum_list_up(OriginalList, TotalSum),
|
|
|
write('Общая сумма: '), write(TotalSum), nl,
|
|
|
|
|
|
% Удаляем элементы с определенной суммой цифр
|
|
|
remove_by_digit_sum(OriginalList, 6, Without6),
|
|
|
write('Без элементов с суммой цифр 6: '), write(Without6), nl,
|
|
|
|
|
|
sum_list_up(Without6, NewSum),
|
|
|
write('Новая сумма: '), write(NewSum), nl,
|
|
|
|
|
|
Difference is TotalSum - NewSum,
|
|
|
write('Разница: '), write(Difference), nl.
|
|
|
|
|
|
demo_scenario_math :-
|
|
|
write('Математические вычисления для N = 6:'), nl,
|
|
|
N = 6,
|
|
|
|
|
|
fact_up(N, Factorial),
|
|
|
write(' Факториал: '), write(Factorial), nl,
|
|
|
|
|
|
digit_sum_up(Factorial, FactDigitSum),
|
|
|
write(' Сумма цифр факториала: '), write(FactDigitSum), nl,
|
|
|
|
|
|
max(N, Factorial, FactDigitSum, MaxValue),
|
|
|
write(' Максимум из (N, N!, сумма_цифр(N!)): '), write(MaxValue), nl,
|
|
|
|
|
|
(square_free(N) ->
|
|
|
write(' N свободно от квадратов') ;
|
|
|
write(' N не свободно от квадратов')), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Интерактивные примеры
|
|
|
% -----------------------------------------------
|
|
|
demo_interactive_examples :-
|
|
|
write('=== ИНТЕРАКТИВНЫЕ ПРИМЕРЫ ==='), nl,
|
|
|
write('Вы можете попробовать следующие запросы в интерактивной сессии:'), nl, nl,
|
|
|
|
|
|
write('1. Основные предикаты:'), nl,
|
|
|
write(' ?- max(10, 5, 15, Z). % Z = 15'), nl,
|
|
|
write(' ?- fact_up(6, F). % F = 720'), nl,
|
|
|
write(' ?- fact_down(6, F). % F = 720'), nl,
|
|
|
write(' ?- digit_sum_up(123, S). % S = 6'), nl,
|
|
|
write(' ?- digit_sum_down(123, S). % S = 6'), nl,
|
|
|
write(' ?- square_free(15). % true'), nl,
|
|
|
write(' ?- square_free(12). % false'), nl, nl,
|
|
|
|
|
|
write('2. Работа со списками:'), nl,
|
|
|
write(' ?- sum_list_down([1,2,3,4], S). % S = 10'), nl,
|
|
|
write(' ?- sum_list_up([1,2,3,4], S). % S = 10'), nl,
|
|
|
write(' ?- write_list([a,b,c]). % [a, b, c]'), nl,
|
|
|
write(' ?- remove_by_digit_sum([12,21,34], 3, R). % R = [34]'), nl, nl,
|
|
|
|
|
|
write('3. Интерактивные программы:'), nl,
|
|
|
write(' ?- list_sum_program. % Интерактивная работа со списками'), nl,
|
|
|
write(' ?- interactive_demo. % Интерактивное меню'), nl, nl,
|
|
|
|
|
|
write('4. Тестирование и анализ:'), nl,
|
|
|
write(' ?- test_all_predicates. % Быстрое тестирование'), nl,
|
|
|
write(' ?- compare_recursions(10). % Сравнение рекурсий'), nl,
|
|
|
write(' ?- benchmark_recursions(15). % Измерение производительности'), nl, nl,
|
|
|
|
|
|
write('5. Демонстрационные программы:'), nl,
|
|
|
write(' ?- demo. % Полная демонстрация'), nl,
|
|
|
write(' ?- run_tests. % Запуск всех тестов'), nl, nl. |