How to create a list of index values based on 2 lists in prolog

时间:2017-04-10 01:25:27

标签: prolog

I'm trying to work on an assignment, however am really stuck on this section. What I need to do is write a predicate called matching with three parameters, all lists. The third list must contain the index of the positions in which the first two lists contain the same value. I really don't know where to start on this so any help would be much appreciated!

2 个答案:

答案 0 :(得分:2)

  

第三个列表必须包含前两个列表包含相同值的位置的索引。

首先重要的是:

  

第三个列表必须包含前两个列表包含相同值的位置索引。

使用统一。作为谓词:

same_value(X, X).
  

第三个列表必须包含前两个列表包含相同值的位置索引。

lists_same_value([X|_], [Y|_]) :- same_value(X, Y). % succeed
lists_same_value([_|Xs], [_|Ys]) :-                 % skip head
    lists_same_value(Xs, Ys).                       % recursive definition

简化并统一:

lists_same_value([X|_], [X|_]).     % succeed
lists_same_value([_|Xs], [_|Ys]) :- % skip head element
    lists_same_value(Xs, Ys).       % recursive definition
  

第三个列表必须包含前两个列表包含相同值的位置的索引

为当前索引添加累加器,当磁头是相同的元素时成功,并查看列表的其余部分。

lists_same_value_index([X|_], [X|_], N, N).      % succeed
lists_same_value_index([_|Xs], [_|Ys], N0, N) :- % skip head element
    succ(N0, N1),                                % next index
    lists_same_value_index(Xs, Ys, N1, N).       % recursive definition

实例化累加器:

lists_same_value_index(Xs, Ys, N) :-
    lists_same_value_index(Xs, Ys, 0, N).

bagof一起使用以查找所有解决方案:

?- bagof(N, lists_same_value_index([a,b,c,a,c,d,c], [a,c,c,a,d,d,c], N), Ns).
Ns = [0, 2, 3, 5, 6].

并且这与当然有两个nth0的解决方案不同,请参阅:

?- numlist(1, 100, L), time( bagof(N, lists_same_value_index(L, L, N), Ns) ).
% 314 inferences, 0.000 CPU in 0.000 seconds (98% CPU, 1785481 Lips)
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
Ns = [0, 1, 2, 3, 4, 5, 6, 7, 8|...].

?- numlist(1, 100000, L), time( bagof(N, lists_same_value_index(L, L, N), Ns) ).
% 300,014 inferences, 0.052 CPU in 0.052 seconds (100% CPU, 5765387 Lips)
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
Ns = [0, 1, 2, 3, 4, 5, 6, 7, 8|...].

然后使用nth0

?- numlist(1, 100, L), time( findall(N, ( nth0(N, L, E), nth0(N, L, E) ), Ns) ).
% 2,181 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 3329847 Lips)
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
Ns = [0, 1, 2, 3, 4, 5, 6, 7, 8|...].

?- numlist(1, 100000, L), time( findall(N, ( nth0(N, L, E), nth0(N, L, E) ), Ns) ).
% 1,667,166,681 inferences, 151.139 CPU in 151.244 seconds (100% CPU, 11030703 Lips)
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
Ns = [0, 1, 2, 3, 4, 5, 6, 7, 8|...].

答案 1 :(得分:1)

正如@Capellic建议您可以使用findall / 3和nth1 / 3谓词:

common_elemnts_pos(L1,L2,Pos):- 
           findall(X, (nth0(X,L1,Elem), nth0(X, L2, Elem)) , Pos).

上面简单地说找到所有位置X,L1中的元素是Elem,L2中的元素是Elem,所以具有相同的元素。

示例:

?- common_elemnts_pos([1,3,4,5,7,9],[1,2,4,5,8,9],Pos).
Pos = [0, 2, 3, 5].

执行纯粹的递归解决方案也很容易:

common_elemnts_pos(L1,L2,Pos):- common_elemnts_pos(L1,L2,Pos,0).

common_elemnts_pos([],_,[],_).
common_elemnts_pos(_,[],[],_).
common_elemnts_pos([H|T],[H|T1],[CurrentPos|T2],CurrentPos):- 
                               N_CurrentPos is CurrentPos+1,
                               common_elemnts_pos(T,T1,T2,N_CurrentPos).
common_elemnts_pos([H|T],[H1|T1],T2,CurrentPos):- 
                               dif(H,H1), N_CurrentPos is CurrentPos+1,
                               common_elemnts_pos(T,T1,T2,N_CurrentPos).

示例:

?- common_elemnts_pos([1,3,4,5,7,9],[1,2,4,5,8,9],Pos).
Pos = [0, 2, 3, 5] ;
Pos = [0, 2, 3, 5] ;
false.
?- common_elemnts_pos([1,3,4,5,7,9],[1,2,4,5,8,9],Pos).
Pos = [0, 2, 3, 5] ;
false.

在上面的第一个测试中有两个相同的解决方案,因为两个基本情况都是有效的。如果你只想要一个,你可以替换:

common_elemnts_pos([],_,[],_).
common_elemnts_pos(_,[],[],_).

基础案例:

common_elemnts_pos([],[_|_],[],_).
common_elemnts_pos(_,[],[],_).