creating list of an elemente multipled n times - list

So my problem is this, i have a predicate which is repete_el(El,N,L) in which El is an element, N is the number of times is repeated and L is the list contaning that element repeated N times.
My problem is that istead of repeating the element its giving false and i dont understand why.
Example:
My output:
?- repete_el(a,3,L).
false
Correct output:
?- repete_el(a,3,L).
L = [a,a,a].
Program:
repete_el(El,0,[]) :- !.
repete_el(El,N,L) :- repete_el(El,N,L,[],N).
repete_el(El,N,L,L2) :- length(L2,C),
C =< N,
append(L2,[N],NL),
repete_el(El,N,L,NL).
By the way, i can only do this iteratively.

You can use the standard findall/3 predicate and the de facto standard between/3 predicate. For example:
| ?- findall(a, between(1,5,_), List).
List = [a, a, a, a, a]
yes

The reason this will not work is because at the moment you call repete_el/4, L2 is a free variable, so length(L2, C) will start building all sorts of lists with lengths. Then you make a recursive call on a list NL with one element extra, and you require that list to have again length C (which should again be smaller than N). But eventually C will be larger than N, and thus the predicate will fail.
You can write such predicate as:
repete_el(_, 0, []). %% (1)
repete_el(X, N, [X|T]) :- %% (2)
N > 0,
N1 is N-1,
repete_el(X, N1, T).
Here we thus say:
(1) A list where we repeat an element 0 times is an empty list; and
(2) a list where we repeat X, N times, with N greater than 0 is a list that starts with X and ends with a list where we repeat X, N-1 times.

Related

Counting elements in list ignoring adjacent duplicates

count([], 0).
count(L, N) :- countDistinct(L, 0).
countDistinct([H,H1|T], N) :-
(H == H1,
countDistinct([H1|T], N));
(H =\= H1, N1 is N+1,
countDistinct([H1|T], N1)).
My approach was to obviously have the trivial base case, and then call a new predicate countDistinct with the initial N as being 0. Then, N is incremented only if the adjacent elements are distinct.
Is my idea of calling countDistinct like this wrong? How should I adapt it.
Since you are trying to solve this with recursion this answer will take that approach. Also this answer will only cover the mode of a list being bound and count being unbound and will not use cuts to remove choice points. You can
enhance the code if desired.
When creating recursive predicates for list I typically start with a template like:
process_list([H|T],R) :-
process_item(H,R),
process_list(T,R).
process_list([],R).
with the recursive case:
process_list([H|T],R) :-
process_item(H,R),
process_list(T,R).
and the base case:
process_list([],R).
The list is deconstructed using [H|T] where H is for head of list and T is for tail of list. R is for result.
The head item is processed using:
process_item(H,R)
and the tail of the list is processed using:
process_list(T,R)
Since this requires processing two adjacent items in the list modifications are needed:
process_list([H1,H2|T],R) :-
process_item(H1,H2,R),
process_list([H2|T],R).
process_list([],0).
process_list([_],1).
NB There are now two base cases instead of one. Just because recursive predicates are typically one recursion clause and one base case clause does not mean they are always one recursive clause and one base case clause.
Next update the process_item
process_item(I1,I1,N,N).
process_item(I1,I2,N0,N) :-
I1 \== I2,
N is N0 + 1.
Since is/2 is used to increment the count, a count state needs to be passed in, updated and passed out, thus the variables, N0 and N.
When using state variable or threaded variables, the naming convention is to append 0 to the input value, have no number appended to the output value and increment the appended number in the same clause as the threading progresses.
When the items are the same the count is not incremented which is done using:
process_item(I1,I1,N,N).
When the items are different the count is incremented which is done using:
process_item(I1,I2,N0,N) :-
I1 \== I2,
N is N0 + 1.
In the process of changing process_item, R became N0 and N so this requires a change to process_list
process_list([H1,H2|T],N0,N) :-
process_item(H1,H2,N0,N1),
process_list([H2|T],N1,N).
and to use this a helper predicate is added so that the signature of the original predicate can stay the same.
count(L,N) :-
process_list(L,0,N).
The full code
count(L,N) :-
process_list(L,0,N).
process_list([H1,H2|T],N0,N) :-
process_item(H1,H2,N0,N1),
process_list([H2|T],N1,N).
process_list([],N,N).
process_list([_],N0,N) :-
N is N0 + 1.
process_item(I1,I1,N,N).
process_item(I1,I2,N0,N) :-
I1 \== I2,
N is N0 + 1.
Test cases
:- begin_tests(count).
test(1,[nondet]) :-
count([],N),
assertion( N == 0 ).
test(2,[nondet]) :-
count([a],N),
assertion( N == 1 ).
test(3,[nondet]) :-
count([a,a],N),
assertion( N == 1 ).
test(4,[nondet]) :-
count([a,b],N),
assertion( N == 2 ).
test(5,[nondet]) :-
count([b,a],N),
assertion( N == 2 ).
test(6,[nondet]) :-
count([a,a,b],N),
assertion( N == 2 ).
test(7,[nondet]) :-
count([a,b,a],N),
assertion( N == 3 ).
test(8,[nondet]) :-
count([b,a,a],N),
assertion( N == 2 ).
:- end_tests(count).
Example run
?- run_tests.
% PL-Unit: count ........ done
% All 8 tests passed
true.
Solution using DCG
% Uses DCG Semicontext
lookahead(C),[C] -->
[C].
% empty list
% No lookahead needed because last item in list.
count_dcg(N,N) --> [].
% single item in list
% No lookahead needed because only one in list.
count_dcg(N0,N) -->
[_],
\+ [_],
{ N is N0 + 1 }.
% Lookahead needed because two items in list and
% only want to remove first item.
count_dcg(N0,N) -->
[C1],
lookahead(C2),
{ C1 == C2 },
count_dcg(N0,N).
% Lookahead needed because two items in list and
% only want to remove first item.
count_dcg(N0,N) -->
[C1],
lookahead(C2),
{
C1 \== C2,
N1 is N0 + 1
},
count_dcg(N1,N).
count(L,N) :-
DCG = count_dcg(0,N),
phrase(DCG,L).
Example run:
?- run_tests.
% PL-Unit: count ........ done
% All 8 tests passed
true.
Better solution using DCG.
Side note
In your example code is the use of the ;/2
A typical convention when forammting code with ;/2 is to format as such
(
;
)
so that the ; stands out.
Your code reformatted
countDistinct([H,H1|T], N) :-
(
(
H == H1,
countDistinct([H1|T], N)
)
;
(
H =\= H1,
N1 is N+1,
countDistinct([H1|T], N1)
)
).

