我是Prolog
的新手,总体来说是逻辑编程。我正在尝试从已有的教科书中进行练习,并且存在以下问题:考虑一个列表列表,例如:
[[spanish, white], [italian, white], [italian, red], [canadian, blue]]
我们将“和谐”定义为一组唯一的元素,这些元素仅位于一个子列表中。内部列表的每个索引都表示类似的东西:国籍或肤色。在上面的示例中,[canadian, blue]
是“和谐”,但是[italian, white]
并不是因为italian
中也有[italian, red]
。
我正在尝试创建一个遍历子列表的关系,并尝试创建最佳的“和谐”。对于上面的示例,我们应该检查第一个子列表; [spanish, white]
,对于每个元素,检查是否存在另一个包含该元素的子列表。如果它们是唯一的,那就是“和谐”,否则我们应该检查是否可以某种方式减少那些列表之一。输出应为:
[[spanish, white], [italian, red], [canadian, blue]]
说明:spanish
已连接到white
,所以我们不应该碰它,但是italian
包含在white
和red
中。然后我们可以理解,italian
必须连接到red
,因为white is with
是西班牙语。
最终目标是拥有唯一子列表的列表。您可以将其视为方程式系统,我们希望对其进行求解。
另一个例子:
[[spanish, white, 5], [italian, red,4], [canadian, blue,2],[canadian,red,2],[spanish, blue,4]]
输出:
[[spanish, white, 5], [italian, red,4], [canadian, blue,2]]
说明:让我们看一下[spanish, white, 5]
。我们知道spanish
也位于[spanish, blue,4]
中,但是blue
也位于[canadian, blue,2]
中。 canadian
不在其他任何地方,因此blue
属于canadian
。这意味着spanish
得到white
(然后还有5
)。 canadian
得到2
,这意味着italian
得到4
和blue
。
我试图使用findall
,但没有成功。我觉得这里有很多信息,这让我感到困惑。
如何从教科书中解决这个问题?
编辑:
总是只有一种可能的解决方案。如果您收到类似[[spanish, white], [italian, white]]
之类的信息,那么您就没有任何其他信息,应该将其保持不变。
我试图再次解决它,但没有成功。我试图以某种方式创建一个包含所有信息的哈希图,但对我来说,它不是Prolog
解决方案。我认为findall
可以解决此问题,但我似乎不知道如何解决。
答案 0 :(得分:2)
由于值在子列表中的位置是固定的,并且所有子列表都是完整的:
harmony(As,Bs) :- maplist(dif,As,Bs).
harmonies(L,R) :-
forall((select(A,L,S),member(B,S)), harmony(A,B))
-> R=L
; select(_,L,T), harmonies(T,R)
.
creasing_harmonies(L,R) :-
setof(D-T,(harmonies(L,T),length(T,D)),R).
不确定什么是“最佳和谐”。假设是更长的时间:
?- creasing_harmonies([[spanish, white, 5], [italian, red,4], [canadian, blue,2],[canadian,red,2],[spanish, blue,4]],L),last(L,B).
L = [1-[[canadian, blue, 2]], 1-[[canadian, red, 2]], 1-[[italian, red, 4]], 1-[[spanish, blue, 4]], 1-[[spanish, white|...]], 2-[[canadian|...], [...|...]], 2-[[...|...]|...], 2-[...|...], ... - ...|...],
B = 3-[[spanish, white, 5], [italian, red, 4], [canadian, blue, 2]].
如果您的Prolog中没有dif / 2或maplist / 3,则近似值为
harmony([],[]).
harmony([E|As],[E|Bs]) :- !, fail.
harmony([_|As],[_|Bs]) :- harmony(As,Bs).
编辑
到目前为止,它的效率非常低。要获得解决方案,必须减少搜索空间:
harmonies(L,R) :-
length(L,N),N>4,
( forall((select(A,L,S),member(B,S)), harmony(A,B))
-> R=L
; select(_,L,T), harmonies(T,R)
).
但是让我们看看我们现在有多少个“解决方案”
?- test_data(L),aggregate(count,harmonies(L,R),C).
L = [[table, green, alex, coffee, prince], [keyboard, green, alex, coffee, bookA], [keyboard, yellow, alex, water, bookA], [cup, red, alex, water, bookB], [computer, white, john, beer|...], [cup, red, birds|...], [keyboard, green|...], [keyboard|...], [...|...]|...],
R = [[table, green, alex, coffee, prince], [computer, white, john, beer, bookD], [cup, red, birds, milk, bookC], [keyboard, yellow, sabrina, water, bookA], [dane, blue, sasha, tea|...]],
C = 5040.
5040个重复!最好在固定长度上停在第一个解决方案上。
harmonies(L,N,R) :-
length(L,M),M>=N,
( forall((select(A,L,S),member(B,S)), harmony(A,B))
-> R=L
; select(_,L,T), harmonies(T,R)
).
?- test_data(L),harmonies(L,5,R).
L = [[table, green, alex, coffee, prince], [keyboard, green, alex, coffee, bookA], [keyboard, yellow, alex, water, bookA], [cup, red, alex, water, bookB], [computer, white, john, beer|...], [cup, red, birds|...], [keyboard, green|...], [keyboard|...], [...|...]|...],
R = [[table, green, alex, coffee, prince], [computer, white, john, beer, bookD], [cup, red, birds, milk, bookC], [keyboard, yellow, sabrina, water, bookA], [dane, blue, sasha, tea|...]] .
答案 1 :(得分:2)
像这样吗?
?- test1(L), solution(L, S).
L = [[spanish, white], [italian, white], [italian, red], [canadian, blue]],
S = [[canadian, blue], [italian, red], [spanish, white]] ;
false.
?- test2(L), solution(L, S).
L = [[spanish, white, 5], [italian, red, 4], [canadian, blue, 2], [canadian, red, 2], [spanish, blue, 4]],
S = [[canadian, blue, 2], [italian, red, 4], [spanish, white, 5]] ;
false.
测试:
within ".mark-ready-btn.server-button" do
click_on ".server-mark-ready"
end
这不是最佳的性能,因为在答案集中没有中间减少,但是可以很好地说明Prolog。