run length decoding of a list in prolog? - list

I'm trying to decode a given list for example mydecode([(a,1), (b,2), (c,3), (d,2)],X) should give X = ['a','b','b','c','c','c','d','d']. What is the error in this code?
mydecode([],[]).
mydecode([X|Ys],[X|Zs]) :- \+ is_list(X), mydecode(Ys,Zs).
mydecode([[1,X]|Ys],[X|Zs]) :- mydecode(Ys,Zs).
mydecode([[N,X]|Ys],[X|Zs]) :- N > 1, N1 is N - 1, mydecode([[N1,X]|Ys],Zs).

you are asked to handle a list of 'tuples' of 2 elements, not a list of lists of 2 elements
then, the test in the second clause will always fail
the tuples elements are key and value, but you're 'accessing' them in inverse order.
So, remove the second clause - it's irrelevant, since pattern matching will discard ill formed lists.
Change the [1,X] to (X,1) and similarly other references to tuples, and test your code with the query assigned.

Related

Counting how many elements in a list of lists satisfy a predicate

Given a list of lists of integers, e.g. [[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]], I want to go over each sublist and count how many of them sum to 15. In this case that would be 1, for the sublist [3,10,2].
I am aware of the predicate aggregate_all/3, but I'm having trouble writing a predicate to check each element of the list, what I have now is something like
fifteens([X|Xs]) :-
sum_list(X, 15),
fifteens(Xs).
and within another predicate I have:
aggregate_all(count, fifteens(Combinations), Value).
where Combinations is the list of lists of integers in question.
I know my fifteens predicate is flawed since it's saying that all elements of the nested list must sum to 15, but to fix this how do I take out each element of Combinations and check those individually? Do I even need to? Thanks.
First of all your fifteens/2 predicate has no because for empty list and thus it will always fails because due to the recursion eventually fifteens([]) will be called and fail.
Also you need to change completely the definition of fifteens, currently even if you add base case, it says check ALL elements-sublists to see if they sum to 15. That's Ok but I don't see how you could use it with aggregate.
To use aggregate/3 you need to express with fifteens/2, something like: for every part of my combinations list check separately each sublist i.e each member:
ifteens(L) :-
member(X,L),
sum_list(X, 15).
Now trying:
?- aggregate_all(count, ifteens([[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]]), Value).
Value = 1.
This is a job for ... foldl/4. Functional programming idioms in logic programming languages? Yes, we can!
First, summing the summable values of a list:
sum_them(List,Sum) :-
foldl(sum_goal,List,0,Sum).
sum_goal(Element,FromLeft,ToRight) :-
must_be(number,Element),
must_be(number,FromLeft),
ToRight is Element+FromLeft.
Then, counting the ones that sum to 15:
count_them(List,Count) :-
foldl(count_goal,List,0,Count).
count_goal(Element,FromLeft,ToRight) :-
must_be(list(number),Element),
must_be(number,FromLeft),
sum_them(Element,15) -> succ(FromLeft,ToRight) ; FromLeft = ToRight.
Does it work? Let's write some unit tests:
:- begin_tests(fifteen_with_foldl).
test("first test",true(R==1)) :-
count_them([[3,10],[3,10,2],[5],[5,2],[5,3],[5,3,2],[5,3,10]],R).
test("test on empty",true(R==0)) :-
count_them([],R).
test("test with 2 hist",true(R==2)) :-
count_them([[15],[],[1,1,1,1,1,10]],R).
:- end_tests(fifteen_with_foldl).
And so:
% PL-Unit: fifteen_with_foldl ... done
% All 3 tests passed
true.

Define the predicate maxlist( List, Max) so that Max is the greatest number in the list of numbers List

