Prolog: fill list with n elements - prolog

Need to make a predicate, fill(L,X,N), where L is a list formed containing N elements X. If N <= 0 or N != length of L, L should be an empty list.
Here's what I've done, I've never been able to get the if, else.. structure working correctly in Prolog:
fill(L,X,N) :-
((N =< 0) ->
L = [];
length(L,I),
((N =\+= I) ->
L = [];
fill2(L,X,N))).
fill2([H|T],X,N2) :-
NewN = N2 - 1,
H = X,
fill2(T,X,NewN).
I also have a simpler version, that works except when N != length of L
fill(L,_,N) :-
N =< 0,
L = [].
fill([H|T],X,N) :-
NewN = N - 1,
H = X,
fill(T,X,NewN).
So, for example, fill(L,20,4) returns L = [20,20,20,20], but fill([20,20,20],X,2) doesn't return L = [].

You are misunderstanding how Prolog is meant to be used. Predicates are not exactly functions, so they can't return. If you bind an argument to an instantiated variable:
?- fill([a,a,a], a, 4).
fail
the only sensible thing is that Prolog tells you, "this is not correct". Anyway, in this example:
?- fill([b,b], a, 3).
What should happen? Should the list be [a,a,a], or should the second and third argument be b and 2?
A very simple fill:
fill([], _, 0).
fill([X|Xs], X, N) :- succ(N0, N), fill(Xs, X, N0).
It will fail if not used properly, but you should make clear how it needs to be used.
A note: try to avoid explicit unification in the body of the predicate definition.

Related

Generate all permutation of N (N - given) respecting the property: for every 2<=i<=n exists a 1<=j<=i, so |v(i)-v(j)|=1 in Prolog

