Сбор результатов методов в один список с прологом - PullRequest
0 голосов
/ 08 ноября 2018

Итак, я пытаюсь
Я определяю наборы с помощью is_a(b, a), is_a(c, a), который для простоты визуально будет выглядеть примерно так:

      a
  b       c
d   e    f  g

Я хочу дать в списке [b, c] и в результате получить список [d, e, f, g]

В тот момент, когда я даю node или переменную, он может найти все, что находится под ним, с помощью этого метода:

find_nodes(Root, Root) :-
    \+ is_a(_, Root).
find_nodes(Root, X) :-
    is_a(Node, Root),
    find_nodes(Node, X).

Что при запуске дает мне результат, который мне нужен:

?- find_nodes(b, X).
X = d.
X = e.

Но его нет в списке, поэтому я попробовал:

?- all_nodes([b, c], X).

all_nodes([], _).
all_nodes([H|T], [R|Res]):-
    findall(L, find_nodes(H, L), R),
    all_nodes(T, Res).

Что дает мне - X = [[d, e], [f, g]|_4040], который состоит из списков в списках, но мне нужен только 1 список, который будет X = [d, e, f, g].

Что я здесь не так делаю?

EDIT

Как сказал @lurker findall возвращает список, и добавление списка в список даст результат, который я получаю прямо сейчас.

Я также попробовал использовать одну вещь:

all_nodes([], _).
all_nodes([H|T], [R|Res]):-
    find_nodes(H, R),
    all_nodes(T, Res).

Но хорошо, что он тоже не работает, потому что он дает мне только 1 элемент, который в данном случае равен d, а затем f.

1 Ответ

0 голосов
/ 08 ноября 2018

Вы можете воспользоваться стандартным предикатом findall/4 (*) де-факто для решения проблемы. Этот предикат является вариантом стандартного предиката findall/3, который позволяет передавать хвост для списка решений, собранных предикатом. Например:

?- findall(N, (N=1; N=2; N=3), L, [4,5]).
L = [1, 2, 3, 4, 5].

В следующем решении я переименовал предикаты и переменные для ясности и изменил предикат листа вашего узла:

is_a(a, b).
is_a(a, c).

is_a(b, d).
is_a(b, e).

is_a(c, f).
is_a(c, g).

leaf(Leaf, Leaf) :-
    \+ is_a(Leaf, _).
leaf(Node, Leaf) :-
    is_a(Node, Child),
    leaf(Child, Leaf).

all_nodes([], []).
all_nodes([Node| Nodes], Leaves):-
    findall(Leaf, leaf(Node, Leaf), Leaves, Tail),
    all_nodes(Nodes, Tail).

Примеры звонков:

?- all_nodes([b, c], X).
X = [d, e, f, g].

?- all_nodes([a], X).
X = [d, e, f, g].

?- all_nodes([b], X).
X = [d, e].

(*) Это встроенный предикат в GNU Prolog, JIProlog, Lean Prolog, O-Prolog, SICStus Prolog, SWI-Prolog, XSB и YAP (возможно, других).

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