Prolog 检查列表之间的数字是否相等?
什么是检查序言中列表之间有多少相同结尾数字的有效方法? 例如,我们有Prolog 检查列表之间的数字是否相等?,prolog,clpfd,Prolog,Clpfd,什么是检查序言中列表之间有多少相同结尾数字的有效方法? 例如,我们有Lista=[443223453243]和Listb=[33453232] 在这两个列表中,我们有4432和3232,它们有2个相同的结束数字和33452345,它们有3个相同的结束数字。3243232有相同的2个起始数字,但我不认为这是有效的。我以最慢的方式解决了这个问题,通过检查每个Lista的数量和每个Listb的数量,但这是非常慢的。我怎样才能更有效地解决这个问题 编辑1:我对答案代码进行了一些更改,我设法找到了相同的
Lista=[443223453243]
和Listb=[33453232]
在这两个列表中,我们有4432和3232,它们有2个相同的结束数字和33452345,它们有3个相同的结束数字。3243232有相同的2个起始数字,但我不认为这是有效的。我以最慢的方式解决了这个问题,通过检查每个Lista
的数量和每个Listb
的数量,但这是非常慢的。我怎样才能更有效地解决这个问题
编辑1:我对答案代码进行了一些更改,我设法找到了相同的数字和剩余的子树,但是我无法将它们组合在一起,以便找到一个列表中元素具有相同数字的数字。你能帮我继续吗
相同的结尾(Tree,N/*4904*/,N-Len-Last):-
原子字符(N,Digs),
反向(Digs、RDIG),
相同的结尾1(RDigs,树,[],鳍,0,透镜),
pow2(镜头,Res1),
Res是Res1-1,
Len=Res,
最后一个=鳍。
相同的结尾1([],[当前,财务,长,长)。
相同的结尾1([Dig | Digs],树,电流,鳍,Len,Len2):-
(选择(挖掘子树、树)->
(成功(Len,Len1),追加([Dig],Curr,Currn),
相同的结尾1(挖掘、子树、当前、Fin、Len1、Len2))
;
Len2=Len,
Fin=Curr树
).
编辑2:对于@gusbro答案的最后建议,我创建了以下代码
ssame_结尾(L1,[],Curr,Final):-Final=Curr。
ssame_结尾(L1、L2、Curr、Final):-
构建树(L1,树),
头部(L2,H),
尾部(L2,T),
findall(Res,相同的_结尾(Tree,H,Res),结尾),
附加(当前、结尾、当前1),
ssame_结尾(L1,T,Curr1,Final)。
头([A | |,]A)。
尾巴([u124; A],A)。
pow2(X,Z):-Z是2**X。
相同的结尾(树,N,N-Len/LItems):-
原子字符(N,Digs),
反向(Digs、RDIG),
相同的结尾1(RDigs,Tree,0,Len,SubTree),
长度(SDigs,Len),
附加(SDigs、RDigs、,
反向(SDigs、RSDigs),
相同的后缀2(子树,RSDigs,[],LItems)。
相同的结尾([],子树,Len,Len,SubTree1):-
子树=[]->SubTree1=[[]];子树1=子树。
相同的结尾1([Dig | Digs],树,Len,Len2,子树):-
(选择(挖掘子树、树、第三个)->
(such(Len,Len1),same_ending1(Digs,DigSubTree,Len1,Len2,SubTree),same_ending1(Digs,Third,Len1,Len2,SubTree));
Len2子树=Len树
).
我按照建议使用findall来组合给出的所有答案,我认为这一部分是正确的。然后我使用select,如果我们有树[1-[2-[3,4]]我们需要1,2,3和1,2,4。如果我们有数字5321,第三个参数也会给我们124。但是我使用它的方式并没有产生预期的结果。我做错了什么?你可以为第一个列表建立一个反向数字树,然后为第二个列表中的每个反向项遍历该树。这可能更有效如果列表中有许多项,请输入
same_endings(L1, L2, Endings):-
build_tree(L1, Tree),
maplist(same_ending(Tree), L2, Endings).
same_ending(Tree, N, N-Len):-
atom_chars(N, Digs),
reverse(Digs, RDigs),
same_ending1(RDigs, Tree, 0, Len).
same_ending1([], _, Len, Len).
same_ending1([Dig|Digs], Tree, Len, Len2):-
(select(Dig-SubTree, Tree, _) ->
(
succ(Len, Len1),
same_ending1(Digs, SubTree, Len1, Len2)
) ;
Len2=Len
).
build_tree(L, Tree):-
foldl(add_tree, L, [], Tree).
add_tree(N, Tree, NTree):-
atom_chars(N, Digs),
reverse(Digs, RDigs),
add_tree1(RDigs, Tree, NTree).
add_tree1([], Tree, Tree).
add_tree1([Dig|Digs], Tree, [Dig-SubTree1|Tree1]):-
(select(Dig-SubTree, Tree, Tree1) -> true; SubTree-Tree1=[]-Tree),
add_tree1(Digs, SubTree, SubTree1).
测试样本:
?- same_endings( [4432,2345,3243] , [3345,3232], Endings).
Endings = [3345-3, 3232-2].
您可以稍微修改此代码以获得具有相同结尾的实际项目
稍微修改一下上面的代码,您还可以列出第一个列表中的实际数字,这些数字在第二个列表中的每个项目上都有相同(最大)的结尾:
same_endings(L1, L2, Endings):-
build_tree(L1, Tree),
maplist(same_ending(Tree), L2, Endings).
same_ending(Tree, N, N-Len/LItems):-
atom_chars(N, Digs),
reverse(Digs, RDigs),
same_ending1(RDigs, Tree, 0, Len, SubTree),
length(SDigs, Len),
append(SDigs, _, RDigs),
reverse(SDigs, RSDigs),
same_ending2(SubTree, RSDigs, [], LItems).
same_ending1([], SubTree, Len, Len, SubTree).
same_ending1([Dig|Digs], Tree, Len, Len2, SubTree):-
(memberchk(Dig-DigSubTree, Tree) ->
(
succ(Len, Len1),
same_ending1(Digs, DigSubTree, Len1, Len2, SubTree)
) ;
Len2-SubTree=Len-Tree
).
same_ending2([], _, LItems, LItems).
same_ending2([Dig-DigSubTree|SubTree], Digs, MItems, LItems):-
(Dig=endmarker ->
(
number_chars(Item, Digs),
NItems=[Item|MItems]
) ;
same_ending2(DigSubTree, [Dig|Digs], MItems, NItems)
),
same_ending2(SubTree, Digs, NItems, LItems).
build_tree(L, Tree):-
foldl(add_tree, L, [], Tree).
add_tree(N, Tree, NTree):-
number_chars(N, Digs),
reverse(Digs, RDigs),
add_tree1(RDigs, Tree, NTree).
add_tree1([], Tree, [endmarker-[]|Tree]).
add_tree1([Dig|Digs], Tree, [Dig-SubTree1|Tree1]):-
(select(Dig-SubTree, Tree, Tree1) -> true; SubTree-Tree1=[]-Tree),
add_tree1(Digs, SubTree, SubTree1).
测试用例:
?- same_endings( [4432,2345,3243] , [3345,3232], Endings).
Endings = [3345-3/[2345], 3232-2/[4432]].
?- same_endings( [4432,2345,3243,2195345,2345] , [3345,3232,19232,2195345], Endings).
Endings = [3345-3/[2195345, 2345, 2345], 3232-2/[4432], 19232-2/[4432], 2195345-7/[2195345]].
当一个项目没有共享任何结尾数字时,没有特殊处理,在这种情况下,代码只会吐出整个列表
如果您想获得至少有一个匹配结尾数字的所有项目,只需将过程
same_endings
和same_endings 1
更改为以下步骤:
same_endings(L1, L2, Endings):-
build_tree(L1, Tree),
findall(Ending, (member(N, L2), same_ending(Tree, N, Ending)), Endings).
same_ending1([], SubTree, Len, Len, SubTree).
same_ending1([Dig|Digs], Tree, Len, Len2, SubTree):-
(select(Dig-DigSubTree, Tree, RestTree) ->
(
(
Len\=0,
RestTree \= [],
Len2=Len,
SubTree=RestTree
) ;
(
succ(Len, Len1),
same_ending1(Digs, DigSubTree, Len1, Len2, SubTree)
)
) ;
Len2-SubTree=Len-Tree
).
shared_tail_len_atom(A,B,N,S):-
亚_原子(A,u,N,0,S),
N> =1%,提高此值以减少开销
亚原子(B,N,0,S)。
相同的结尾(As、Bs、Es):-
一组(N-ab(A,B),
聚合(
最大值(C),
(成员(A,As),
成员(B,Bs),
共享尾长原子(A,B,C,S)
),N),Es)。
您可以尝试这个简单的代码段。sub_atom/5它是一个ISO Prolog内置代码,但它与数字一起工作的事实可能是一个SWI Prolog扩展
?-相同的结尾(参见[123223333],[423433],结尾)。
结尾=[1-ab(123433),1-ab(223433),1-ab(333423),2-ab(123423),2-ab(223423),2-ab(333433)]。
我编辑了这个问题,因为我正在修整以获得具有相同结尾的实际项目,但我有一个困难:感谢编辑,如果3345有两个相同的结尾数字和另一个数字,而不仅仅是3@Vaas:此算法显示具有最大“相同结尾”的数字。如果您想显示其他数字,您可以更改相同的\u ending1
来添加其他数字。我已经尝试了几天了,您能给我一个提示吗?我正在修改此代码,问题是程序“继续”直到树上不再有相等的数字。但是我找不到一种方法来添加相等数字小于最大值的数字,因为如果每次它找到一个相等的数字时我都停止它,我们将有许多重复的数字。例如,如果第一个列表是[443223453221953452345995],那么在结果中我应该有[3345-3]/[219534523452345],3345-1/[9995],…],但他们似乎不可能以这种方式编写代码。我错了吗?它会得到“列表之间有多少相等的结尾数字”,按长度排序