
Лаб. 6 ФЛП
.docxЛабораторная работа 6
%1
% База данных родственных связей
отец(иван, лиза).
отец(иван, марк).
мать(анна, лиза).
мать(анна, марк).
мать(лиза, виктор).
% Родитель — это либо отец, либо мать
родитель(X, Y) :- отец(X, Y).
родитель(X, Y) :- мать(X, Y).
% Предок — это родитель или предок родителя
предок_потомок(X, Y) :- родитель(X, Y).
предок_потомок(X, Y) :- родитель(X, Z), предок_потомок(Z, Y).
%предок_потомок(лиза, X)
% База данных списков
список([1, 2, 3, 4]).
список([apple, banana, orange, mango]).
список([x, y, z, a]).
% Основной предикат: ищем список, в котором последний элемент = Last
my_last2(X, Last) :-
список(X), % Берём список из базы
last(X, Last). % Проверяем его последний элемент
% last/2 — находит последний элемент списка
last([X], X). % База: если в списке один элемент, он и есть последний
last([_ | T], X) :- last(T, X). % Рекурсивный случай: идём дальше по списку
%my_last2(X, a)
%my_last2(X, 2)
Дерево вызовов для предок_потомок(лиза, X):
предок_потомок(X, Y) :- родитель(X, Y).
родитель(X, Y) :- отец(X, Y).
родитель(X, Y) :- мать(X, Y).
предок_потомок(X, Y) :- родитель(X, Z), предок_потомок(Z, Y).
родитель(X, Y) :- отец(X, Y).
родитель(X, Y) :- мать(X, Y).
Дерево вызовов для my_last2(X, a):
my_last2(X, Last)
last([_ | T], X) вызовется 11 раз
last([X], X)
:- begin_tests(predok_potomok).
test(ivan_is_ancestor_of_liza) :-
предок_потомок(иван, лиза).
test(ivan_is_ancestor_of_viktor) :-
предок_потомок(иван, виктор).
test(anna_is_ancestor_of_viktor) :-
предок_потомок(анна, виктор).
test(liza_is_ancestor_of_viktor) :-
предок_потомок(лиза, виктор).
test(marc_is_not_ancestor_of_viktor, fail) :-
предок_потомок(марк, виктор).
test(viktor_is_not_ancestor_of_ivan, fail) :-
предок_потомок(виктор, иван).
:- end_tests(predok_potomok).
:- begin_tests(my_last2).
test(last_element_4) :-
my_last2([1, 2, 3, 4], 4).
test(last_element_mango) :-
my_last2([apple, banana, orange, mango], mango).
test(last_element_a) :-
my_last2([x, y, z, a], a).
test(find_list_with_last_a) :-
my_last2([x, y, z, a], a). % Здесь X не используется, так что избавляемся от неё
test(find_list_with_last_2, fail) :-
my_last2([1, 2, 3, 4], 2). % Здесь тоже X не используется
test(find_list_with_last_pizza, fail) :-
my_last2([x, y, z, a], pizza). % Нет такого элемента в списке
:- end_tests(my_last2).
%2
zip([], [], []). % Пустые списки дают пустой результат.
zip([H1|T1], [H2|T2], [[H1, H2]|ZippedTail]) :-
zip(T1, T2, ZippedTail). % Рекурсивно объединяем оставшиеся элементы.
%zip([a,b,c], [1,2,3], X)
%zip(X, [1,2,3], [[a,1], [b,2], [c,3]])
%zip([a,b,c], X, [[a,1], [b,2], [c,3]])
%zip(X, Y, [[a,1], [b,2], [c,3]])
%zip([a, b], [1, 2, 3], X)
:- begin_tests(zip).
test(zip_normal_case) :-
zip([a, b, c], [1, 2, 3], X),
X == [[a,1], [b,2], [c,3]].
test(zip_empty_lists) :-
zip([], [], X),
X == [].
test(zip_first_argument_var) :-
zip(X, [1, 2, 3], [[a,1], [b,2], [c,3]]),
X == [a, b, c].
test(zip_second_argument_var) :-
zip([a, b, c], X, [[a,1], [b,2], [c,3]]),
X == [1, 2, 3].
test(zip_both_arguments_vars) :-
zip(X, Y, [[a,1], [b,2], [c,3]]),
X == [a, b, c],
Y == [1, 2, 3].
test(zip_unequal_length, fail) :-
zip([a, b], [1, 2, 3], _).
test(zip_partial_match, fail) :-
zip([a, b, c], [1, 2], _).
:- end_tests(zip).
%3
% Предикат успешен, если в списке есть повторяющиеся элементы.
contains_duplicates(List) :-
append(_, [X | Tail], List), % Разделяем список, начиная с элемента X
member(X, Tail). % Проверяем, есть ли X в оставшейся части списка
%contains_duplicates([a, b, a, b, c, c, a])
%contains_duplicates([a, b, c])
%contains_duplicates([X, Y, X])
%contains_duplicates([X, Y, Z])
:- begin_tests(contains_duplicates).
test(duplicates_present) :-
contains_duplicates([a, b, a, b, c, c, a]).
test(no_duplicates, fail) :-
contains_duplicates([a, b, c]).
test(empty_list, fail) :-
contains_duplicates([]).
test(single_element_list, fail) :-
contains_duplicates([a]).
test(two_same_elements) :-
contains_duplicates([x, x]).
:- end_tests(contains_duplicates).
%4
% Базовый случай: пустой список расплющивается в пустой список
my_flatten([], []).
% Если голова списка — это список, рекурсивно обрабатываем его и объединяем с остальным
my_flatten([H | T], Flattened) :-
my_flatten(H, FlatHead), % Расплющиваем голову
my_flatten(T, FlatTail), % Расплющиваем хвост
append(FlatHead, FlatTail, Flattened). % Объединяем результат
% Если голова списка — не список, просто добавляем её к результату
my_flatten(X, [X]) :-
X \= [],
X \= [_|_].
%my_flatten([a, [[b], c], [[d]]], X)
%my_flatten([[1, [2, 3]], [4, [5]], 6], X)
%my_flatten([], X)
:- begin_tests(my_flatten).
% Тест для простого случая: уже плоский список
test(flatten_simple) :-
my_flatten([a, b, c], X),
X == [a, b, c].
% Тест для вложенных списков
test(flatten_nested) :-
my_flatten([a, [[b], c], [[d]]], X),
X == [a, b, c, d].
% Тест для глубоко вложенных списков
test(flatten_deeply_nested) :-
my_flatten([[1, [2, [3, [4, 5]]]], 6], X),
X == [1, 2, 3, 4, 5, 6].
% Тест для списка с пустыми подсписками
test(flatten_with_empty_lists) :-
my_flatten([a, [], [b, []], [[]], c], X),
X == [a, b, c].
% Тест для пустого списка
test(flatten_empty_list) :-
my_flatten([], X),
X == [].
% Тест для списка с одним элементом
test(flatten_single_element) :-
my_flatten([x], X),
X == [x].
% Тест для списка, содержащего только вложенные пустые списки
test(flatten_only_empty_lists) :-
my_flatten([[], [[]], [[[]]]], X),
X == [].
:- end_tests(my_flatten).
%5
% Базовый случай: код Грея для одного бита
gray([_], [[0], [1]]).
% Рекурсивное построение кода Грея для N бит
gray([_|T], Code) :-
gray(T, SmallerCode), % Строим код для (N-1) бит
reverse(SmallerCode, RevCode), % Переворачиваем его
add_prefix(0, SmallerCode, ZeroPrefixed), % Дописываем 0 в начало
add_prefix(1, RevCode, OnePrefixed), % Дописываем 1 в начало
append(ZeroPrefixed, OnePrefixed, Code). % Объединяем
% Вспомогательный предикат: добавляет префикс к каждому элементу списка
add_prefix(_, [], []).
add_prefix(Prefix, [H|T], [[Prefix|H]|Rest]) :-
add_prefix(Prefix, T, Rest).
%gray([0], Code)
%gray([0,0], Code)
%gray([0,0,0], Code)
:- begin_tests(gray).
test(gray_1bit) :-
gray([0], [[0], [1]]).
test(gray_2bit) :-
gray([0,0], [[0,0], [0,1], [1,1], [1,0]]).
test(gray_3bit) :-
gray([0,0,0], [[0,0,0], [0,0,1], [0,1,1], [0,1,0],
[1,1,0], [1,1,1], [1,0,1], [1,0,0]]).
test(gray_4bit) :-
gray([0,0,0,0], [[0,0,0,0], [0,0,0,1], [0,0,1,1], [0,0,1,0],
[0,1,1,0], [0,1,1,1], [0,1,0,1], [0,1,0,0],
[1,1,0,0], [1,1,0,1], [1,1,1,1], [1,1,1,0],
[1,0,1,0], [1,0,1,1], [1,0,0,1], [1,0,0,0]]).
test(gray_invalid_input, fail) :-
gray([], _).
:- end_tests(gray).