Generate all permutation of N (N - given) respecting the property: for every 2<=i<=n exists a 1<=j<=i,
so |v(i)-v(j)|=1. I have found a solution building the list of the first N numbers(it is built reversed), reversing it, testing for every number if the condition is met, applying that for every number on a possible permutation found using the candidate predicate. Here is the code that works so far:
% candidate returns each number from the list and the list without it
% candidate(L - list, R - integer, L1 - list)
% flow(i,o,o)
% candidate(l1...ln)= - l1,l2...ln
% - (e,l1 U L), (e,L) = candidate(l2...ln)
candidate([H|T],H,T).
candidate([H|T],R,[H|T1]):-candidate(T,R,T1).
%build(N - integer, L - list)
%flow(i,o)
%build(l1...ln,n) = - [], n = 0 or 1
% - build(l2...ln,n-1), n>1
build(0,[]).
build(1,[]).
build(N1,[N|L]) :- N1 > 1, N is N1 - 1, build(N,L).
%reverse(L - input list, Z - list, R - list)
%flow(i,o,i)
%reverse(l1...ln) = - [], list is empty
% - l1 U reverse(l2...ln)
reverse([],Z,Z).
reverse([H|T],Z,Acc) :- reverse(T,Z,[H|Acc]).
%buildReverse(N - integer, R - list)
%flow(i,o)
buildReverse(N1,R):-build(N1+1,R1),reverse(R1,R,[]).
%checks whether the condition in the requirement
%nrTest(L - list, R - int, I - int)
%nrTest(i,i,o)
%nrTest(l1...ln,r,i) = - false, l1 = r, i = 1
% - true, abs(l1-r)= 1, list length is 1
% - true, abs(l1-r)= 1
% - nrTest(l2...ln,r,1)
% - nrTest(l2...ln,r,1), i = 0, l1 = r
nrTest([],0,_).
nrTest([R|T],R,0):-nrTest(T,R,1).
nrTest([R|_T],R,1):-!,fail.
nrTest([H],R,_):-1 is abs(H-R),true,!.
nrTest([H|_T],R,_):-1 is abs(H-R),true,!.
nrTest([_H|T],R,_I):-nrTest(T,R,1).
% checks if for every element of the list the condition in the
% requirement is met
% test2(L - list, R - list)
% flow(i,i)
% test2(l1...ln,r1...rn) = - false, lists are empty
% - true, first list is empty
% - true, lists have one element each
% - test2(l2...ln,r1...rn), if
% nrTest(r1...rn,l1,0)
test2([],[]):-false.
test2([],_):-true.
test2([_],[_]):-true.
test2([H|T],R):-nrTest(R,H,0),test2(T,R),!.
%wrapper for test2
%test2Wrap(R - list)
%flow(i)
test2Wrap([]):-false.
test2Wrap([_]):-true.
test2Wrap(R):-test2(R,R).
%perm2(L - list, R - list)
%flow(i,o)
%perm2(l1...ln,r1...rn) = - [], list is empty
% - perm2(candidate(l1...ln,r1),r2...rn),
% otherwise
perm2([],[]).
perm2(L,[E|T]):-candidate(L,E,R),perm2(R,T).
%perm3(L - list, R - list)
%flow(i,o)
%perm3(l1...ln,r1...rn) = - perm3(l1...ln,r1...rn), test2Wrap(r1...rn)
perm3(L,R):-perm2(L,R),test2Wrap(R).
%wrapper(N - int, R - list)
%flow(i,o)
wrapper(0,[]).
wrapper(N,R):-buildReverse(N,R1),perm3(R1,R).
I am curious to see if there are any simpler methods for doing that, as it seems I've complicated it more than I should have.
Well, let's compare to the SWI-Prolog implementation of permutation/2 (click the :- button to see the source. There's a bunch of type checking and then it resolves to a call to this predicate:
perm([], []).
perm(List, [First|Perm]) :-
select(First, List, Rest),
perm(Rest, Perm).
This doesn't look much different from yours; let's see if select/3 and candidate/3 are comparable:
select(X, [Head|Tail], Rest) :-
select3_(Tail, Head, X, Rest).
select3_(Tail, Head, Head, Tail).
select3_([Head2|Tail], Head, X, [Head|Rest]) :-
select3_(Tail, Head2, X, Rest).
So the documentation suggests that the use of select3_/3 here is really about making the predicate deterministic on the last element. Indeed, this is a small distinction between candidate/3 and select/3, apart from the order of parameters:
?- candidate([a,b,c], X, Y).
X = a,
Y = [b, c] ;
X = b,
Y = [a, c] ;
X = c,
Y = [a, b] ;
false.
?- select(X, [a,b,c], Y).
X = a,
Y = [b, c] ;
X = b,
Y = [a, c] ;
X = c,
Y = [a, b].
No trailing false here.
There is a build-in reverse/2, so there's no need for you to code that. There is not a built-in predicate to give you lists of length N of integers. I would have coded that slightly differently without using reverse/2, like this:
iota(N, L) :- iota(1, N, L).
iota(N, N, [N]).
iota(N0, N, [N0|NL]) :-
N0 < N,
succ(N0, N1),
iota(N1, N, NL).
Past this, we get into your wrapper/2, perm3/2, test2/2, nrTest/3 predicates, and I don't really understand what you're trying to do there. But I don't think there's anything intrinsically terrible about your permutation generator, you just need to utilize the library routines where they exist (remove candidate/3 and use select/3, use the supplied reverse/2 if really necessary).
Prolog is very high level, but it is not very terse. Prolog code of excellent quality can be shorter than comparable procedural code, but (in my experience) this has to do with the variety of calling conventions available to you and relational thinking, because the language by itself just isn't that short. I wrote about this on my blog with an example from another question.

Changing output of Prolog from a list to individual values

I want to alter the following code so that genN(3,R) outputs:
R=0.
R=1.
R=2.
Instead of a list R=[0,1,2]. How would I go about completing this?
genN(0,[]).
genN(N,R) :-
N > 0,
N1 is N-1,
genN(N1,R1),
append(R1,[N1],R),
!.
Use genN/2 and member/2 in conjunction, like this:
?- genN(3,Rs), member(R,Rs).
Rs = [0,1,2], R = 0 ;
Rs = [0,1,2], R = 1 ;
Rs = [0,1,2], R = 2.
You can do :
gen(N, R) :-
gen_one(N, 0, R).
gen_one(N, V, R) :-
N > V,
( R = V; V1 is V+1, gen_one(N,V1,R)).
from0_upto(N, R) :-
succ(N0, N),
between(0, N0, R).
Consider that it is not trivial (not impossible either) to write your own version of between/3 that behaves well in all corner cases. There are several attempts at this here on Stackoverflow, as well as an implementation in Prolog here: http://www.cs.otago.ac.nz/staffpriv/ok/pllib.htm (search for the string "between/3".
The Bottom Line
If you need a list, generate a list. If you need solution upon backtracking, generate solutions upon backtracking.

how to pass a list in a predicate in prolog

