You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
19 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

% ===============================================
% ДЕМОНСТРАЦИЯ 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.