Exercise 3.17 “ Prolog Programming for Artificial Intelligence” by
Ivan Btrako
I understand the max predicate, but I'm having trouble tracing the maxList one. I'm trying to write the logic in pseudocode to help me out
Take first and second elements and compare them and get the
maximum
Take that maximum and compare it with third element in
list and if it's bigger overwrite the maximum and repeat again till
list is empty.
I don't understand the solution given however, and I tried tracing it and failed. I'm having trouble mapping the MaxRest to the Max & with the base case. Also, I don't understand why prolog doesn't give an error when unifying [X,Y|Rest] with [Y|T]. Example [1,3,[7,2]] with [3|[7,2]].
max(X,Y,X):-
X>=Y.
max(X,Y,Y):-
X<Y.
maxlist( [X], X). %what does this line do?
maxlist( [X,Y|Rest], Max):-
maxlist( [Y|Rest], MaxRest),
max(X, MaxRest,Max).
Any help tracing would be greatly appreciated.
Since you understand max/3 this won't explain it.
maxlist( [X], X). %what does this line do?
maxlist( [X,Y|Rest], Max):-
maxlist( [Y|Rest], MaxRest),
max(X, MaxRest,Max).
This is a classic recursive list pattern that does the recursion before processing the item. The normal recursive list pattern with a tail-call is
process_list([H|T],R) :-
process_item(H,R),
process_list(T,R).
process_list([],R).
but here it is
process_list([H|T],R) :-
process_list(T,R),
process_item(H,R).
process_list([],R).
where the item is processed after recursing through the list.
Also this processes two items at a time, i.e.
[H1,H2|T]
because the compare needs two items.
This
maxlist( [X,Y|Rest], Max):-
maxlist( [Y|Rest], MaxRest),
is just taking the values off of the list and pushing them onto the stack so that when it backtracks it will have one value for the comparison, i.e. MaxRest which is the max of all the values that were in Rest and the current value which is X. You might think it should be Y, but when there is just one item in the list, the list is actually [Y|[]] which is really [Y] with matches with the pattern in this clause maxlist( [X], X)..
So what does maxlist( [X], X). do? A common base case for a list is just predicate([],R). for returning a list, but in this case the last value alone needs to be returned as a value, so this takes X out of the list in the first parameter and returns it as a value in the second parameter so that it becomes MaxRest which is the max value when there is only one item in the list. When max(X, MaxRest,Max) is executed it has a value for MaxRest return from backtracking, and X on the stack when deconstructing the list. The result is Max which is returned as the third parameter in maxlist( [X,Y|Rest], Max) which becomes the value for MaxRest upon backtracking again.
Ask questions if that doesn't make sense.
I don't understand why Prolog doesn't give an error when unifying
[X,Y|Rest] with [Y|Rest].
Example [1,3,[7,2]] with [3|[7,2]]
Actually
?- [1,3,[7,2]] = [3|[7,2]].
false.
so while your example does give an error, it is not what is being done with
[X,Y|Rest] and [Y|Rest]
Start with the list [1,2,3,4] and unify it with[X,Y|Rest]
?- [1,2,3,4] = [X,Y|Rest].
X = 1,
Y = 2,
Rest = [3, 4].
Notice that [Y|Rest] would then be [2|[3,4]].
?- [1,2,3,4] = [X,Y|Rest],A = [Y|Rest].
X = 1,
Y = 2,
Rest = [3, 4],
A = [2, 3, 4].
Don't try an unify [X,Y|Rest] with [Y|Rest] but instead unify Rest with Rest and Y with Y, X is stored on the stack but not passed to next level of the stackframe.
If you really want to understand list then use this to see them
?- write_term([1,2,3,4],[dotlists(true)]).
.(1,.(2,.(3,.(4,[]))))
true.
If you have Version 4 of the book see Figure 3.1 on page 61.
Prolog predicates define relations in terms of logic that says that the head of the clause is true if (:-) the body is true. This helps you properly read a predicate:
max(X,Y,X):-
X>=Y.
This says that:
X is the maximum of X and Y if X >= Y is true.
You can similarly read the clause for max(X,Y,Y).
Now look at:
maxlist( [X], X).
Here, we're defining maxlist to mean the maximum value of a list. This particular clause says that:
X is the maximum value of the list [X].
There are no if conditions (:-) in this case since no other conditions are necessary to establish this rule.
Then there is the recursive clause:
maxlist( [X,Y|Rest], Max):-
maxlist( [Y|Rest], MaxRest),
max(X, MaxRest,Max).
This says that:
Max is the maximum value of list [X,Y|Rest] if MaxRest is the maximum of list [Y|Rest] and Max is the maximum value of X and MaxRest.
This recursive clause and the prior base case clause completely define maxlist. If you read through that carefully, it should seem completely logical.
I don't understand why prolog doesn't give an error when unifying [X,Y|Rest] with [Y|T]
I don't understand this comment. Nowhere in your code does Prolog attempt to unify these two terms. Your example terms of [1,3,[7,2]] and [3|[7,2]] would not unify because the first is a list of three elements: 1, 3, and [7,2], whereas the other is a list of 3 elements: 3, 7, and 2. For two lists to be unifiable, it not only needs to be the same length, but each corresponding term in the list must be unifiable.
What would then make [X,Y|Rest] and [Y|T] unifiable? You can write [X,Y|Rest] as [X|[Y|Rest]], which makes it easy to see that these are unifiable if the following are true:
X = Y,
[Y|Rest] = T
In other words, the lists have to have (a) at least two elements, and (b) the first two elements are the same.