I want to store a paragram as a list in a variable and then call that list for counting how many times a particular word appears in that paragraph.
However, when I do this:
L = [hello,hello,hello].
counthowmany(_, [], 0) :- !.
counthowmany(X, [X|Q], N) :- !, counthowmany(X, Q, N1), N is N1+1.
counthowmany(X, [_|Q], N) :- counthowmany(X, Q, N).
... and compile buffer, and then ask this:
counthowmany(hello,L,N).
The number of "hello" occurrences in the list doesn't show, instead I receive a warning:
singleton variable:[X]
The line in a prolog file:
L = [hello,hello,hello].
Means to prolog:
=(L, [hello,hello,hello]).
Which means you're attempting to define a predicate, =/2. So not only will you get a singleton warning about L (since L isn't used anywhere else in this predicate definition), but you'll also see an error about an attempt to re-define the built-in =/2 since prolog already has it defined.
What you can do instead is:
my_list([hello,hello,hello]).
Then later on, you can do:
my_list(L), counthowmany(hello,L,N).
Note that this case works:
L = [hello,hello,hello], counthowmany(hello,L,N).
It works because it's not attempting to re-define =/2. It is just using the existing built-in predicate =/2.
You do
?- X = [hello,how,are,you,hello,hello], counthowmany(hello, X, N).
X = [hello, how, are, you, hello, hello],
N = 3.
First you first bind X ans then you ask for this specific X.
Example 2.
?- counthowmany(hello, X, N).
X = [],
N = 0.

Prolog count list elements higher than n

