#list #prolog #tuples #prolog-findall
#Список #пролог #кортежи #пролог-найти все
Вопрос:
Мне нужно создать список из базы знаний, который мог бы выглядеть следующим образом:
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)
Этот список должен содержать кортежи, каждый из которых содержит второе и третье значение fact2, а также добавленные числа fact2 всякий раз, когда первое значение fact1 и fact2 совпадают.
Может быть, это станет понятнее, когда я покажу, что у меня есть на данный момент. Вот мой предикат с оператором 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)]
Это означает, что всякий раз, когда первые два элемента кортежа совпадают, числа, которые являются третьим элементом кортежа, должны быть сложены вместе.
Однако я не знаю, как даже приблизиться к чему-то подобному, поскольку я всегда читал, что, как только список установлен, его нельзя изменить, поскольку prolog является функциональным и декларативным.
Поэтому я думаю, что мне каким-то образом нужно сопоставить каждый элемент с элементом до или после него (поскольку список всегда будет сортироваться по переменным Out1 и Out2), и если они совпадают, добавьте третье значение в кортеж вместе. Проблема в том, что я понятия не имею, как это сделать.
Мне кажется, что это не может быть сделано в самом findall, но должно быть сделано после findall Я настоящий новичок и был бы признателен за любую помощь. В этом случае было бы лучше, если бы все решение заключалось в одном предикате.
Комментарии:
1. Мне неприятно это говорить, но когда я вижу ваши вопросы, я просто пропускаю их мимо ушей, потому что вы никогда не даете достаточно подробностей.
2. Пожалуйста, используйте правильный синтаксис.
fact2 (Val3, Out1, Out2)
будет синтаксической ошибкой в Prolog. Между функтором и аргументами не должно быть пробелов.
Ответ №1:
Вот еще одно решение, которое использует более одного предиката:
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]].
Ответ №2:
с помощью агрегата библиотеки:
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)].
Вы здесь не правы
поскольку prolog является функциональным и декларативным
Prolog является реляционным и декларативным