контрольный список пролога - PullRequest
2 голосов
/ 08 января 2012

У меня есть следующий код:

check([],[]).
check([X], [Y]) :-
    X > 0,
    Y is 1.
check([X], [Y]) :-
    X =:= 0,
    Y is 0.
check([L1|Tail], [L2|Tail2]) :-
    L1 > 0,
    L2 is 1,
    check(Tail,Tail2).
check([L1|Tail], [L2|Tail2]) :-
    L1 =:= 0,
    L2 is 0,
    check(Tail,Tail2).

проверка предиката создает таблицу, которая заменяет все элементы больше 0 на 1. этот предикат работает для простого списка типа L = [3,4,5,6,0] и создает список L1 = [1,1,1,1,0].

Мне нужно выполнить предикатную проверку, чтобы принимать списки, у которых списки есть как элементы.

Например: L = [[2, 3, 4], [4, 0, 6], [5, 6, 3]]. Элементов списка столько же, сколько элементов списка элементов. Это означает, что если список содержит 3 списка элементов, каждый список элементов должен содержать 3 элемента.

Ответы [ 2 ]

6 голосов
/ 08 января 2012

Для отношений, которые одинаковы для каждого элемента в списке, часто лучше описать отношение для одного элемента, а затем использовать maplist / 3:

check(0, 0).
check(N, 1) :- N > 0.

Пример запроса:

?- maplist(check, [3,4,5,6,0], Ls).
Ls = [1, 1, 1, 1, 0] ;
false.

Теперь регистр вложенных списков преобразуется во вложенный список карт / 3:

?- maplist(maplist(check), [[2, 3, 4], [4, 0, 6], [5, 6, 3]], Ls).
Ls = [[1, 1, 1], [1, 0, 1], [1, 1, 1]] ;
false.
0 голосов
/ 08 января 2012

Прежде всего, ваши вторые и третьи предложения не нужны, они просто создают дубликаты решений, вот лучший предикат check/2:

check([],[]).
check([L1|Tail], [L2|Tail2]) :-
    L1 > 0,
    L2 is 1,
    check(Tail,Tail2).
check([L1|Tail], [L2|Tail2]) :-
    L1 =:= 0,
    L2 is 0,
    check(Tail,Tail2).

Затем, вместо использования is/2 для присвоения значений L2, вы можете напрямую указать значение L2 в заголовке ваших предложений, например:

check([],[]).
check([L1|Tail], [1|Tail2]) :-
    L1 > 0,
    check(Tail,Tail2).
check([L1|Tail], [0|Tail2]) :-
    L1 =:= 0,
    check(Tail,Tail2).

Затем, вместо использования =:=/2, вы можете снова указать непосредственно значение в заголовке вашего второго предложения:

check([],[]).
check([L1|Tail], [1|Tail2]) :-
    L1 > 0,
    check(Tail,Tail2).
check([0|Tail], [0|Tail2]) :-
    check(Tail,Tail2).

Теперь ваш предикат check/2 уже выглядит намного лучше!

Давайте добавим предложение для обработки вложенности списка:

check([],[]).
check([L1|Tail], [L2|Tail2]) :-
    L1 = [_|_],
    check(L1, L2),
    check(Tail, Tail2).
check([L1|Tail], [1|Tail2]) :-
    \+ L1 = [_|_],
    L1 > 0,
    check(Tail,Tail2).
check([0|Tail], [0|Tail2]) :-
    check(Tail,Tail2).

Как вы видели, нам также нужно было добавить тест, что L1 не является списком в нашем предыдущем предложении, чтобы список не шел по этому пути и не приводил к странным решениям.

Надеюсь, это помогло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...