Iterating over list elements in turns in prolog

I have this predicate repeat/3 which I need to construct. It is supposed to repeat all the elements in a list n amount of times. For example:
?- repeat([a,b,a,a,c],2,X).
Would produce
X = [a, a, b, b, a, a, a, a, c, c].
The current code I have written for it is the following:
repeat([],_,[]).
repeat(_,0,[]).
repeat([A],Int,[A|X]):- Int1 is Int-1, repeat([A],Int1,X).
repeat(A,1,A).
repeat([A|Tail],Int,[A|X]):- Int1 is Int-1, repeat([A|Tail],Int1,X).
It will return:
1) An empty list upon giving it an empty list.
2) An empty list upon giving it the number 0 as an argument.
3) One letter n amount of times.
4) The given list one time.
Now, the issue I'm having with is the final line of code.
5) What this line will do for me currently is return all the elements in a list after repeating the first element n amount of times.
Example:
?- repeat([a,b,b,c],3,X).
X = [a, a, a, b, b, c]
I figure the solution is for me to go through the list and for every element repeat it n amount of times but I do not have any clue as to how to do it.
One idea which I attempted was to have the number I pass into the predicate turn into the original upon reaching 1 and then continue the predicate using the tail:
repeat([],_,[]).
repeat(_,0,[]).
repeat([A],Int,[A|X]):- Int1 is Int-1, repeat([A],Int1,X).
repeat([A|Tail],1,[A|X]):- repeat(Tail,Int,X). % The line where I made a change.
repeat([A|Tail],Int,[A|X]):- Int1 is Int-1, repeat([A|Tail],Int1,X).
This did not work out. I do now know whether I am on the right track for this or not. Any help would be appreciated.
Although there are definitely some other issues as well, the most important issue is that you decrement N until it hits zero to repeat the first element. But after it hits zero, of course you do no longer can obtain the original N.
So how can we store the original N? We can simply introduce a new predicate repeat/4, with:
repeat(L, N, LN) :-
repeat(L, N, N, LN).
So we redirect repeat/3 to repeat/4 by copying N. The idea is that we will decrement only one of the parameters. From the moment that parameter hits zero, we will "reset" the parameter, by fetching the value from the second N (which we do not decrement).
So now we only need to work out repeat/4. In case we reached the end of the list, then - regardless of the value of N - the repetition is an empty list:
repeat([], _, _, []).
in case the first N has reached zero, we proceed to the next element of the list, and reset that N:
repeat([_|T], 0, N, LN) :-
repeat(T, N, N, LN).
and finally in case we did not yet hit zero, we of course prepend the result with the head of the first list:
repeat([H|T], A, N, [H|LN]) :-
A > 0,
A1 is A-1,
repeat([H|T], A1, N, LN).
If we put it all together, we obtain:
repeat(L, N, LN) :-
repeat(L, N, N, LN).
repeat([], _, _, []).
repeat([_|T], 0, N, LN) :-
repeat(T, N, N, LN).
repeat([H|T], A, N, [H|LN]) :-
A > 0,
A1 is A-1,
repeat([H|T], A1, N, LN).

