What would be an efficient way to check how many equal ending digits have numbers between lists in prolog?
For example we have Lista = [4432,2345,3243]
and Listb = [3345,3232]
.
In these two lists we have 4432 and 3232 which have 2 same ending digits and 3345 , 2345 which have 3 same ending digits. 3243 , 3232 have the same 2 starting digits but I don't count this as valid. I have solved this problem in the slowest way , by checking each number of Lista
with each number of Listb
, but this is very slow. How can I solve this problem more efficiently?
Edit 1: I applied some changes to the answer code I managed to find the same digits and the subtree remaining , however I cannot combine them in order to find exactly the numbers that the element of the one list has the same digits with them. Can you help me proceed?
same_ending(Tree, N /*4904*/, N-Len-Last) :-
atom_chars(N, Digs),
reverse(Digs, RDigs),
same_ending1(RDigs, Tree, [], Fin, 0, Lens),
pow2(Lens, Res1),
Res is Res1-1,
Len = Res,
Last = Fin.
same_ending1([], _, Curr, Fin, Len, Len).
same_ending1([Dig|Digs], Tree, Curr, Fin, Len, Len2) :-
( select(Dig-SubTree, Tree, _) ->
( succ(Len, Len1), append([Dig], Curr, Currn),
same_ending1(Digs, SubTree, Currn, Fin, Len1, Len2) )
;
Len2 = Len,
Fin = Curr-Tree
).
Edit 2: For the final suggestion on @gusbro 's answer I created this code
ssame_endings(L1,[],Curr,Final):- Final=Curr.
ssame_endings(L1, L2,Curr,Final):-
build_tree(L1, Tree),
head(L2,H),
tail(L2,T),
findall(Res,same_ending(Tree,H,Res) , Endings),
append(Curr,Endings,Curr1),
ssame_endings(L1,T,Curr1,Final).
head([A|_],A).
tail([_|A],A).
pow2(X,Z) :- Z is 2**X.
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, SubTree1):-
SubTree=[] -> SubTree1=[[]]; SubTree1=SubTree.
same_ending1([Dig|Digs], Tree, Len, Len2, SubTree):-
(select(Dig-DigSubTree, Tree,Third) ->
(succ(Len, Len1), same_ending1(Digs, DigSubTree, Len1, Len2, SubTree),same_ending1(Digs,Third,Len1,Len2,SubTree)) ;
Len2-SubTree=Len-Tree
).
I used findall as suggested in order to combine all the answers given and I think that part is correct as I have written it. Then I used select after that which as I understand if we have the tree [1-[2-[3,4]] and we want both 1,2,3 and 1,2,4. if we have the number 5321 the third parameter will also give us 124. However the way I am using it does not produce the expected outcome. What I am doing wrong?
See Question&Answers more detail:os