|
|
% ===============================================
|
|
|
% ТЕСТЫ ДЛЯ LAB9 TASK1
|
|
|
% Автоматические тесты всех предикатов
|
|
|
% ===============================================
|
|
|
|
|
|
% Запуск всех тестов
|
|
|
run_tests :-
|
|
|
write('=== ЗАПУСК АВТОМАТИЧЕСКИХ ТЕСТОВ ==='), nl,
|
|
|
test_max,
|
|
|
test_factorial,
|
|
|
test_digit_sum,
|
|
|
test_square_free,
|
|
|
test_list_operations,
|
|
|
test_remove_by_digit_sum,
|
|
|
write('=== ВСЕ ТЕСТЫ ЗАВЕРШЕНЫ ==='), nl.
|
|
|
|
|
|
% ===============================================
|
|
|
% ТЕСТЫ ДЛЯ MAX/4
|
|
|
% ===============================================
|
|
|
test_max :-
|
|
|
write('--- Тестирование max/4 ---'), nl,
|
|
|
|
|
|
% Тест 1: обычные числа
|
|
|
(max(5, 3, 7, 7) ->
|
|
|
write('✓ max(5,3,7,7) - ПРОЙДЕН') ;
|
|
|
write('✗ max(5,3,7,7) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест 2: отрицательные числа
|
|
|
(max(-5, -3, -7, -3) ->
|
|
|
write('✓ max(-5,-3,-7,-3) - ПРОЙДЕН') ;
|
|
|
write('✗ max(-5,-3,-7,-3) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест 3: одинаковые числа
|
|
|
(max(5, 5, 5, 5) ->
|
|
|
write('✓ max(5,5,5,5) - ПРОЙДЕН') ;
|
|
|
write('✗ max(5,5,5,5) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест 4: генерация максимума
|
|
|
max(10, 20, 15, Z),
|
|
|
(Z =:= 20 ->
|
|
|
write('✓ max(10,20,15,Z) где Z=20 - ПРОЙДЕН') ;
|
|
|
write('✗ max(10,20,15,Z) - ПРОВАЛЕН')), nl,
|
|
|
nl.
|
|
|
|
|
|
% ===============================================
|
|
|
% ТЕСТЫ ДЛЯ ФАКТОРИАЛОВ
|
|
|
% ===============================================
|
|
|
test_factorial :-
|
|
|
write('--- Тестирование факториалов ---'), nl,
|
|
|
|
|
|
% Тест базового случая
|
|
|
(fact_up(0, 1) ->
|
|
|
write('✓ fact_up(0,1) - ПРОЙДЕН') ;
|
|
|
write('✗ fact_up(0,1) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
(fact_down(0, 1) ->
|
|
|
write('✓ fact_down(0,1) - ПРОЙДЕН') ;
|
|
|
write('✗ fact_down(0,1) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест небольших значений
|
|
|
TestValues = [1, 3, 5, 6],
|
|
|
forall(member(N, TestValues), test_factorial_value(N)),
|
|
|
|
|
|
% Тест эквивалентности рекурсий
|
|
|
test_factorial_equivalence([0, 1, 2, 3, 4, 5, 6, 7]),
|
|
|
nl.
|
|
|
|
|
|
test_factorial_value(N) :-
|
|
|
fact_up(N, F1),
|
|
|
fact_down(N, F2),
|
|
|
write('fact_up('), write(N), write(') = '), write(F1),
|
|
|
write(', fact_down('), write(N), write(') = '), write(F2),
|
|
|
(F1 =:= F2 -> write(' ✓') ; write(' ✗')), nl.
|
|
|
|
|
|
test_factorial_equivalence([]).
|
|
|
test_factorial_equivalence([N|Rest]) :-
|
|
|
fact_up(N, F1),
|
|
|
fact_down(N, F2),
|
|
|
(F1 =:= F2 ->
|
|
|
write('✓ Факториалы '), write(N), write(' эквивалентны') ;
|
|
|
write('✗ Факториалы '), write(N), write(' НЕ эквивалентны')), nl,
|
|
|
test_factorial_equivalence(Rest).
|
|
|
|
|
|
% ===============================================
|
|
|
% ТЕСТЫ ДЛЯ СУММЫ ЦИФР
|
|
|
% ===============================================
|
|
|
test_digit_sum :-
|
|
|
write('--- Тестирование суммы цифр ---'), nl,
|
|
|
|
|
|
% Тест базового случая
|
|
|
(digit_sum_up(0, 0) ->
|
|
|
write('✓ digit_sum_up(0,0) - ПРОЙДЕН') ;
|
|
|
write('✗ digit_sum_up(0,0) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
(digit_sum_down(0, 0) ->
|
|
|
write('✓ digit_sum_down(0,0) - ПРОЙДЕН') ;
|
|
|
write('✗ digit_sum_down(0,0) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест известных значений
|
|
|
TestCases = [(123, 6), (456, 15), (999, 27), (1000, 1), (12345, 15)],
|
|
|
forall(member((N, ExpectedSum), TestCases), test_digit_sum_value(N, ExpectedSum)),
|
|
|
|
|
|
% Тест эквивалентности рекурсий
|
|
|
test_digit_sum_equivalence([0, 1, 12, 123, 1234, 12345, 999, 1000]),
|
|
|
nl.
|
|
|
|
|
|
test_digit_sum_value(N, ExpectedSum) :-
|
|
|
digit_sum_up(N, S1),
|
|
|
digit_sum_down(N, S2),
|
|
|
write('digit_sum для '), write(N), write(': up='), write(S1), write(', down='), write(S2),
|
|
|
write(', ожидалось='), write(ExpectedSum),
|
|
|
((S1 =:= ExpectedSum, S2 =:= ExpectedSum) -> write(' ✓') ; write(' ✗')), nl.
|
|
|
|
|
|
test_digit_sum_equivalence([]).
|
|
|
test_digit_sum_equivalence([N|Rest]) :-
|
|
|
digit_sum_up(N, S1),
|
|
|
digit_sum_down(N, S2),
|
|
|
(S1 =:= S2 ->
|
|
|
write('✓ Суммы цифр '), write(N), write(' эквивалентны') ;
|
|
|
write('✗ Суммы цифр '), write(N), write(' НЕ эквивалентны')), nl,
|
|
|
test_digit_sum_equivalence(Rest).
|
|
|
|
|
|
% ===============================================
|
|
|
% ТЕСТЫ ДЛЯ SQUARE_FREE
|
|
|
% ===============================================
|
|
|
test_square_free :-
|
|
|
write('--- Тестирование square_free ---'), nl,
|
|
|
|
|
|
% Числа, свободные от квадратов
|
|
|
SquareFreeNumbers = [1, 2, 3, 5, 6, 7, 10, 11, 13, 14, 15],
|
|
|
forall(member(N, SquareFreeNumbers), test_square_free_positive(N)),
|
|
|
|
|
|
% Числа, НЕ свободные от квадратов
|
|
|
NonSquareFreeNumbers = [4, 8, 9, 12, 16, 18, 20, 24, 25, 27],
|
|
|
forall(member(N, NonSquareFreeNumbers), test_square_free_negative(N)),
|
|
|
nl.
|
|
|
|
|
|
test_square_free_positive(N) :-
|
|
|
(square_free(N) ->
|
|
|
write('✓ '), write(N), write(' корректно определено как свободное от квадратов') ;
|
|
|
write('✗ '), write(N), write(' ошибочно определено как НЕ свободное от квадратов')), nl.
|
|
|
|
|
|
test_square_free_negative(N) :-
|
|
|
(\+ square_free(N) ->
|
|
|
write('✓ '), write(N), write(' корректно определено как НЕ свободное от квадратов') ;
|
|
|
write('✗ '), write(N), write(' ошибочно определено как свободное от квадратов')), nl.
|
|
|
|
|
|
% ===============================================
|
|
|
% ТЕСТЫ ДЛЯ ОПЕРАЦИЙ СО СПИСКАМИ
|
|
|
% ===============================================
|
|
|
test_list_operations :-
|
|
|
write('--- Тестирование операций со списками ---'), nl,
|
|
|
|
|
|
% Тест пустого списка
|
|
|
(sum_list_down([], 0) ->
|
|
|
write('✓ sum_list_down([],0) - ПРОЙДЕН') ;
|
|
|
write('✗ sum_list_down([],0) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
(sum_list_up([], 0) ->
|
|
|
write('✓ sum_list_up([],0) - ПРОЙДЕН') ;
|
|
|
write('✗ sum_list_up([],0) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест одного элемента
|
|
|
(sum_list_down([5], 5) ->
|
|
|
write('✓ sum_list_down([5],5) - ПРОЙДЕН') ;
|
|
|
write('✗ sum_list_down([5],5) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
(sum_list_up([5], 5) ->
|
|
|
write('✓ sum_list_up([5],5) - ПРОЙДЕН') ;
|
|
|
write('✗ sum_list_up([5],5) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест различных списков
|
|
|
TestLists = [
|
|
|
([1, 2, 3], 6),
|
|
|
([10, 20, 30], 60),
|
|
|
([-1, 1, -2, 2], 0),
|
|
|
([0, 0, 0], 0),
|
|
|
([100], 100)
|
|
|
],
|
|
|
forall(member((List, ExpectedSum), TestLists), test_list_sum(List, ExpectedSum)),
|
|
|
|
|
|
% Тест эквивалентности рекурсий
|
|
|
test_list_sum_equivalence([
|
|
|
[],
|
|
|
[1],
|
|
|
[1, 2],
|
|
|
[1, 2, 3],
|
|
|
[1, 2, 3, 4, 5],
|
|
|
[-1, -2, -3],
|
|
|
[0, 0, 0, 0]
|
|
|
]),
|
|
|
nl.
|
|
|
|
|
|
test_list_sum(List, ExpectedSum) :-
|
|
|
sum_list_down(List, S1),
|
|
|
sum_list_up(List, S2),
|
|
|
write('Сумма '), write(List), write(': down='), write(S1), write(', up='), write(S2),
|
|
|
write(', ожидалось='), write(ExpectedSum),
|
|
|
((S1 =:= ExpectedSum, S2 =:= ExpectedSum) -> write(' ✓') ; write(' ✗')), nl.
|
|
|
|
|
|
test_list_sum_equivalence([]).
|
|
|
test_list_sum_equivalence([List|Rest]) :-
|
|
|
sum_list_down(List, S1),
|
|
|
sum_list_up(List, S2),
|
|
|
(S1 =:= S2 ->
|
|
|
write('✓ Суммы списка '), write(List), write(' эквивалентны') ;
|
|
|
write('✗ Суммы списка '), write(List), write(' НЕ эквивалентны')), nl,
|
|
|
test_list_sum_equivalence(Rest).
|
|
|
|
|
|
% ===============================================
|
|
|
% ТЕСТЫ ДЛЯ УДАЛЕНИЯ ПО СУММЕ ЦИФР
|
|
|
% ===============================================
|
|
|
test_remove_by_digit_sum :-
|
|
|
write('--- Тестирование remove_by_digit_sum ---'), nl,
|
|
|
|
|
|
% Тест пустого списка
|
|
|
(remove_by_digit_sum([], 5, []) ->
|
|
|
write('✓ remove_by_digit_sum([],5,[]) - ПРОЙДЕН') ;
|
|
|
write('✗ remove_by_digit_sum([],5,[]) - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест удаления всех элементов
|
|
|
remove_by_digit_sum([11, 20, 101, 110], 2, Result1),
|
|
|
(Result1 = [] ->
|
|
|
write('✓ Удаление всех элементов с суммой цифр 2 - ПРОЙДЕН') ;
|
|
|
write('✗ Удаление всех элементов с суммой цифр 2 - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест удаления части элементов
|
|
|
remove_by_digit_sum([12, 21, 34, 43, 50], 3, Result2),
|
|
|
Expected2 = [34, 43, 50],
|
|
|
(Result2 = Expected2 ->
|
|
|
write('✓ Частичное удаление элементов - ПРОЙДЕН') ;
|
|
|
write('✗ Частичное удаление элементов - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Тест с нецелыми элементами
|
|
|
remove_by_digit_sum([12, abc, 21, -5, 30], 3, Result3),
|
|
|
Expected3 = [abc, -5],
|
|
|
(Result3 = Expected3 ->
|
|
|
write('✓ Обработка нецелых элементов - ПРОЙДЕН') ;
|
|
|
write('✗ Обработка нецелых элементов - ПРОВАЛЕН')), nl,
|
|
|
|
|
|
% Дополнительные тесты
|
|
|
TestCases = [
|
|
|
(([123, 456, 789], 6), [456, 789]),
|
|
|
(([1, 11, 111, 1111], 1), [11, 111]),
|
|
|
(([0, 10, 100, 1000], 1), [0]),
|
|
|
(([999, 888, 777], 27), [888, 777])
|
|
|
],
|
|
|
forall(member(((List, TargetSum), Expected), TestCases),
|
|
|
test_remove_case(List, TargetSum, Expected)),
|
|
|
nl.
|
|
|
|
|
|
test_remove_case(List, TargetSum, Expected) :-
|
|
|
remove_by_digit_sum(List, TargetSum, Result),
|
|
|
write('remove_by_digit_sum('), write(List), write(', '), write(TargetSum), write(') = '),
|
|
|
write(Result), write(', ожидалось: '), write(Expected),
|
|
|
(Result = Expected -> write(' ✓') ; write(' ✗')), nl.
|
|
|
|
|
|
% ===============================================
|
|
|
% ДОПОЛНИТЕЛЬНЫЕ ТЕСТЫ
|
|
|
% ===============================================
|
|
|
|
|
|
% Тест производительности
|
|
|
performance_test :-
|
|
|
write('--- Тест производительности ---'), nl,
|
|
|
|
|
|
write('Тестирование факториала для больших чисел:'), nl,
|
|
|
TestNumbers = [10, 15, 20],
|
|
|
forall(member(N, TestNumbers), test_factorial_performance(N)),
|
|
|
|
|
|
write('Тестирование суммы цифр для больших чисел:'), nl,
|
|
|
BigNumbers = [12345, 123456, 1234567],
|
|
|
forall(member(N, BigNumbers), test_digit_sum_performance(N)),
|
|
|
nl.
|
|
|
|
|
|
test_factorial_performance(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,
|
|
|
|
|
|
write('Факториал '), write(N), write(': up='), write(TimeUp),
|
|
|
write('с, down='), write(TimeDown), write('с, результат='), write(F1),
|
|
|
(F1 =:= F2 -> write(' ✓') ; write(' ✗')), nl.
|
|
|
|
|
|
test_digit_sum_performance(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,
|
|
|
|
|
|
write('Сумма цифр '), write(N), write(': up='), write(TimeUp),
|
|
|
write('с, down='), write(TimeDown), write('с, результат='), write(S1),
|
|
|
(S1 =:= S2 -> write(' ✓') ; write(' ✗')), nl.
|
|
|
|
|
|
% Стресс-тест
|
|
|
stress_test :-
|
|
|
write('--- Стресс-тест ---'), nl,
|
|
|
|
|
|
write('Тестирование 100 случайных чисел для square_free:'), nl,
|
|
|
stress_test_square_free(100),
|
|
|
|
|
|
write('Тестирование 50 случайных списков для sum_list:'), nl,
|
|
|
stress_test_list_sum(50),
|
|
|
nl.
|
|
|
|
|
|
stress_test_square_free(0) :- !.
|
|
|
stress_test_square_free(N) :-
|
|
|
N > 0,
|
|
|
random(1, 100, TestNumber),
|
|
|
(square_free(TestNumber) -> Result = 'free' ; Result = 'not_free'),
|
|
|
(N mod 10 =:= 0 ->
|
|
|
(write('Тест '), write(N), write(': '), write(TestNumber), write(' - '), write(Result), nl)
|
|
|
; true),
|
|
|
N1 is N - 1,
|
|
|
stress_test_square_free(N1).
|
|
|
|
|
|
stress_test_list_sum(0) :- !.
|
|
|
stress_test_list_sum(N) :-
|
|
|
N > 0,
|
|
|
random(1, 10, ListLength),
|
|
|
generate_random_list(ListLength, TestList),
|
|
|
sum_list_down(TestList, S1),
|
|
|
sum_list_up(TestList, S2),
|
|
|
(N mod 10 =:= 0 ->
|
|
|
(write('Тест '), write(N), write(': '), write(TestList),
|
|
|
write(' - суммы равны: '), (S1 =:= S2 -> write('да') ; write('нет')), nl)
|
|
|
; true),
|
|
|
N1 is N - 1,
|
|
|
stress_test_list_sum(N1).
|
|
|
|
|
|
generate_random_list(0, []) :- !.
|
|
|
generate_random_list(N, [H|T]) :-
|
|
|
N > 0,
|
|
|
random(0, 100, H),
|
|
|
N1 is N - 1,
|
|
|
generate_random_list(N1, T). |