How to write a prolog program that takes List1 and List2 as inputs, and the resulting list is the alternating elements of List1 and List2? [duplicate]

This question already has answers here:
Shuffle in prolog
(2 answers)
Closed 5 years ago.
This is my first attempt at using recursion over lists on a non-sample program so bare with my inexperience!
Expected Valid Queries:
mixElements([],[a,b,c], [a,b,c]).
mixElements([a,b],[],[a,b]).
mixElements([a,b,c],[d,e,f],[a,d,b,e,c,f]).
mixElements([a,b,c],[d,e,f,g,h],[a,d,b,e,c,f,g,h]).
Here I tried to create the base case for when the inputs lists are empty, the Result is simply returned.
/* Base cases */
mixElements([],[],Result).
The logic for my recursive statement is that the input lists must be at least 1 or more elements. Thus they must both be represented by [H|L] respectively for list 1 and 2. Then it will append H1 and H2 to Result to create the alternating pattern of list elements. Finally it will call mixElements with the remainder of the lists, L1 and L2, and the Result list that should now contain the first head elements of both lists.
/* Recursive case where both L1 and L2 are not empty */
mixElements([H1|L1],[H2|L2],Result) :- append(H1,H2,Result), mixElements(L1,L2,Result).
My resulting output is always "no".
When dealing with lists it's usually worthwhile considering DCGs since they yield easily readable code. It further aids readability to choose a descriptive name for the relation, say list_list_interlocked/3. Consider the following code:
list_list_interlocked(L1,L2,I) :-
phrase(interlocked(L1,L2),I).
interlocked([],[]) --> % if both input lists are empty
[]. % the resulting list is also empty
interlocked([],[H2|T2]) --> % if the first input list is empty
[H2], % the head of the second is in the list
interlocked([],T2). % the relation holds for the tail as well
interlocked([H1|T1],[]) --> % if the second input list is empty
[H1], % the head of the first is in the list
interlocked(T1,[]). % the relation holds for the tail as well
interlocked([H1|T1],[H2|T2]) --> % if both lists are non-empty
[H1,H2], % the heads are in the list
interlocked(T1,T2). % the relation holds for the tails as well
Your example queries yield the desired result:
?- list_list_interlocked([],[a,b,c],I).
I = [a,b,c]
?- list_list_interlocked([a,b],[],I).
I = [a,b]
?- list_list_interlocked([a,b,c],[d,e,f],I).
I = [a,d,b,e,c,f]
?- list_list_interlocked([a,b,c],[d,e,f,g,h],I).
I = [a,d,b,e,c,f,g,h]
Basically there are four cases here:
the first list is empty, the second list is empty, in that case the result should be empty:
mixElements([],[],[]).
the first list is empty, the second list is non-empty, in that case, the result is the second list:
mixElements([],[H2|T2],[H2|T2]).
the first list is non-empty, the second list is empty, in that case, the result is the first list:
mixElements([H1|T1],[],[H1|T1]).
finall both lists are non-empty, in that case the two first elements of the result are the heads of the list, followed by mixing the tails of the lists:
mixElements([H1|T1],[H2|T2],[H1,H2|TT]) :-
mixElements(T1,T2,TT).
Now we can put that all together into:
mixElements([],[],[]).
mixElements([],[H2|T2],[H2|T2]).
mixElements([H1|T1],[],[H1|T1]).
mixElements([H1|T1],[H2|T2],[H1,H2|TT]) :-
mixElements(T1,T2,TT).
Now we have created some redundant statements. For instance we can merge the first two statements into one, like:
mixElements([],L,L).
mixElements([H1|T1],[],[H1|T1]).
mixElements([H1|T1],[H2|T2],[H1,H2|TT]) :-
mixElements(T1,T2,TT).
I leave it as an exercise to further improve the predicate. You can for instance use cuts, but this can eliminate the multi-direction of the predicate, which is sometimes very useful.
You're using append/3 where it's not needed. When the pattern is formed by 2 lists of at least one element, you can get the result immediately, then recurse to handle the tails:
mixElements([H1|L1],[H2|L2],[H1,H2|Rest]) :-
!, mixElements(L1,L2,Rest).
mixElements(L1,L2,Rest) :- append(L1,L2,Rest).

Merge alternate elements from two lists in Prolog

