Слияние элементов кортежей в списке в Прологе - PullRequest
0 голосов
/ 14 апреля 2019

Мне нужно создать список из базы знаний, который может выглядеть следующим образом:

fact1(3,3).
fact1(2,3).
fact1(3,5).
fact1(2,2).
fact1(2,10).
fact1(3,1).
fact1(1,1).
fact1(1,6).

fact2(3,a,b)
fact2(2,c,d)
fact2(1,e,f)

Этот список должен содержать кортежи, каждый из которых содержит второе и третье значение факта 2 и добавленные номера факта 2, всякий раз, когда совпадают первые значения факта 1 и факта 2.

Может быть, станет яснее, когда я покажу, что у меня есть. Вот мой предикат с утверждением findall, которое, как мне кажется, дает мне самое близкое место, куда мне нужно попасть:

collect_items(List):-
    findall((Out1,Out2,Nr),
        (fact2(Val1,Out1,Out2),
        fact1(Val1,Nr)),
        List).

Список, который я получаю от этого, выглядит следующим образом:

List = [(a,b,3),(a,b,5),(a,b,1),(c,d,3),(c,d,2),(c,d,10),(e,f,1),(e,f,6)]

Но мне действительно нужно, чтобы список выглядел так:

List = [(a,b,9),(c,d,15),(e,f,7)]

Это означает, что всякий раз, когда совпадают первые два элемента кортежа, числа, являющиеся третьим элементом кортежа, должны складываться вместе.

Однако я не знаю, как даже приблизиться к чему-то подобному, как я всегда читал, что, как только список задан, его нельзя изменить, поскольку пролог функционален и декларативен.

Так что я думаю, что мне нужно как-то сопоставить каждый элемент с элементом до или после него (поскольку список всегда будет отсортирован по переменным Out1 и Out2), и, если они совпадают, добавьте третье значение в кортеж вместе. Проблема в том, что я понятия не имею, как.

Мне кажется, что это не может быть сделано в самом самом findal, но должно быть сделано после findall Я настоящий новичок и буду признателен за любую помощь. В этом случае было бы лучше, если бы решение было все в одном предикате.

Ответы [ 3 ]

0 голосов
/ 14 апреля 2019

Вот еще одно решение, которое использует более одного предиката:

collect_items(Result):-
    findall([Out1,Out2,Nr],(fact2(Val1,Out1,Out2),fact1(Val1,Nr)),[[OutA, OutB, N]|B]), 
    sumElements([[OutA, OutB, N]|B], Result).

sumElements([],[]).
sumElements([[Out, Outt, N]|B], [[Out, Outt, SumLocal]|RestOfList]):-
    findall([Out, Outt, X], member([Out, Outt, X], [[Out, Outt, N]|B]), SubList),
    sumLocal(SubList, SumLocal),
    subtract([[Out, Outt, N]|B], SubList, New),
    sumElements(New, RestOfList).

sumLocal([],0).
sumLocal([[_,_,S]|B], T):-
    sumLocal(B, R),
    T is S + R.

выход:

?- collect_items(Result).
Result = [[a, b, 9], [c, d, 15], [e, f, 7]].
0 голосов
/ 17 апреля 2019

с библиотечным агрегатом:

collect_items(L) :-
    setof((U,V,S),
          K^aggregate((set(X/Y),sum(N)), (
                          fact2(K,X,Y),
                          fact1(K,N)
                      ), ([U/V],S)), L).

мы получаем

?- collect_items(L).
L = [(a, b, 9),  (c, d, 15),  (e, f, 7)].

Вы здесь не правы

поскольку пролог является функциональным и декларативным

Пролог реляционный и декларативный

0 голосов
/ 14 апреля 2019

Это не окончательное решение, так как это домашнее задание.

transformation(fact2(N,A,B),values(Values,A,B)) :-
    bagof(Value,fact1(N,Value),Values).

sum_values(values(Values,A,B),values(Sum,A,B)) :-
    sum_list(Values,Sum).

items(Items) :-
    bagof(fact2(N,A,B), fact2(N,A,B),Facts2),
    maplist(transformation,Facts2,Items1),
    maplist(sum_values,Items1,Items).

Пример выполнения:

?- items(Result).
Result = [values(9, a, b), values(15, c, d), values(7, e, f)].
...