Invert atoms from list to integers - Prolog - list

I have this:
streams=[[1,2,2,4],[2,1,4,2],[3,4,1,3],[4,3,3,1]]
And the numbers inside that lists are all atoms and I need to invert then all to integers. The streams should look like this:
streams=[[1,2,2,4],[2,1,4,2],[3,4,1,3],[4,3,3,1]]
But with all numbers with format 'integer' and not 'atom'
Can someone explain how tranform those numbers to integers please?

To convert between atom and number you can use the built-in predicate atom_number/2:
?- atom_number(Atom, 1).
Atom = '1'.
?- atom_number('1', Number).
Number = 1.
Using maplist/3, you can apply that convertion on all elements of a list of atoms:
?- maplist(atom_number, ['1','2','2','3'], Numbers).
Numbers = [1, 2, 2, 3].
To apply that convertion on all atoms in a list of lists you can do as follows:
?- maplist(maplist(atom_number), [['1','2'],['2','1','4'],['3'],['4','1']], ListOfLists).
ListOfLists = [[1, 2], [2, 1, 4], [3], [4, 1]].

Related

Most common sublist in Prolog

The problem is as follows: Write a predicate in Prolog most_common_sublist(L1,N,L2) that will find the sublist L2 with length N such that it is the most common sublist in L1.
//Example 1:
?- most_common_sublist([1,2,2,3,2,2,4,2,2,3],1,L).
L=[2];
//Example 2:
?- most_common_sublist([1,2,2,3,2,2,4,2,2,3],2,L).
L=[2,2];
//Example 3:
?- most_common_sublist([1,2,2,3,2,2,4,2,2,3],3,L).
L=[2,2,3];
My approach was to generate all the possible sublists of size N using the generator predicate, check which of those is the most common one in the list using the check predicate, and then just put that as my result.
The reason why I'm not using the built-in predicates for length and add is because I'm supposed to write my own.
My generator predicate works, it gives out the correct output.
?- generator([1,2,2,3,2,2,4,2,2,3],3,L).
L = [[1, 2, 2], [2, 2, 3], [2, 3, 2], [3, 2, 2], [2, 2, 4], [2, 4, 2], [4, 2|...], [2|...]] [write]
L = [[1, 2, 2], [2, 2, 3], [2, 3, 2], [3, 2, 2], [2, 2, 4], [2, 4, 2], [4, 2, 2], [2, 2, 3]]
I checked all my predicates and they all seem to work (at least for the test cases I'm using), the problem occurs with the check predicate. It seems to work fine until it gets to N>=P (when this is NOT true, works fine when it is true). I expect the program to go onto the next check predicate under it (the third check predicate) so that it stores Temp value in Result instead of the H value. For some reason it does not go to the third check predicate (I checked with debugger), instead it does something weird (I can't figure out what).
most_common_sublist(L,N,Result):-generator(L,N,LOP),check(LOP,_,Temp),add(Temp,[],Result).
add([],L,L).
add([X|L1],L2,[X|L3]):-add(L1,L2,L3).
length([],0).
length([X|O],N):-length(O,M),N is M+1.
sublist([H|_],1,[H]).
sublist([H|T],N,[H|LOP]):-M is N-1,sublist(T,M,LOP).
generator(L,N,[L]):-length(L,M),N=:=M.
generator([H|T],N,LOP):-sublist([H|T],N,PN),generator(T,N,LP),add([PN],LP,LOP).
check([],Z,K):-Z is 0,add([],[],K).
check([H|T],Hits,Result):-check_how_many(H,[H|T],N),check(T,P,_),N>=P,Hits is N,add(H,[],Result).
check([H|T],Hits,Result):-check_how_many(H,[H|T],N),check(T,P,Temp),Hits is P,add(Temp,[],Result).
check_how_many(X,[X],1).
check_how_many(_,[_],0).
check_how_many(Pattern,[H|T],Hits):-same(Pattern,H),check_how_many(Pattern,T,P),Hits is P+1.
check_how_many(Pattern,[_|T],Hits):-check_how_many(Pattern,T,P),Hits is P.
same([], []).
same([H1|R1], [H2|R2]):-
H1 = H2,
same(R1, R2).
Since I'm not familiar with your code I rewrote it with similar functionality. Lines followed by %here are my improvements (2 times used). For simplicity I used the inbuild predicates length/2 and append/3 instead of add/3. sublist/3 has a complete different code but same functionality, same/2 is not necessary at all. Most uses of you add/3 were not necessary as well as some equality statements.
most_common_sublist(L,N,Temp):-
generator(L,N,LOP),
check(LOP,_,Temp).
sublist(L,N,S):-
length(S,N),
append(S,_,L).
generator(L,N,[L]):-
length(L,N).
generator([H|T],N,LOP):-
sublist([H|T],N,PN),
generator(T,N,LP),
append([PN],LP,LOP).
check([],0,[]).
check([H|T],N,H):-
check_how_many(H,[H|T],N),
check(T,P,_),
N>=P.
check([H|T],P,Temp):-
check_how_many(H,[H|T],N),
check(T,P,Temp)
%here
, N=<P
.
check_how_many(X,[X],1).
check_how_many(_,[_],0).
check_how_many(H,[H|T],Hits):-
check_how_many(H,T,P),
Hits is P+1.
check_how_many(Pattern,[H|T],P):-
%here
Pattern \== H,
check_how_many(Pattern,T,P).
After giving up on tracing I just used the following call to debug after enabling long output (
?- set_prolog_flag(answer_write_options,[max_depth(100)]).
):
?- findall(Temp,check([[1, 2, 2], [2, 2, 1]],_,Temp),Out).
Initial output was
Out = [[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[2,2,1],[2,2,1],[],[],[2,2,1],[2,2,1],[],[]].
Which contains way to much empty lists. First fix (%here) was to set the condition N=<P for the last check/3 case. Until now it was possible to choose a P lower than N, which should be covered by the 2nd check/3 case. Output changed to
Out = [[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[2,2,1],[2,2,1],[2,2,1],[]].
Better, but still empty lists possible. A similar case happens in the last check_how_many/3 case: you have to state that H and Pattern are different, otherwise it would be possible for a fitting Pattern not to be counted. Lets check the output
Out = [[1,2,2],[1,2,2],[1,2,2],[2,2,1]].
Way better. Lets check another case:
?- findall(Temp,check([[1, 2, 2], [1, 2, 2], [2, 2, 1]],_,Temp),Out).
Out = [[1,2,2],[1,2,2],[1,2,2],[1,2,2]].
?- findall(Temp,check([[1, 2, 2], [2, 2, 2], [1, 2, 2]],_,Temp),Out).
Out = [[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[2,2,2],[2,2,2],[2,2,2],[1,2,2]].
Works... Almost.
So the problem seems to be check_how_many/3: alter
check_how_many(_,[_],0).
to
check_how_many(_,[],0).
and you should be fine.
?- findall(Temp,check([[1, 2, 2], [2, 2, 2], [1, 2, 2]],_,Temp),Out).
Out = [[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2],[1,2,2]].
Since it is way more fun to write the code yourself than to debug foreign code I'll add another answer with my attempt.
It is way more fun to code by yourself than to debug alien code. So here is my attempt. It works different than yours because I do not calculate possible subsets but work on the "leftover" list. I use the inbuild predicates length/2, append/3 and member/2 which are 3 lines each to write down.
% check how often 2.nd attribute List occurs in 1st attribute List.
countit([],_,Val,Val).
countit([H|In],Out,Past,Future):-
( append(Out,_,[H|In])
-> Present is Past+1,
countit(In,Out,Present,Future)
; countit(In,Out,Past,Future)
).
mostCommonSublist(In,N,Out):-
maxStartList(In,N,OutList,Max),
member((Max,Out),OutList).
% for every endlist calculate how often the first N elements appear within the endlist, track the max
maxStartList(In,N,[(1,In)],1):-
length(In,N),
!.
maxStartList([H|In],N,[(CntH,Curr)|MaxList],Max):-
length(Curr,N),
countit([H|In],Curr,0,CntH),
maxStartList(In,N,MaxList,CntIn),
Max is max(CntH , CntIn).
The main predicate mostCommonSublist/3 calls the predicate maxStartList/4 to get all sublists/countpairs. Afterwards it validates if the count of a sublist equals the maximum. This is neccessary to check for different answers with the same (maximum) count.
The maxStartList/4 drops elements from the inputlist and counts how often the start of the current list occurs within it. Also it keeps track of the maximum.
For the current inputlist the calculating predicate countit/4 is called. It calculated for a given inputlist (first argument) the number of occurences of a sublist (2nd argument).
My code actually uses a twist: The content of the sublist is not unified when calling countit/4 for the first time, just the sublist length is set. In the first recursion it will unify all entries with the start elements from the inputlist and count it. In the following recursion steps the sublist if fully known. Using an if-then-else (..->..;..) the two cases for remaining inputlist starts with the sublist or not, the predicate basically counts the occurences. Until the remaining inputlist has only N elements left (length(In,N)).
The calculated count/sublist pairs are stored in a list, the maximum is tracked as well.
After knowing all count/sublist pairs I finallize it all by stating that the count of an accepted sublist has to be equal to the maximum.
The nice thing is that there are no dublicate answers.
?- mostCommonSublist([1,2,2,3,2,2,4,2,2,3],3,L).
L = [2,2,3] ;
false.
?- mostCommonSublist([1,2,2,1,2,1,2,2,2,3],3,L).
L = [1,2,2] ;
L = [2,1,2] ;
false.
?- mostCommonSublist([1,2,2,1,2,1,2,2,2,1],2,L).
L = [1,2] ;
L = [2,2] ;
L = [2,1] ;
false.

Prolog: Finding 2 times of a list numbers and putting the number and its double in a list

I'm new to Prolog and I've been trying to create a predicate in Prolog which finds the double of a list of numbers and putting the number and its double in one single list. For example:
?- double_list([2,3,6,10], List).
List = [[2, 4], [3, 6], [6, 12], [10, 20]].
This is the code I've done so far:
double_list([],[]).
double_list([H|T], [[H, double]| List]):-
double is (H*2),
double_list(T, List).
I don't know where I went wrong. I keep on getting false. when trying to run the program.
Variables in Prolog start with either an underscore or an upper case letter. The issue in your code is that you wrote double instead of Double. Correcting your code to:
double_list([],[]).
double_list([H|T], [[H, Double]| List]):-
Double is H*2,
double_list(T, List).
gives you the expected answer to your query:
| ?- double_list([2,3,6,10], List).
List = [[2, 4], [3, 6], [6, 12], [10, 20]]
yes
Some Prolog systems are able to detect the error in your code. For example, using SICStus Prolog, we get:
* invalid LHS in arithmetic expression: double

How to write the result in list instead of printing out in prolog

I'm writing a predicate for finding the bigger number in pairs. If the number has no pair - it will be just added.
write_list([A|[]]):- write(A).
write_list([A, B|Tail]) :- ((A>B, write(A));(A<B,write(B))), nl,
write_list([B|Tail]).
My problem is, I cannot figure out how to write a result in another list instead of printing the result out:
write_list([1,2,6,8,5], X).
X = [2,6,8,8,5].
write only prints the content to the standard output, it does not "yield" it to the result list. In Prolog the only way to generate values, is through unification.
You thus need to define a predicate maxpair/2, not write_list/1.
The predicate thus looks like:
:- use_module(library(clpfd)).
maxpair([A], [A]).
maxpair([A, B|Tail], [H|T]) :-
H #= max(A, B),
maxpair([B|Tail], T).
The first clause says that the maxpair/2 of a singleton list is that singleton list. The latter says that the maxpair/2 for a list containing two or more lists is a list that starts with the maximum of the first two elements, and we recurse on the tail of the list.
The above can also yield a list in reverse. For example:
?- write_list(L, [5, 3, 2, 1]).
L = [5, 3, 2, 1] ;
false.
?- write_list(L, [1, 4, 2, 5]).
false.
?- write_list(L, [3, 3, 5, 5]).
L = [_542, _548, _554, 5],
_542 in inf..3,
3#=max(_542, _548),
_548 in inf..3,
3#=max(_548, _554),
_554 in inf..3 ;
false.
?- write_list(L, [3, 5, 5, 4]).
L = [_1128, _1134, 5, 4],
_1128 in inf..3,
3#=max(_1128, _1134),
_1134 in inf..3 ;
false.
So depending on the situation it can:
fully reconstruct the list;
construct a list with some variables with intervals; or
proof that it is impossible to construct such a list.

Prolog - Most common occurring sequence of length N in a list

I am trying to find the most common sequence of length N that occurs in a list. So I am supposed to write a predicate common(L,N,X) that gives me this sequence in a form of a list. For example: common([1,2,3,2,3,1,4],2,X) should give me back X=[2,3] ; common([1,2,3,4,2,2,2,3,4],3,X) should give back X=[2,3,4] or common([1,2,3],1,X) should give X=[1] X=[2] X=[3].
I have read a couple of posts when we seek only the most common element (so a case where N=1), but I don`t know how to do it for a general N. I am not allowed to use if-then-else or clpfd.
I was thinking maybe grouping the elements and then ordering them, so for common([1,2,3,2,3,1,4],2,X) make a list like this[[1,2],[2,3],[3,2],[2,3],[3,1],[1,4]] and then order the elements from most common to least.
I like your plan. Here's how I'd get the overlapping subsequences.
First, let's get the prefix of the list of length N:
subsequences(L, N, Sub) :- append(Sub, _, L), length(Sub, N).
This should be read "Sub is a subsequence of length N of list L if Sub, appended to something else yields L, and the length of Sub is N." This will definitely get you a prefix of L of length N. Now let's see the recursive case:
subsequences([_|L], N, Sub) :- subsequences(L, N, Sub).
"Otherwise, find a subsequence in the tail of L." And this will produce multiple solutions:
?- subsequences([1,2,3,2,3,1,4], 2, X).
X = [1, 2] ;
X = [2, 3] ;
X = [3, 2] ;
X = [2, 3] ;
X = [3, 1] ;
X = [1, 4] ;
findall/3 is your friend here, you can use it to build the list you want:
?- findall(X, subsequences([1,2,3,2,3,1,4], 2, X), Subsequences).
Subsequences = [[1, 2], [2, 3], [3, 2], [2, 3], [3, 1], [1, 4]].
Hope this helps!

PROLOG - Change elements in a list

I need to change elements in a list, I have the following code:
change_aux(_,_,[],[]).
change_aux(X,Y,[X|T],[Y|S]):-!,change_aux(X,Y,T,S).
change_aux(X,Y,[Z|T],[Z|S]):-change_aux(X,Y,T,S).
flatten2([], []) :- !.
flatten2([L|Ls], FlatL) :-
!,
flatten2(L, NewL),
flatten2(Ls, NewLs),
append(NewL, NewLs, FlatL).
flatten2(L, [L]).
change(X,Y,[X1|Y1],[X2,Y2]):-
flatten([X1|Y1],L),
change_aux(X,Y,L,[X2|Y2]).
Input: change(2,5,[1,[2,[3,2],1]],R).
Print: R = [1, [5, 3, 5, 1]] .
But I need R to be printed like this: R = [1,[5,[3,5],1]]
Could you help me, please?
There are some problems in the code above like in definition change(X,Y,[X1|Y1],[X2,Y2]):- I don't think that the output list should always consists of two elements. Besides that the change_aux predicate needs some work since now it's just traversing the list and not building the nested output list. You could try something that would build recursively the nested levels of the list like:
change(_,_,[],[]).
change(X,Y,[H|T],[H|T1]):- \+is_list(H),dif(H,X),change(X,Y,T,T1).
change(X,Y,[X|T],[Y|T1]):- change(X,Y,T,T1).
change(X,Y,[H|T],[L|T1]):- is_list(H),change(X,Y,H,L),change(X,Y,T,T1).
Note that in the above predicate there is no need to use flatten/2 predicate since we take advantage of the nested levels of input list to build output list.
Example:
?- change(2,5,[1,[2,[3,2],1]],R).
R = [1, [5, [3, 5], 1]] ;
false.