Prolog - creating cumulative duplicates in a list?

I have a list L given and my task is to create cumulative duplicates, depending on how many I want.
I have the list [a,b,c,d] for example and want the first element to be duplicated 4 times (optional), then every subsequent element has to be duplicated like the previous one + 1.
Let's assume my predicate is called list_copy(L,N,R), the result with L = [a,b,c,d] and K = 2 should be:
?- list_copy([a,b,c,d],2,R).
R = [a,a,b,b,b,c,c,c,c,d,d,d,d,d]
I've managed to create a universal code for duplicating a list two times:
dupl([],[]).
dupl([O|U],[O,O|U1]) :- dupl(U,U1).
Depending on how many O's I put in my second line I get that many duplicates.
My question is, though: How can I implement a 3rd variable as a cumulative counter, in order to get the desired outcome?
When you have to "count" stuff one by one, consider using succ/2. It has the nice property that it works both ways, and fails when you call it with succ(X, 0).
So first, the predicate that does "cumulative duplicates":
cum_dup([], _, []).
cum_dup([X|Xs], N, Ys) :-
repeat_n(X, N, Ys, Back),
succ(N, N1),
cum_dup(Xs, N1, Back).
This uses the predicate repeat_n/4, which takes an elements, a non-negative integer, and repeats the element. It leaves a "hole" in the back of the list that you can fill with the rest of the result using cum_dup/3. Here is a straight-forward implementation of repeat_n/4:
repeat_n(_, 0, L, L).
repeat_n(X, N, [X|Xs], Rest) :-
succ(N0, N),
repeat_n(X, N0, Xs, Rest).
This will already give you the result you need:
?- cum_dup([a,b,c,d], 2, R).
R = [a, a, b, b, b, c, c, c, c, d, d, d, d, d] ;
false
It leaves behind a harmless choice point. There are too many ways to make a repeat_n/4 that does not leave unnecessary choice points:
use CLP(FD)
use a cut
use a conditional (if-then-else)
use a structure instead of an integer
Just one example:
repeat_n(X, N, L, Back) :-
length(Ns, N),
repeat_n_(Ns, X, L, Back).
repeat_n_([], _, L, L).
repeat_n_([_|Ns], X, [X|Xs], L) :-
repeat_n_(Ns, X, Xs, L).
Here, instead of counting with an integer, you (ab)use a list of that length.
I guess you can think about it yourself and ask another question if you really need to.
--- EDIT --- modified using succ/2, as suggested by Boris (thanks!).
I suppose you can use a helper clause. Like list_copy_h/4 in the following example
list_copy_h([], _, _, []).
list_copy_h([_ | Tin], 0, Num, Lout) :-
succ(Num, Np1),
list_copy_h(Tin, Np1, Np1, Lout).
list_copy_h([H | Tin], Count, Num, [H | Tout]) :-
succ(Cm1, Count),
list_copy_h([H | Tin], Cm1, Num, Tout).
list_copy(Lin, Num, Lout) :-
list_copy_h(Lin, Num, Num, Lout).
The idea is use a counter (the second argument) that decrease to zero. When zero, the head of the input list is discharged and the cycle begin again with the following element of the input list but increasing the starting value of the counter. The third argument is the starting value.

Prolog Recursion removing elements at index that is multiples of n from a list where n is any number