I'm kinda new to Prolog so I have a few problems with a certain task. The task is to write a tail recursive predicate count_elems(List,N,Count) condition List_Element > N, Count1 is Count+1.
My approach:
count_elems( L, N, Count ) :-
count_elems(L,N,0).
count_elems( [H|T], N, Count ) :-
H > N ,
Count1 is Count+1 ,
count_elems(T,N,Count1).
count_elems( [H|T], N, Count ) :-
count_elems(T,N,Count).
Error-Msg:
ERROR: toplevel: Undefined procedure: count_elems/3 (DWIM could not correct goal)
I'm not quite sure where the problem is. thx for any help :)
If you want to make a tail-recursive version of your code, you need (as CapelliC points out) an extra parameter to act as an accumulator. You can see the issue in your first clause:
count_elems(L, N, Count) :- count_elems(L,N,0).
Here, Count is a singleton variable, not instantiated anywhere. Your recursive call to count_elems starts count at 0, but there's no longer a variable to be instantiated with the total. So, you need:
count_elems(L, N, Count) :-
count_elems(L, N, 0, Count).
Then declare the count_elem/4 clauses:
count_elems([H|T], N, Acc, Count) :-
H > N, % count this element if it's > N
Acc1 is Acc + 1, % increment the accumulator
count_elems(T, N, Acc1, Count). % check the rest of the list
count_elems([H|T], N, Acc, Count) :-
H =< N, % don't count this element if it's <= N
count_elems(T, N, Acc, Count). % check rest of list (w/out incrementing acc)
count_elems([], _, Count, Count). % At the end, instantiate total with accumulator
You can also use an "if-else" structure for count_elems/4:
count_elems([H|T], N, Acc, Count) :-
(H > N
-> Acc1 is Acc + 1
; Acc1 = Acc
),
count_elems(T, N, Acc1, Count).
count_elems([], _, Count, Count).
Also as CapelliC pointed out, your stated error message is probably due to not reading in your prolog source file.
Preserve logical-purity with clpfd!
Here's how:
:- use_module(library(clpfd)).
count_elems([],_,0).
count_elems([X|Xs],Z,Count) :-
X #=< Z,
count_elems(Xs,Z,Count).
count_elems([X|Xs],Z,Count) :-
X #> Z,
Count #= Count0 + 1,
count_elems(Xs,Z,Count0).
Let's have a look at how versatile count_elems/3 is:
?- count_elems([1,2,3,4,5,4,3,2],2,Count).
Count = 5 ; % leaves useless choicepoint behind
false.
?- count_elems([1,2,3,4,5,4,3,2],X,3).
X = 3 ;
false.
?- count_elems([1,2,3,4,5,4,3,2],X,Count).
Count = 0, X in 5..sup ;
Count = 1, X = 4 ;
Count = 3, X = Count ;
Count = 5, X = 2 ;
Count = 7, X = 1 ;
Count = 8, X in inf..0 .
Edit 2015-05-05
We could also use meta-predicate
tcount/3, in combination with a reified version of (#<)/2:
#<(X,Y,Truth) :- integer(X), integer(Y), !, ( X<Y -> Truth=true ; Truth=false ).
#<(X,Y,true) :- X #< Y.
#<(X,Y,false) :- X #>= Y.
Let's run above queries again!
?- tcount(#<(2),[1,2,3,4,5,4,3,2],Count).
Count = 5. % succeeds deterministically
?- tcount(#<(X),[1,2,3,4,5,4,3,2],3).
X = 3 ;
false.
?- tcount(#<(X),[1,2,3,4,5,4,3,2],Count).
Count = 8, X in inf..0 ;
Count = 7, X = 1 ;
Count = 5, X = 2 ;
Count = 3, X = Count ;
Count = 1, X = 4 ;
Count = 0, X in 5..sup .
A note regarding efficiency:
count_elems([1,2,3,4,5,4,3,2],2,Count) left a useless choicepoint behind.
tcount(#<(2),[1,2,3,4,5,4,3,2],Count) succeeded deterministically.
Seems you didn't consult your source file.
When you will fix this (you could save these rules in a file count_elems.pl, then issue a ?- consult(count_elems).), you'll face the actual problem that Count it's a singleton in first rule, indicating that you must pass the counter down to actual tail recursive clauses, and unify it with the accumulator (the Count that gets updated to Count1) when the list' visit is done.
You'll end with 3 count_elems/4 clauses. Don't forget the base case:
count_elems([],_,C,C).

What does this wildcard do in this prolog scenario?

I've come across this code:
connectRow(_,_,0).
connectRow([spot(_,R,_,_)|Spots],R,K) :- K1 is K-1, connectRow(Spots,R,K1).
/*c*/
connectRows([]).
connectRows(Spots) :-
connectRow(Spots,_,9),
skip(Spots,9,Spots1),
connectRows(Spots1).
How does the wildcard in the connectRow(Spots,_,9) work? How does it know which values to check and how does it know that it checked all the possible values?
Edit: I think I understand why this works but I'd like it if someone could verify this for me:
When I "call" the connectRow with the wildcard it matches the wildcard with the "R" in the connectRow predicate. Could this be it?
The _ is just like any other variable, except that each one you see is treated as a different variable and Prolog won't show you what it unifies with. There's no special behavior there; if it confuses you about the behavior, just invent a completely new variable and put it in there to see what it does.
Let's talk about how Prolog deals with variables. Here's an experiment you can follow along with that should undermine unhelpful preconceived notions if you happen to have them.
?- length([2,17,4], X)
X = 3.
A lot of Prolog looks like this and it's easy to fall into the trap of thinking that there are designated "out" variables that work like return values and designated "in" variables that work like parameters. After all:
?- length([2,17,4], 3).
true.
?- length([2,17,4], 5).
false.
Here we begin to see that something interesting is happening. A faulty intuition would be that Prolog is somehow keeping track of the input and output variables and "checking" in this case. That's not what's happening though, because unification is more general than that. Observe:
?- length(X, 3).
X = [_G2184, _G2187, _G2190].
We've now turned the traditional parameter/return value on its head: Prolog knows that X is a list three items long, but doesn't know what the items actually are. Believe it or not, this technique is frequently used to generate variables when you know how many you need but you don't need to have them individually named.
?- length(X, Y).
X = [],
Y = 0 ;
X = [_G2196],
Y = 1 ;
X = [_G2196, _G2199],
Y = 2 ;
X = [_G2196, _G2199, _G2202],
Y = 3
It happens that the definition of length is very general and Prolog can use it to generate lists along with their lengths. This kind of behavior is part of what makes Prolog so good at "generate and test" solutions. You define your problem logically and Prolog should be able to generate logically sound values to test.
All of this variation springs from a pretty simple definition of length:
length([], 0).
length([_|Rest], N1) :-
length(Rest, N0),
succ(N0, N1).
The key is to not read this like a procedure for calculating length but instead to see it as a logical relation between lists and numbers. The definition is inductive, relating the empty list to 0 and a list with some items to 1 + the length of the remainder of the list. The engine that makes this work is called unification.
In the first case, length([2,17,4], X), the value [17,4] is unified with Rest, N0 with 2 and N1 with 3. The process is recursive. In the final case, X is unified with [] and Y with 0, which leads naturally to the next case where we have some item and Y is 1, and the fact that the variable representing the item in the list doesn't have anything in particular to unify with doesn't matter because the value of that variable is never used.
Looking at your problem we see the same sort of recursive structure. The predicates are quite complex, so let's take them in pieces.
connectRow(_, _, 0).
This says connectRow(X, Y, 0) is true, regardless of X and Y. This is the base case.
connectRow([spot(_, R, _, _)|Spots], R, K) :-
This rule is matching a list of spots of a particular structure, presuming the first spot's second value (R) matches the second parameter.
K1 is K-1, connectRow(Spots, R, K1).
The body of this clause is essentially recurring on decrementing K, the third parameter.
It's clear now that this is basically going to generate a list that looks like [spot(_, R, _, _), spot(_, R, _, _), ... spot(_, R, _, _)] with length = K and no particular values in the other three positions for spot. And indeed that's what we see when we test it:
?- connectRow(X, Y, 0).
true ;
(infinite loop)^CAction (h for help) ? abort
% Execution Aborted
?- connectRow(X, Y, 2).
X = [spot(_G906, Y, _G908, _G909), spot(_G914, Y, _G916, _G917)|_G912] ;
(infinite loop)^CAction (h for help) ? abort
So there seem to be a few bugs here; if I were sure these were the whole story I would say:
The base case should use the empty list rather than matching anything
We should stipulate in the inductive case that K > 0
We should use clpfd if we want to be able to generate all possibilities
Making the changes we get slightly different behavior:
:- use_module(library(clpfd)).
connectRow([], _, 0).
connectRow([spot(_, R, _, _)|Spots], R, K) :-
K #> 0, K1 #= K-1, connectRow(Spots, R, K1).
?- connectRow(X, Y, 0).
X = [] ;
false.
?- connectRow(X, Y, 1).
X = [spot(_G906, Y, _G908, _G909)] ;
false.
?- connectRow(X, Y, Z).
X = [],
Z = 0 ;
X = [spot(_G918, Y, _G920, _G921)],
Z = 1 ;
X = [spot(_G918, Y, _G920, _G921), spot(_G1218, Y, _G1220, _G1221)],
Z = 2
You'll note that in the result we have Y standing in our spot structures, but we have weird looking automatically generated variables in the other positions, such as _G918. As it happens, we could use _ instead of Y and see a similar effect:
?- connectRow(X, _, Z).
X = [],
Z = 0 ;
X = [spot(_G1269, _G1184, _G1271, _G1272)],
Z = 1 ;
X = [spot(_G1269, _G1184, _G1271, _G1272), spot(_G1561, _G1184, _G1563, _G1564)],
Z = 2
All of these strange looking variables are there because we used _. Note that all of the spot structures have the exact same generated variable in the second position, because Prolog was told it had to unify the second parameter of connectRow with the second position of spot. It's true everywhere because R is "passed along" to the next call to connectRow, recursively.
Hopefully this helps explain what's going on with the _ in your example, and also Prolog unification in general.
Edit: Unifying something with R
To answer your question below, you can unify R with a value directly, or by binding it to a variable and using the variable. For instance, we can bind it directly:
?- connectRow(X, 'Hello, world!', 2).
X = [spot(_G275, 'Hello, world!', _G277, _G278), spot(_G289, 'Hello, world!', _G291, _G292)]
We can also bind it and then assign it later:
?- connectRow(X, R, 2), R='Neato'.
X = [spot(_G21, 'Neato', _G23, _G24), spot(_G29, 'Neato', _G31, _G32)],
R = 'Neato'
There's nothing special about saying R=<foo>; it unifies both sides of the expression, but both sides can be expressions rather than variables:
?- V = [2,3], [X,Y,Z] = [1|V].
V = [2, 3],
X = 1,
Y = 2,
Z = 3.
So you can use R in another predicate just as well:
?- connectRow(X, R, 2), append([1,2], [3,4], R).
X = [spot(_G33, [1, 2, 3, 4], _G35, _G36), spot(_G41, [1, 2, 3, 4], _G43, _G44)],
R = [1, 2, 3, 4] ;
Note that this creates opportunities for backtracking and generating other solutions. For instance:
?- connectRow(X, R, 2), length(R, _).
X = [spot(_G22, [], _G24, _G25), spot(_G30, [], _G32, _G33)],
R = [] ;
X = [spot(_G22, [_G35], _G24, _G25), spot(_G30, [_G35], _G32, _G33)],
R = [_G35] ;
X = [spot(_G22, [_G35, _G38], _G24, _G25), spot(_G30, [_G35, _G38], _G32, _G33)],
R = [_G35, _G38] ;
Hope this helps!

Resources