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.

376 lines
15 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 - ОСНОВНЫЕ ПРЕДИКАТЫ PROLOG
% Реализация математических и списочных предикатов
% ===============================================
% ===============================================
% 1. ПРЕДИКАТ MAX/4
% ===============================================
% max(+X, +Y, +U, -Z) - Z максимальное из чисел X, Y, U
max(X, Y, U, Z) :-
MaxXY is max(X, Y),
Z is max(MaxXY, U).
% ===============================================
% 2. ФАКТОРИАЛ (РЕКУРСИЯ ВВЕРХ И ВНИЗ)
% ===============================================
% fact_up(+N, -X) - факториал с помощью рекурсии вверх
fact_up(0, 1) :- !.
fact_up(N, X) :-
N > 0,
N1 is N - 1,
fact_up(N1, X1),
X is N * X1.
% fact_down(+N, -X) - факториал с помощью рекурсии вниз
fact_down(N, X) :-
fact_down_helper(N, 1, X).
fact_down_helper(0, Acc, Acc) :- !.
fact_down_helper(N, Acc, Result) :-
N > 0,
N1 is N - 1,
Acc1 is Acc * N,
fact_down_helper(N1, Acc1, Result).
% ===============================================
% 3. СУММА ЦИФР ЧИСЛА (РЕКУРСИЯ ВВЕРХ И ВНИЗ)
% ===============================================
% digit_sum_up(+N, -Sum) - сумма цифр числа с рекурсией вверх
digit_sum_up(0, 0) :- !.
digit_sum_up(N, Sum) :-
N > 0,
Digit is N mod 10,
N1 is N // 10,
digit_sum_up(N1, Sum1),
Sum is Digit + Sum1.
% digit_sum_down(+N, -Sum) - сумма цифр числа с рекурсией вниз
digit_sum_down(N, Sum) :-
digit_sum_down_helper(N, 0, Sum).
digit_sum_down_helper(0, Acc, Acc) :- !.
digit_sum_down_helper(N, Acc, Sum) :-
N > 0,
Digit is N mod 10,
N1 is N // 10,
Acc1 is Acc + Digit,
digit_sum_down_helper(N1, Acc1, Sum).
% ===============================================
% 4. ПРОВЕРКА НА СВОБОДНОСТЬ ОТ КВАДРАТОВ
% ===============================================
% square_free(+N) - проверяет, свободно ли число от квадратов
square_free(N) :-
N > 0,
square_free_helper(N, 2).
square_free_helper(1, _) :- !.
square_free_helper(N, Divisor) :-
Divisor * Divisor > N, !.
square_free_helper(N, Divisor) :-
Square is Divisor * Divisor,
Square =< N,
N mod Square =\= 0,
NextDivisor is Divisor + 1,
square_free_helper(N, NextDivisor).
% ===============================================
% 5. ВВОД И ВЫВОД СПИСКОВ
% ===============================================
% read_list(-List) - чтение списка с клавиатуры
read_list(List) :-
write('Введите элементы списка (завершите ввод атомом end):'), nl,
read_list_elements(List).
read_list_elements([]) :-
write('Введите элемент (или end для завершения): '),
read(end), !,
write('Ввод завершен.'), nl.
read_list_elements([H|T]) :-
write('Введите элемент (или end для завершения): '),
read(H),
H \= end, !,
read_list_elements(T).
% write_list(+List) - вывод списка на экран
write_list([]) :-
write('[]'), nl.
write_list(List) :-
List \= [],
write('['),
write_list_elements(List),
write(']'), nl.
write_list_elements([H]) :-
write(H), !.
write_list_elements([H|T]) :-
write(H),
write(', '),
write_list_elements(T).
% ===============================================
% 6. СУММА ЭЛЕМЕНТОВ СПИСКА (РЕКУРСИЯ ВНИЗ)
% ===============================================
% sum_list_down(+List, ?Sum) - сумма элементов списка (рекурсия вниз)
sum_list_down([], 0).
sum_list_down([H|T], Sum) :-
sum_list_down(T, TailSum),
Sum is H + TailSum.
% ===============================================
% 7. СУММА ЭЛЕМЕНТОВ СПИСКА (РЕКУРСИЯ ВВЕРХ)
% ===============================================
% sum_list_up(+List, ?Sum) - сумма элементов списка (рекурсия вверх)
sum_list_up(List, Sum) :-
sum_list_up_helper(List, 0, Sum).
sum_list_up_helper([], Acc, Acc).
sum_list_up_helper([H|T], Acc, Sum) :-
Acc1 is Acc + H,
sum_list_up_helper(T, Acc1, Sum).
% ===============================================
% 8. ПРОГРАММА РАБОТЫ СО СПИСКАМИ
% ===============================================
% list_sum_program - программа для работы со списками
list_sum_program :-
write('=== ПРОГРАММА ВЫЧИСЛЕНИЯ СУММЫ СПИСКА ==='), nl,
read_list(List),
write('Прочитанный список: '), write_list(List),
sum_list_down(List, Sum),
write('Сумма элементов списка: '), write(Sum), nl.
% ===============================================
% 9. УДАЛЕНИЕ ЭЛЕМЕНТОВ ПО СУММЕ ЦИФР
% ===============================================
% remove_by_digit_sum(+List, +TargetSum, -Result) - удаляет элементы с заданной суммой цифр
remove_by_digit_sum([], _, []).
remove_by_digit_sum([H|T], TargetSum, Result) :-
integer(H),
H >= 0,
digit_sum_up(H, DigitSum),
( DigitSum =:= TargetSum ->
remove_by_digit_sum(T, TargetSum, Result)
; Result = [H|TailResult],
remove_by_digit_sum(T, TargetSum, TailResult)
).
remove_by_digit_sum([H|T], TargetSum, [H|TailResult]) :-
(\+ integer(H) ; H < 0),
remove_by_digit_sum(T, TargetSum, TailResult).
% ===============================================
% ДЕМОНСТРАЦИОННЫЕ И ВСПОМОГАТЕЛЬНЫЕ ПРЕДИКАТЫ
% ===============================================
% task_info - информация о задании
task_info :-
write('РЕАЛИЗОВАННЫЕ ПРЕДИКАТЫ:'), nl,
write('1. max(X, Y, U, Z) - максимальное из трех чисел'), nl,
write('2. fact_up(N, X) - факториал (рекурсия вверх)'), nl,
write('3. fact_down(N, X) - факториал (рекурсия вниз)'), nl,
write('4. digit_sum_up(N, Sum) - сумма цифр (рекурсия вверх)'), nl,
write('5. digit_sum_down(N, Sum) - сумма цифр (рекурсия вниз)'), nl,
write('6. square_free(N) - проверка свободности от квадратов'), nl,
write('7. read_list(List) - чтение списка с клавиатуры'), nl,
write('8. write_list(List) - вывод списка на экран'), nl,
write('9. sum_list_down(List, Sum) - сумма списка (рекурсия вниз)'), nl,
write('10. sum_list_up(List, Sum) - сумма списка (рекурсия вверх)'), nl,
write('11. remove_by_digit_sum(List, TargetSum, Result) - удаление по сумме цифр'), nl,
write('12. list_sum_program - программа работы со списками'), nl.
% show_examples - показать примеры использования
show_examples :-
write('ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ:'), nl,
write('?- max(5, 3, 7, Z). % Z = 7'), nl,
write('?- fact_up(5, X). % X = 120'), nl,
write('?- fact_down(5, X). % X = 120'), nl,
write('?- digit_sum_up(123, Sum). % Sum = 6'), nl,
write('?- digit_sum_down(123, Sum). % Sum = 6'), nl,
write('?- square_free(12). % false (делится на 4)'), nl,
write('?- square_free(15). % true'), nl,
write('?- sum_list_down([1,2,3], S). % S = 6'), nl,
write('?- sum_list_up([1,2,3], S). % S = 6'), nl,
write('?- remove_by_digit_sum([12,21,34,43], 3, R). % R = [34,43]'), nl,
write('?- list_sum_program. % интерактивная программа'), nl.
% test_all_predicates - тестирование всех предикатов
test_all_predicates :-
write('=== ТЕСТИРОВАНИЕ ВСЕХ ПРЕДИКАТОВ ==='), nl,
% Тест max
write('Тест max: '),
max(5, 3, 7, Z1),
write('max(5,3,7) = '), write(Z1), nl,
% Тест факториалов
write('Тест факториалов: '),
fact_up(5, F1),
fact_down(5, F2),
write('fact_up(5) = '), write(F1), write(', fact_down(5) = '), write(F2), nl,
% Тест суммы цифр
write('Тест суммы цифр: '),
digit_sum_up(123, S1),
digit_sum_down(123, S2),
write('digit_sum_up(123) = '), write(S1), write(', digit_sum_down(123) = '), write(S2), nl,
% Тест square_free
write('Тест square_free: '),
(square_free(15) -> write('15 - свободно от квадратов') ; write('15 - не свободно от квадратов')), write(', '),
(square_free(12) -> write('12 - свободно от квадратов') ; write('12 - не свободно от квадратов')), nl,
% Тест сумм списков
write('Тест сумм списков: '),
sum_list_down([1,2,3,4], Sum1),
sum_list_up([1,2,3,4], Sum2),
write('sum_list_down([1,2,3,4]) = '), write(Sum1), write(', sum_list_up([1,2,3,4]) = '), write(Sum2), nl,
% Тест удаления по сумме цифр
write('Тест удаления по сумме цифр: '),
remove_by_digit_sum([12, 21, 34, 43, 105], 3, Filtered),
write('remove_by_digit_sum([12,21,34,43,105], 3) = '), write_list(Filtered),
write('=== ТЕСТИРОВАНИЕ ЗАВЕРШЕНО ==='), nl.
% compare_recursions(+N) - сравнение рекурсий для числа N
compare_recursions(N) :-
write('Сравнение рекурсий для числа '), write(N), write(':'), nl,
% Факториалы
fact_up(N, F1),
fact_down(N, F2),
write(' Факториал (вверх): '), write(F1), nl,
write(' Факториал (вниз): '), write(F2), nl,
write(' Факториалы равны: '), (F1 =:= F2 -> write('да') ; write('нет')), nl,
% Суммы цифр
digit_sum_up(N, S1),
digit_sum_down(N, S2),
write(' Сумма цифр (вверх): '), write(S1), nl,
write(' Сумма цифр (вниз): '), write(S2), nl,
write(' Суммы цифр равны: '), (S1 =:= S2 -> write('да') ; write('нет')), nl.
% interactive_demo - интерактивная демонстрация
interactive_demo :-
write('=== ИНТЕРАКТИВНАЯ ДЕМОНСТРАЦИЯ ==='), nl,
write('Выберите операцию:'), nl,
write('1. Тест max(X,Y,U,Z)'), nl,
write('2. Тест факториала'), nl,
write('3. Тест суммы цифр'), nl,
write('4. Тест свободности от квадратов'), nl,
write('5. Работа со списками'), nl,
write('6. Удаление по сумме цифр'), nl,
write('7. Выход'), nl,
write('Введите номер (1-7): '),
read(Choice),
handle_choice(Choice).
handle_choice(1) :-
write('Введите три числа X, Y, U: '),
read(X), read(Y), read(U),
max(X, Y, U, Z),
write('Максимальное из '), write(X), write(', '), write(Y), write(', '), write(U),
write(' = '), write(Z), nl,
interactive_demo.
handle_choice(2) :-
write('Введите число для вычисления факториала: '),
read(N),
( N >= 0 ->
fact_up(N, F1),
fact_down(N, F2),
write('Факториал '), write(N), write(' (рекурсия вверх) = '), write(F1), nl,
write('Факториал '), write(N), write(' (рекурсия вниз) = '), write(F2), nl
; write('Число должно быть неотрицательным!'), nl
),
interactive_demo.
handle_choice(3) :-
write('Введите число для вычисления суммы цифр: '),
read(N),
( N >= 0 ->
digit_sum_up(N, S1),
digit_sum_down(N, S2),
write('Сумма цифр '), write(N), write(' (рекурсия вверх) = '), write(S1), nl,
write('Сумма цифр '), write(N), write(' (рекурсия вниз) = '), write(S2), nl
; write('Число должно быть неотрицательным!'), nl
),
interactive_demo.
handle_choice(4) :-
write('Введите число для проверки свободности от квадратов: '),
read(N),
( N > 0 ->
( square_free(N) ->
write('Число '), write(N), write(' свободно от квадратов'), nl
; write('Число '), write(N), write(' НЕ свободно от квадратов'), nl
)
; write('Число должно быть положительным!'), nl
),
interactive_demo.
handle_choice(5) :-
list_sum_program,
interactive_demo.
handle_choice(6) :-
write('Введите список чисел [a,b,c,...]: '),
read(List),
write('Введите целевую сумму цифр: '),
read(TargetSum),
remove_by_digit_sum(List, TargetSum, Result),
write('Исходный список: '), write_list(List),
write('После удаления элементов с суммой цифр '), write(TargetSum), write(': '),
write_list(Result),
interactive_demo.
handle_choice(7) :-
write('До свидания!'), nl.
handle_choice(_) :-
write('Неверный выбор! Попробуйте снова.'), nl,
interactive_demo.
% benchmark_recursions(+N) - бенчмарк рекурсий
benchmark_recursions(N) :-
write('Бенчмарк рекурсий для N = '), write(N), write(':'), nl,
% Бенчмарк факториалов
get_time(T1),
fact_up(N, _),
get_time(T2),
fact_down(N, _),
get_time(T3),
TimeUp is T2 - T1,
TimeDown is T3 - T2,
write(' Факториал (рекурсия вверх): '), write(TimeUp), write(' сек'), nl,
write(' Факториал (рекурсия вниз): '), write(TimeDown), write(' сек'), nl,
% Бенчмарк сумм цифр
get_time(T4),
digit_sum_up(N, _),
get_time(T5),
digit_sum_down(N, _),
get_time(T6),
TimeSumUp is T5 - T4,
TimeSumDown is T6 - T5,
write(' Сумма цифр (рекурсия вверх): '), write(TimeSumUp), write(' сек'), nl,
write(' Сумма цифр (рекурсия вниз): '), write(TimeSumDown), write(' сек'), nl.