This is my first time asking a question here but I have a problem that I really can't wrap my head around which is Prolog recursion especially when it deals with list. So the task that I am supposed to solve is to write a drop predicate that works like this. For example, drop([1,2,3,4,5,6,7,8,9], 2, L) where L = [1,3,5,7,9] and N=n where elements at position n, 2n, 3n.... will be removed. The list starts from 1 is another thing to be noted.
Here is my attempt so far and thought process:
drop([], _, []).
indexOf([X|_], X, 1). %Using 1 because the question says the first element starts from 1.
indexOf([_|Ys], Y , I):-
indexOf(Ys, Y, N),
I is N + 1.
drop([X|Xs], Y, [X|_]) :-
indexOf([X|Xs] , X , A),
Z is A mod Y,
Z \== 0.
drop([X|Xs], Y, Zs) :-
%indexOf([X|Xs], X, A),
drop(Xs, Y, Zs).
I created an indexOf predicate to find the index of the elements starting from 1 . Next, my idea was to use the my first drop recursive case (in the code above it is the 5th case) to check and see whether the position of the element returns a remainder of zero when divided by the Y (second input). if it does not return a remainder of zero, then the X remains inside the list and is not dropped. Then, prolog moves on to the 2nd drop recursive case which can only be arrived when Z=0 and it will drop X from the list to return Zs. In essence, an element with index n, 2n, 3n... that is returned by indexOf will be dropped if it does not return a remainder of zero when divided by Y (second input).
I have not learnt Cut at this point of the course at the moment. I would appreciate if someone can point me to the right direction. I have been working on this for almost a day.
I am still trying to adapt the logic and declarative thinking in this programming paradigm. I would appreciate it if you could share with me, how did you personally go about mastering Logic programming?
First, looking at your approach, there's a flaw with using the indexOf/3. That is, at a given point in time when you need to know the index of what you're removing, you don't know what the item is yet until you get to it. At that point, the index is 1.
That's one issue with the following rule:
drop([X|Xs], Y, [X|_]) :-
indexOf([X|Xs], X, A),
Z is A mod Y,
Z \== 0.
The first subquery: indexOf([X|Xs], X, A) will succeed with A = 1 on its first attempt, just by definition (of course, X has index 1 in list [X|Xs]. As it succeeds, then the next line Z is A mod Y yields 1 since 1 mod Y is always 1 if Y > 0. And therefore, Z \== 0 will always succeed in this case.
Thus, you get the result: [X|_] where X is the first element of the list. So the first solution you get for, say, drop([1,2,3,4], 2, L). is L = [1|_]. Your third drop/3 predicate clause just recurses to the next element in the list, so then it will succeed the second clause the same way, yielding, L = [2|_], and so on...
Starting from the top, here's a way to think about a problem like this.
Auxiliary predicate
I know I want to remove every N-th element, so it helps to have a counter so that every time it gets to N I will ignore that element. This is done with an auxiliary predicate, drop/4 which will also have a recurring counter in addition to the original N:
drop(L, N, R) :-
drop(L, N, 1, R). % Start counter at 1
Base rule
If I drop any element from the empty list, I get the empty list. It doesn't matter what elements I drop. That's expressed as:
drop([], _, _, []).
You have this rule expressed correctly already. The above is the 4-argument version.
Recursive rule 1 - The N-th element
I have list [X|Xs] and X is the N-th element index, then the result is R if I skip X, reset my index counter to 1, and drop the N-th element from Xs:
drop([_|Xs], N, N, R) :- % I don't care what the element is; I drop it
drop(Xs, N, 1, R).
Recursive rule 2 - Other than the N-th element
I have list [X|Xs] and X is the A-th element (< N), then the result is [X|R] if I increment my index counter (A), and drop N-th elements from Xs with my updated index counter:
drop([X|Xs], N, A, [X|R]) :-
A < N,
NextA is A + 1,
drop(Xs, N, NextA, R).
Those are all the needed rules (4 of them).

Returning a list of primes in Prolog

I am trying to create a list that returns number primes until a N number.
I have this code that indicates if a number is prime:
is_prime(2).
is_prime(3).
is_prime(P) :- integer(P), P > 3, P mod 2 =\= 0, \+has_factor(P,3).
has_factor(N,L) :- N mod L =:= 0.
has_factor(N,L) :- L * L < N, L2 is L + 2, has_factor(N,L2).
that works very well.
My logic is: to test if N is prime, if so add N in a list, if doesn't just ignore and test to N-1. Here the code:
primeList(N,C):- is_prime(N) -> append(N,[C],L),fail; N1 is N-1, primeList(N1,L).
And it doesn't work! How could I fix this problem following my logic?
Thanks a lot.
Once a variable in Prolog is instantiated (has a value) in a predicate clause, it can't be reassigned. So you can't keep appending to the list L in primeList.
But you can use findall and between:
prime_list(N, C) :-
findall(X, (between(2,N,X), is_prime(X)), C).