I need to write a Prolog predicate mergealt(X,Y,Z) that succeeds if the list Z is a merger of alternate elements from the lists X and Y.
The input and output will like below:
?- mergealt([1,2,3,4],[6,7,8],Z).
Z = [1, 7, 3] .
?- mergealt([1,2,3,4],[6,7,8,9],Z).
Z = [1, 7, 3, 9] .
?- mergealt([1,2,3,4],[6,7,8,9,10],Z).
Z = [1, 7, 3, 9] .
I don't really understand recursion. How can I get started on this problem?
Prolog can be considered the 'flagman' of declarative languages.
So try to describe your problem, top down:
mergealt(X, Y, Z) :-
'take first element from X and put it in Z',
'discard first element from Y',
'mergealt rest-of-X and rest-of-Y, but exchange them'.
First step can't be accomplished if there are no elements in X.
This fact highlights the recursion termination case. Originally, Prolog didn't used if then else, instead alternatives are stated as different rules:
mergealt([], _Y, []).
Here you can see that pattern matching on first argument it's the key to distinguish alternatives, and contextually, Z get bound to an empty list. Y is unused, so it's marked as anonymus place holder, just to avoid a warning.
Then this simpler case suggests that we should use pattern matching to accomplish those verbose descriptions. See if you can complete the procedure with these guidelines:
mergealt([X|Xs], Y, [X|Zs]) :-
% take first element from X and put it in Z : done in the head
% discard first element from Y : see below
% mergealt rest-of-X and rest-of-Y, but exchange them'. : make your recursive call
discard_first_element([_|Rest], Rest).
% why is this necessary? do you see where it fails if we don't specify this case?
discard_first_element([], []).
Notice that the result always starts with the first element of the first list.
This means that, if the first list is empty, you know the answer right away.
Also notice that, if it isn't empty, we already know the first item of the result, so we need to use mergealt to compute the rest. But "the rest" will have the second item of the second list as the first item of the result, and as we said above, that means that a call to mergealt to compute it would have to have that be the first item of the first list (yeah, this is the tricky part).

Prolog list adding

--the question has been edited--
Using this data, I need to create a list:
team(milan,1).
team(napoli,2).
team(lazio,3).
team(roma,4).
team(inter,4).
team(juventus,5).
So, given a query like:
check([milan,lazio,roma,inter]).
make a new list with their respective team number.
X=[1,3,4,4]
What I'm trying to do is creating a list, adding elements one at a time.
check([H|T]) :-
team(H,R),
append([R],_, X),
check(T).
Could someone help me complete this?
You need to find all the team numbers for which the name of the team is a member of the list of team names that you are interested in:
?- findall(Number, (
team(Name, Number),
member(Name, [milan, lazio, roma, inter])), Numbers).
Numbers = [1, 3, 4, 4].
To return the numbers in a given order, just apply member/2 before team/2, in this case member/2 generates names (in the given order), and team/2 maps them to numbers:
?- findall(Number, (
member(Name, [lazio, milan, inter]),
team(Name, Number)), Numbers).
Numbers = [3, 1, 4].
A lot of time since I used Prolog but an answer -more or less- would look like:
check([]) :- true.
check([X]) :- team(X,_).
check([X,Y]) :- team(X,N), team(Y,M), N < M.
check([X,Y|T]) :- check(X,Y), check([Y|T]).
See this question for a very similar problem.
From what you say you might be better off making a list and then sorting it. That way you'd know the list is in order. Of course it's tricky in that you are sorting on the team ranks, not the alphabetic order of their names.
But the question you asked is how to check the list is in sorted order, so let's do it.
check([ ]). % just in case an empty list is supplied
check([_]). % singleton lists are also in sort order
check([H1,H2|T]) :-
team(H1,R1),
team(H2,R2),
R1 <= R2,
check([H2|T]).
Note that the recursion reduces lists with at least two items by one, so the usual termination case will be getting down to a list of length one. That's the only tricky part of this check.
Added in response to comment/question edit:
Sure, it's good to learn a variety of simple "design patterns" when you are getting going with Prolog. In this case we want to "apply" a function to each item of a list and build a new list that contains the images.
mapTeamRank([ ],[ ]). % image of empty list is empty
mapTeamRank([H|T],[R|S]) :-
team(H,R),
mapTeamRank(T,S).
So now you have a predicate that will turn a list of teams LT into the corresponding list of ranks LR, and you can "check" this for sorted order by calling msort(LR,LR):
check(LT) :-
mapTeamRank(LT,LR),
msort(LR,LR).