|
|
% ===============================================
|
|
|
% ДЕМОНСТРАЦИЯ LAB9 TASK2
|
|
|
% Полная демонстрация специальных предикатов
|
|
|
% ===============================================
|
|
|
|
|
|
% Главная демонстрация
|
|
|
demo :-
|
|
|
write('=== ДЕМОНСТРАЦИЯ LAB9 TASK2: СПЕЦИАЛЬНЫЕ ПРЕДИКАТЫ PROLOG ==='), nl, nl,
|
|
|
|
|
|
% 1. Демонстрация произведения цифр
|
|
|
write('1. ПРОИЗВЕДЕНИЕ ЦИФР ЧИСЛА'), nl,
|
|
|
write('==========================='), nl,
|
|
|
demo_digit_product,
|
|
|
nl,
|
|
|
|
|
|
% 2. Демонстрация максимальной цифры не делящейся на 3
|
|
|
write('2. МАКСИМАЛЬНАЯ ЦИФРА НЕ ДЕЛЯЩАЯСЯ НА 3'), nl,
|
|
|
write('======================================='), nl,
|
|
|
demo_max_digit_not_div3,
|
|
|
nl,
|
|
|
|
|
|
% 3. Демонстрация количества делителей
|
|
|
write('3. КОЛИЧЕСТВО ДЕЛИТЕЛЕЙ ЧИСЛА'), nl,
|
|
|
write('============================='), nl,
|
|
|
demo_divisor_count,
|
|
|
nl,
|
|
|
|
|
|
% 4. Сравнительный анализ рекурсий
|
|
|
write('4. СРАВНИТЕЛЬНЫЙ АНАЛИЗ РЕКУРСИЙ'), nl,
|
|
|
write('================================'), nl,
|
|
|
demo_recursion_comparison,
|
|
|
nl,
|
|
|
|
|
|
% 5. Анализ унификации переменных
|
|
|
write('5. АНАЛИЗ УНИФИКАЦИИ ПЕРЕМЕННЫХ'), nl,
|
|
|
write('==============================='), nl,
|
|
|
demo_unification_analysis,
|
|
|
nl,
|
|
|
|
|
|
% 6. Практические примеры
|
|
|
write('6. ПРАКТИЧЕСКИЕ ПРИМЕРЫ'), nl,
|
|
|
write('======================='), nl,
|
|
|
demo_practical_examples,
|
|
|
nl,
|
|
|
|
|
|
% 7. Производительность и оптимизация
|
|
|
write('7. ПРОИЗВОДИТЕЛЬНОСТЬ И ОПТИМИЗАЦИЯ'), nl,
|
|
|
write('==================================='), nl,
|
|
|
demo_performance_analysis,
|
|
|
nl,
|
|
|
|
|
|
write('=== ДЕМОНСТРАЦИЯ TASK2 ЗАВЕРШЕНА ==='), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация произведения цифр
|
|
|
% -----------------------------------------------
|
|
|
demo_digit_product :-
|
|
|
write('Предикаты digit_product_up/2 и digit_product_down/2 вычисляют'), nl,
|
|
|
write('произведение всех цифр числа.'), nl, nl,
|
|
|
|
|
|
write('ПРИНЦИП РАБОТЫ:'), nl,
|
|
|
write('- digit_product_up: рекурсия вверх, вычисления при возврате'), nl,
|
|
|
write('- digit_product_down: рекурсия вниз с аккумулятором'), nl, nl,
|
|
|
|
|
|
TestNumbers = [0, 1, 123, 456, 789, 102, 555, 12345],
|
|
|
|
|
|
write('Сравнение результатов:'), nl,
|
|
|
write('Число | Произведение (вверх) | Произведение (вниз) | Время (вверх) | Время (вниз)'), nl,
|
|
|
write('--------|----------------------|---------------------|---------------|-------------'), nl,
|
|
|
|
|
|
forall(member(N, TestNumbers), demo_digit_product_case(N)),
|
|
|
|
|
|
nl,
|
|
|
write('ОСОБЫЕ СЛУЧАИ:'), nl,
|
|
|
write('- Произведение цифр 0 = 1 (по определению)'), nl,
|
|
|
write('- Если число содержит 0, произведение = 0'), nl,
|
|
|
write('- Для однозначных чисел произведение = само число'), nl, nl,
|
|
|
|
|
|
write('ДЕМОНСТРАЦИЯ УНИФИКАЦИИ для digit_product_up(123, P):'), nl,
|
|
|
write('1. N=123 (унифицированная), P - неунифицированная'), nl,
|
|
|
write('2. Digit = 123 mod 10 = 3 (унифицируется)'), nl,
|
|
|
write('3. N1 = 123 // 10 = 12 (унифицируется)'), nl,
|
|
|
write('4. Рекурсивный вызов digit_product_up(12, SubProduct)'), nl,
|
|
|
write('5. SubProduct = 2 (унифицируется при возврате)'), nl,
|
|
|
write('6. P = 3 * 2 = 6 (унифицируется с результатом)'), nl.
|
|
|
|
|
|
demo_digit_product_case(N) :-
|
|
|
get_time(T1),
|
|
|
digit_product_up(N, P1),
|
|
|
get_time(T2),
|
|
|
digit_product_down(N, P2),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeUp is T2 - T1,
|
|
|
TimeDown is T3 - T2,
|
|
|
|
|
|
format('~w~7| | ~w~19| | ~w~18| | ~6f~9| | ~6f~n', [N, P1, P2, TimeUp, TimeDown]).
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация максимальной цифры не делящейся на 3
|
|
|
% -----------------------------------------------
|
|
|
demo_max_digit_not_div3 :-
|
|
|
write('Предикаты max_digit_not_div3_up/2 и max_digit_not_div3_down/2'), nl,
|
|
|
write('находят максимальную цифру числа, которая не делится на 3.'), nl, nl,
|
|
|
|
|
|
write('ПРИНЦИП РАБОТЫ:'), nl,
|
|
|
write('- Проверяем каждую цифру на деление на 3'), nl,
|
|
|
write('- Среди не делящихся на 3 находим максимальную'), nl,
|
|
|
write('- Если все цифры делятся на 3, возвращаем -1'), nl, nl,
|
|
|
|
|
|
TestNumbers = [0, 123, 456, 789, 369, 147, 98765, 36960, 12457],
|
|
|
|
|
|
write('Анализ цифр по числам:'), nl,
|
|
|
write('Число | Цифры | Не дел. на 3 | Максимум (вверх) | Максимум (вниз)'), nl,
|
|
|
write('--------|------------|--------------|------------------|----------------'), nl,
|
|
|
|
|
|
forall(member(N, TestNumbers), demo_max_digit_case(N)),
|
|
|
|
|
|
nl,
|
|
|
write('ОБЪЯСНЕНИЕ РЕЗУЛЬТАТОВ:'), nl,
|
|
|
write('- 123: цифры [1,2,3], не дел. на 3: [1,2] → макс: 2'), nl,
|
|
|
write('- 369: цифры [3,6,9], все делятся на 3 → результат: -1'), nl,
|
|
|
write('- 147: цифры [1,4,7], не дел. на 3: [1,4,7] → макс: 7'), nl, nl,
|
|
|
|
|
|
write('ДЕМОНСТРАЦИЯ УНИФИКАЦИИ для max_digit_not_div3_up(147, M):'), nl,
|
|
|
write('1. N=147 (унифицированная), M - неунифицированная'), nl,
|
|
|
write('2. Digit = 147 mod 10 = 7 (унифицируется)'), nl,
|
|
|
write('3. N1 = 147 // 10 = 14 (унифицируется)'), nl,
|
|
|
write('4. Рекурсивный вызов max_digit_not_div3_up(14, SubMax)'), nl,
|
|
|
write('5. SubMax = 4 (унифицируется при возврате)'), nl,
|
|
|
write('6. combine_max_not_div3(7, 4, M): 7 не дел. на 3, M = max(7,4) = 7'), nl.
|
|
|
|
|
|
demo_max_digit_case(N) :-
|
|
|
% Получаем список цифр
|
|
|
number_digits(N, Digits),
|
|
|
% Фильтруем не делящиеся на 3
|
|
|
include(not_divisible_by_3, Digits, NotDiv3),
|
|
|
|
|
|
max_digit_not_div3_up(N, M1),
|
|
|
max_digit_not_div3_down(N, M2),
|
|
|
|
|
|
format('~w~7| | ~w~9| | ~w~11| | ~w~15| | ~w~n', [N, Digits, NotDiv3, M1, M2]).
|
|
|
|
|
|
% Вспомогательные предикаты для демонстрации
|
|
|
number_digits(0, [0]) :- !.
|
|
|
number_digits(N, Digits) :-
|
|
|
N > 0,
|
|
|
number_digits_helper(N, [], Digits).
|
|
|
|
|
|
number_digits_helper(0, Acc, Acc) :- !.
|
|
|
number_digits_helper(N, Acc, Digits) :-
|
|
|
N > 0,
|
|
|
Digit is N mod 10,
|
|
|
N1 is N // 10,
|
|
|
number_digits_helper(N1, [Digit|Acc], Digits).
|
|
|
|
|
|
not_divisible_by_3(Digit) :-
|
|
|
Digit mod 3 =\= 0.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Демонстрация количества делителей
|
|
|
% -----------------------------------------------
|
|
|
demo_divisor_count :-
|
|
|
write('Предикаты для подсчета количества делителей числа:'), nl,
|
|
|
write('- divisor_count_up/2: рекурсия вверх'), nl,
|
|
|
write('- divisor_count_down/2: рекурсия вниз с аккумулятором'), nl,
|
|
|
write('- divisor_count_optimized/2: оптимизированный алгоритм'), nl, nl,
|
|
|
|
|
|
write('ПРИНЦИП ОПТИМИЗАЦИИ:'), nl,
|
|
|
write('- Обычный алгоритм: проверяем все числа от 1 до N'), nl,
|
|
|
write('- Оптимизированный: проверяем только до sqrt(N)'), nl,
|
|
|
write('- Для каждого делителя d находим пару N/d'), nl,
|
|
|
write('- Если d = sqrt(N), добавляем только один раз'), nl, nl,
|
|
|
|
|
|
TestNumbers = [1, 6, 12, 24, 36, 100, 144, 1000],
|
|
|
|
|
|
write('Сравнение методов:'), nl,
|
|
|
write('Число | Делители | Кол-во | Время (up) | Время (down) | Время (opt)'), nl,
|
|
|
write('------|-------------------------------|--------|------------|--------------|------------'), nl,
|
|
|
|
|
|
forall(member(N, TestNumbers), demo_divisor_case(N)),
|
|
|
|
|
|
nl,
|
|
|
write('АНАЛИЗ СЛОЖНОСТИ:'), nl,
|
|
|
write('- Обычный алгоритм: O(N) - проверяем все числа до N'), nl,
|
|
|
write('- Оптимизированный: O(sqrt(N)) - проверяем только до sqrt(N)'), nl,
|
|
|
write('- Для N=10000: обычный ~10000 операций, оптим. ~100 операций'), nl, nl,
|
|
|
|
|
|
write('ДЕМОНСТРАЦИЯ УНИФИКАЦИИ для divisor_count_down(12, C):'), nl,
|
|
|
write('1. N=12 (унифицированная), C - неунифицированная'), nl,
|
|
|
write('2. Вызов helper(12, 1, 0, C)'), nl,
|
|
|
write('3. Current=1, Acc=0: 12 mod 1 = 0 → Acc1 = 1'), nl,
|
|
|
write('4. Current=2, Acc=1: 12 mod 2 = 0 → Acc1 = 2'), nl,
|
|
|
write('5. Current=3, Acc=2: 12 mod 3 = 0 → Acc1 = 3'), nl,
|
|
|
write('6. Current=4, Acc=3: 12 mod 4 = 0 → Acc1 = 4'), nl,
|
|
|
write('7. Current=5, Acc=4: 12 mod 5 ≠ 0 → Acc1 = 4'), nl,
|
|
|
write('8. Current=6, Acc=4: 12 mod 6 = 0 → Acc1 = 5'), nl,
|
|
|
write('9. Current=7..11: не делители → Acc1 = 5'), nl,
|
|
|
write('10. Current=12, Acc=5: 12 mod 12 = 0 → Acc1 = 6'), nl,
|
|
|
write('11. Current=13 > 12 → C унифицируется с 6'), nl.
|
|
|
|
|
|
demo_divisor_case(N) :-
|
|
|
% Находим все делители для отображения
|
|
|
findall(D, (between(1, N, D), N mod D =:= 0), Divisors),
|
|
|
|
|
|
get_time(T1),
|
|
|
divisor_count_up(N, C1),
|
|
|
get_time(T2),
|
|
|
divisor_count_down(N, C2),
|
|
|
get_time(T3),
|
|
|
divisor_count_optimized(N, C3),
|
|
|
get_time(T4),
|
|
|
|
|
|
TimeUp is T2 - T1,
|
|
|
TimeDown is T3 - T2,
|
|
|
TimeOpt is T4 - T3,
|
|
|
|
|
|
format('~w~5| | ~w~28| | ~w~6| | ~6f~4| | ~6f~6| | ~6f~n',
|
|
|
[N, Divisors, C1, TimeUp, TimeDown, TimeOpt]).
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Сравнительный анализ рекурсий
|
|
|
% -----------------------------------------------
|
|
|
demo_recursion_comparison :-
|
|
|
write('Сравнение эффективности рекурсии вверх и вниз:'), nl, nl,
|
|
|
|
|
|
write('ТЕОРЕТИЧЕСКИЕ РАЗЛИЧИЯ:'), nl,
|
|
|
write('┌─────────────────┬──────────────────────┬────────────────────────┐'), nl,
|
|
|
write('│ Характеристика │ Рекурсия вверх │ Рекурсия вниз │'), nl,
|
|
|
write('├─────────────────┼──────────────────────┼────────────────────────┤'), nl,
|
|
|
write('│ Стек вызовов │ Растет с глубиной │ Оптимизируется │'), nl,
|
|
|
write('│ Вычисления │ При возврате │ При погружении │'), nl,
|
|
|
write('│ Память │ O(глубина) │ O(1) для хвост. рек. │'), nl,
|
|
|
write('│ Понимание │ Интуитивно │ Требует практики │'), nl,
|
|
|
write('│ Оптимизация │ Ограничена │ Компилятор может помочь│'), nl,
|
|
|
write('└─────────────────┴──────────────────────┴────────────────────────┘'), nl, nl,
|
|
|
|
|
|
write('ПРАКТИЧЕСКОЕ СРАВНЕНИЕ:'), nl,
|
|
|
TestNumbers = [12345, 987654, 1234567],
|
|
|
forall(member(N, TestNumbers), demo_recursion_performance(N)),
|
|
|
|
|
|
nl,
|
|
|
write('ВЫВОДЫ:'), nl,
|
|
|
write('1. Для небольших чисел разница незначительна'), nl,
|
|
|
write('2. Для больших чисел рекурсия вниз может быть эффективнее'), nl,
|
|
|
write('3. Рекурсия вниз безопаснее при глубокой рекурсии'), nl,
|
|
|
write('4. Оптимизированные алгоритмы дают наибольшее ускорение'), nl.
|
|
|
|
|
|
demo_recursion_performance(N) :-
|
|
|
write('Тестирование для N = '), write(N), write(':'), nl,
|
|
|
|
|
|
% Произведение цифр
|
|
|
get_time(T1),
|
|
|
digit_product_up(N, P1),
|
|
|
get_time(T2),
|
|
|
digit_product_down(N, P2),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeProductUp is T2 - T1,
|
|
|
TimeProductDown is T3 - T2,
|
|
|
|
|
|
write(' Произведение цифр: рекурсия вверх = '), write(TimeProductUp), write('с, '),
|
|
|
write('рекурсия вниз = '), write(TimeProductDown), write('с'), nl,
|
|
|
|
|
|
% Максимальная цифра
|
|
|
get_time(T4),
|
|
|
max_digit_not_div3_up(N, M1),
|
|
|
get_time(T5),
|
|
|
max_digit_not_div3_down(N, M2),
|
|
|
get_time(T6),
|
|
|
|
|
|
TimeMaxUp is T5 - T4,
|
|
|
TimeMaxDown is T6 - T5,
|
|
|
|
|
|
write(' Макс. цифра: рекурсия вверх = '), write(TimeMaxUp), write('с, '),
|
|
|
write('рекурсия вниз = '), write(TimeMaxDown), write('с'), nl, nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Анализ унификации переменных
|
|
|
% -----------------------------------------------
|
|
|
demo_unification_analysis :-
|
|
|
write('АНАЛИЗ УНИФИКАЦИИ В ПРЕДИКАТАХ:'), nl, nl,
|
|
|
|
|
|
write('1. ТИПЫ ПЕРЕМЕННЫХ В PROLOG:'), nl,
|
|
|
write(' • Унифицированные (+): уже имеют значение при вызове'), nl,
|
|
|
write(' • Неунифицированные (-): получают значение в процессе выполнения'), nl,
|
|
|
write(' • Переменные режима (?): могут быть и теми, и другими'), nl, nl,
|
|
|
|
|
|
write('2. ПРИМЕРЫ УНИФИКАЦИИ В НАШИХ ПРЕДИКАТАХ:'), nl, nl,
|
|
|
|
|
|
% Пример 1: digit_product_up
|
|
|
write('ПРИМЕР 1: digit_product_up(+N, -Product)'), nl,
|
|
|
write('Вызов: digit_product_up(123, P)'), nl,
|
|
|
write('• N = 123 (унифицированная при вызове)'), nl,
|
|
|
write('• Product = неунифицированная переменная'), nl,
|
|
|
write('• Digit is N mod 10 → Digit унифицируется с 3'), nl,
|
|
|
write('• N1 is N // 10 → N1 унифицируется с 12'), nl,
|
|
|
write('• При возврате из рекурсии SubProduct унифицируется с 2'), nl,
|
|
|
write('• Product is 3 * 2 → Product унифицируется с 6'), nl, nl,
|
|
|
|
|
|
% Пример 2: max_digit_not_div3_down
|
|
|
write('ПРИМЕР 2: max_digit_not_div3_down(+N, -MaxDigit)'), nl,
|
|
|
write('Вызов: max_digit_not_div3_down(147, M)'), nl,
|
|
|
write('• N = 147, M = неунифицированная'), nl,
|
|
|
write('• Вызов helper(147, -1, M) → CurrentMax = -1 (унифицированная)'), nl,
|
|
|
write('• Digit = 7, update_max_not_div3(7, -1, NewMax)'), nl,
|
|
|
write('• 7 mod 3 ≠ 0, CurrentMax = -1 → NewMax унифицируется с 7'), nl,
|
|
|
write('• Процесс продолжается с NewMax = 7 (теперь унифицированная)'), nl, nl,
|
|
|
|
|
|
% Пример 3: divisor_count_optimized
|
|
|
write('ПРИМЕР 3: divisor_count_optimized(+N, -Count)'), nl,
|
|
|
write('Вызов: divisor_count_optimized(16, C)'), nl,
|
|
|
write('• N = 16, C = неунифицированная'), nl,
|
|
|
write('• Sqrt is floor(sqrt(16)) → Sqrt унифицируется с 4'), nl,
|
|
|
write('• Current = 1: 16 mod 1 = 0, Current ≠ sqrt(16) → Acc1 = 0 + 2 = 2'), nl,
|
|
|
write('• Current = 2: 16 mod 2 = 0, Current ≠ sqrt(16) → Acc1 = 2 + 2 = 4'), nl,
|
|
|
write('• Current = 4: 16 mod 4 = 0, Current = sqrt(16) → Acc1 = 4 + 1 = 5'), nl,
|
|
|
write('• Current = 5 > Sqrt → C унифицируется с 5'), nl, nl,
|
|
|
|
|
|
write('3. ВАЖНЫЕ ОСОБЕННОСТИ УНИФИКАЦИИ:'), nl,
|
|
|
write(' • Унификация происходит один раз и необратима'), nl,
|
|
|
write(' • Переменная может унифицироваться только с одним значением'), nl,
|
|
|
write(' • В рекурсии каждый вызов создает новую область видимости'), nl,
|
|
|
write(' • Аккумуляторы передают состояние между вызовами'), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Практические примеры
|
|
|
% -----------------------------------------------
|
|
|
demo_practical_examples :-
|
|
|
write('ПРАКТИЧЕСКИЕ ПРИМЕНЕНИЯ ПРЕДИКАТОВ:'), nl, nl,
|
|
|
|
|
|
write('СЦЕНАРИЙ 1: Криптографический анализ'), nl,
|
|
|
write('─────────────────────────────────────'), nl,
|
|
|
demo_crypto_analysis,
|
|
|
nl,
|
|
|
|
|
|
write('СЦЕНАРИЙ 2: Числовая теория'), nl,
|
|
|
write('───────────────────────────'), nl,
|
|
|
demo_number_theory,
|
|
|
nl,
|
|
|
|
|
|
write('СЦЕНАРИЙ 3: Анализ данных'), nl,
|
|
|
write('─────────────────────────'), nl,
|
|
|
demo_data_analysis,
|
|
|
nl.
|
|
|
|
|
|
demo_crypto_analysis :-
|
|
|
Numbers = [1234, 5678, 9876],
|
|
|
write('Анализ чисел для криптографических свойств:'), nl,
|
|
|
forall(member(N, Numbers), demo_crypto_number(N)).
|
|
|
|
|
|
demo_crypto_number(N) :-
|
|
|
digit_product_up(N, Product),
|
|
|
max_digit_not_div3_up(N, MaxDigit),
|
|
|
divisor_count_optimized(N, DivCount),
|
|
|
|
|
|
write('Число '), write(N), write(':'), nl,
|
|
|
write(' Произведение цифр: '), write(Product),
|
|
|
(Product =:= 0 -> write(' (содержит 0 - слабо)') ; write(' (без нулей - лучше)')), nl,
|
|
|
write(' Макс. цифра не дел. на 3: '), write(MaxDigit),
|
|
|
(MaxDigit =:= -1 -> write(' (все дел. на 3 - предсказуемо)') ; write(' (есть разнообразие)')), nl,
|
|
|
write(' Количество делителей: '), write(DivCount),
|
|
|
(DivCount =:= 2 -> write(' (простое - хорошо для криптографии)') ; write(' (составное)')), nl.
|
|
|
|
|
|
demo_number_theory :-
|
|
|
write('Исследование числовых свойств:'), nl,
|
|
|
|
|
|
% Поиск чисел с интересными свойствами
|
|
|
write('Поиск чисел от 1 до 100 с особыми свойствами:'), nl,
|
|
|
|
|
|
% Числа, где произведение цифр равно количеству делителей
|
|
|
findall(N, (between(1, 100, N),
|
|
|
digit_product_up(N, P),
|
|
|
divisor_count_optimized(N, D),
|
|
|
P =:= D), SpecialNumbers),
|
|
|
write('Числа, где произведение цифр = количеству делителей: '), write(SpecialNumbers), nl,
|
|
|
|
|
|
% Числа без цифр, делящихся на 3, но само число делится на 3
|
|
|
findall(N, (between(10, 100, N),
|
|
|
N mod 3 =:= 0,
|
|
|
max_digit_not_div3_up(N, M),
|
|
|
M =\= -1), ParadoxNumbers),
|
|
|
write('Числа дел. на 3, но есть цифры не дел. на 3: '), write(ParadoxNumbers), nl.
|
|
|
|
|
|
demo_data_analysis :-
|
|
|
write('Анализ последовательности чисел:'), nl,
|
|
|
|
|
|
Sequence = [123, 234, 345, 456, 567, 678, 789],
|
|
|
write('Последовательность: '), write(Sequence), nl,
|
|
|
|
|
|
% Анализ произведений цифр
|
|
|
findall(P, (member(N, Sequence), digit_product_up(N, P)), Products),
|
|
|
sum_list(Products, TotalProduct),
|
|
|
length(Products, Len),
|
|
|
AvgProduct is TotalProduct / Len,
|
|
|
write('Произведения цифр: '), write(Products), nl,
|
|
|
write('Среднее произведение: '), write(AvgProduct), nl,
|
|
|
|
|
|
% Анализ максимальных цифр
|
|
|
findall(M, (member(N, Sequence), max_digit_not_div3_up(N, M)), MaxDigits),
|
|
|
write('Макс. цифры не дел. на 3: '), write(MaxDigits), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Производительность и оптимизация
|
|
|
% -----------------------------------------------
|
|
|
demo_performance_analysis :-
|
|
|
write('АНАЛИЗ ПРОИЗВОДИТЕЛЬНОСТИ И ОПТИМИЗАЦИИ:'), nl, nl,
|
|
|
|
|
|
write('1. СРАВНЕНИЕ АЛГОРИТМОВ ПОДСЧЕТА ДЕЛИТЕЛЕЙ:'), nl,
|
|
|
write(' Тестирование на различных размерах чисел'), nl, nl,
|
|
|
|
|
|
TestSizes = [100, 1000, 10000],
|
|
|
forall(member(Size, TestSizes), demo_divisor_scaling(Size)),
|
|
|
|
|
|
nl,
|
|
|
write('2. ВЛИЯНИЕ ДЛИНЫ ЧИСЛА НА ЦИФРОВЫЕ ОПЕРАЦИИ:'), nl,
|
|
|
LengthTests = [12, 1234, 123456, 12345678],
|
|
|
forall(member(N, LengthTests), demo_length_impact(N)),
|
|
|
|
|
|
nl,
|
|
|
write('3. ОПТИМИЗАЦИЯ И РЕКОМЕНДАЦИИ:'), nl,
|
|
|
write(' • Для подсчета делителей всегда используйте оптимизированную версию'), nl,
|
|
|
write(' • Рекурсия вниз предпочтительна для глубокой рекурсии'), nl,
|
|
|
write(' • Для цифровых операций длина числа влияет линейно'), nl,
|
|
|
write(' • Кэширование результатов может ускорить повторные вычисления'), nl.
|
|
|
|
|
|
demo_divisor_scaling(N) :-
|
|
|
get_time(T1),
|
|
|
divisor_count_down(N, C1),
|
|
|
get_time(T2),
|
|
|
divisor_count_optimized(N, C2),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeNormal is T2 - T1,
|
|
|
TimeOpt is T3 - T2,
|
|
|
SpeedUp is TimeNormal / TimeOpt,
|
|
|
|
|
|
write('N='), write(N), write(': обычный='), write(TimeNormal),
|
|
|
write('с, оптим.='), write(TimeOpt), write('с, ускорение='), write(SpeedUp), write('x'), nl.
|
|
|
|
|
|
demo_length_impact(N) :-
|
|
|
atom_chars(N, Chars),
|
|
|
length(Chars, Length),
|
|
|
|
|
|
get_time(T1),
|
|
|
digit_product_down(N, _),
|
|
|
get_time(T2),
|
|
|
max_digit_not_div3_down(N, _),
|
|
|
get_time(T3),
|
|
|
|
|
|
TimeProduct is T2 - T1,
|
|
|
TimeMaxDigit is T3 - T2,
|
|
|
|
|
|
write('Длина='), write(Length), write(', произведение='), write(TimeProduct),
|
|
|
write('с, макс.цифра='), write(TimeMaxDigit), write('с'), nl.
|
|
|
|
|
|
% -----------------------------------------------
|
|
|
% Интерактивные примеры
|
|
|
% -----------------------------------------------
|
|
|
demo_interactive_examples :-
|
|
|
write('=== ИНТЕРАКТИВНЫЕ ПРИМЕРЫ TASK2 ==='), nl,
|
|
|
write('Вы можете попробовать следующие запросы в интерактивной сессии:'), nl, nl,
|
|
|
|
|
|
write('1. Произведение цифр:'), nl,
|
|
|
write(' ?- digit_product_up(123, P). % P = 6'), nl,
|
|
|
write(' ?- digit_product_down(456, P). % P = 120'), nl,
|
|
|
write(' ?- digit_product_up(102, P). % P = 0 (содержит 0)'), nl, nl,
|
|
|
|
|
|
write('2. Максимальная цифра не делящаяся на 3:'), nl,
|
|
|
write(' ?- max_digit_not_div3_up(123, M). % M = 2'), nl,
|
|
|
write(' ?- max_digit_not_div3_down(369, M). % M = -1 (все дел. на 3)'), nl,
|
|
|
write(' ?- max_digit_not_div3_up(147, M). % M = 7'), nl, nl,
|
|
|
|
|
|
write('3. Количество делителей:'), nl,
|
|
|
write(' ?- divisor_count_up(12, C). % C = 6'), nl,
|
|
|
write(' ?- divisor_count_down(16, C). % C = 5'), nl,
|
|
|
write(' ?- divisor_count_optimized(100, C). % C = 9'), nl, nl,
|
|
|
|
|
|
write('4. Сравнение и анализ:'), nl,
|
|
|
write(' ?- compare_recursions(12345). % Сравнение всех методов'), nl,
|
|
|
write(' ?- benchmark_predicates(98765). % Измерение производительности'), nl,
|
|
|
write(' ?- interactive_demo. % Интерактивное меню'), nl, nl,
|
|
|
|
|
|
write('5. Проверка эквивалентности:'), nl,
|
|
|
write(' ?- digit_product_up(X, 24), digit_product_down(X, 24). % Поиск чисел'), nl,
|
|
|
write(' ?- max_digit_not_div3_up(X, 8), X > 0, X < 1000. % Числа с макс. цифрой 8'), nl, nl. |