So i created counting sort(https://en.wikipedia.org/wiki/Counting_sort) program in Prolog using ECLiPSe 6.1. It sorts fine, but it can only write sorted list in console instead of returning it as second variable. So how to make it return sorted list as variable?
For example:
mysort([1,1,6,7,4,1.5,11,6,7],Z)
is writing ([7, 7, 6, 6, 4, 1, 1]) in console, which is correct answer (it sorts numbers from 0 to 10).But variable Z is Z=Z, instead of Z=([7, 7, 6, 6, 4, 1, 1])
build(_,0,[]). %create list with ARG1 value , ARG2 size, and write to ARG3
build(X,N1,[X|L]) :- N1 > 0, N is N1 - 1, build(X,N,L).
build(X,N1,[X]):- N1>0, N1 is N - 1, build(X,N,[]).
build_list(X,N):-build(0,N,X).%create list with ARG1 value , ARG2 size, and write to ARG3
sum_list([], 0).% ARG1 list sum, write to ARG2
sum_list([H|T], Sum) :-
sum_list(T, Rest),
Sum is H + Rest.
replace([_|T], 0, X, [X|T]).%replace in ARG1 list, ARG2 index with ARG3 value,return as ARG4
replace([H|T], I, X, [H|R]):- I > -1, NI is I-1, replace(T, NI, X, R), !.
replace(L, _, _, L).
increment_nth_in_list( [] , [],_ ) .%Increment element in ARG1, return as ARG2, increment element on ARG3 position
increment_nth_in_list( [X|Xs] , [Y|Ys],N) :-
(N=0->Y is X+1,N1 is N-1;
N1 is N-1,Y is X),
increment_nth_in_list(Xs,Ys,N1).
decrement_nth_in_list( [] , [],_ ) .%Decrement element in ARG1, return as ARG2, Decrement element on ARG3 position
decrement_nth_in_list( [X|Xs] , [Y|Ys],N) :-
(N=0->Y is X-1,N1 is N-1;
N1 is N-1,Y is X),
decrement_nth_in_list(Xs,Ys,N1).
mysort([],[]).
mysort([_],[]).
mysort(Sorting,Sorted):-%Starting sort
build_list(Amounts_of,10),%create list from 0 to 10 (MAX)
count_numbers(Sorting,Amounts_of).%starting to count numbers
count_numbers([Sortinghead|Sortingtail],Amount_of):-%counting numbers from ARG1 and writing to ARG2
increment_nth_in_list(Amount_of,NewAmount,Sortinghead),
length(Sortingtail,Z),
(Z>0->count_numbers(Sortingtail,NewAmount);
sum_list(NewAmount,Sum),build_list(Sorted,Sum),length(Sorted,L),fill_list(NewAmount,Sorted,0,L)
).
fill_list([],A,_,_):-write(A).
fill_list([Amount_of_Head|[]],[Sorted],N,L).
fill_list([Amount_of_Head|Amount_of_Tail],Sorted,N,L):-%Filling ARG2 based on values in ARG1,with ARG3 values on ARG4 position.
Amount_of_Head>0- >decrement_nth_in_list([Amount_of_Head|Amount_of_Tail],NewAmount,0),L1 is L- 1,replace(Sorted,L1,N,NewSorted),fill_list(NewAmount,NewSorted,N,L1)
;N1 is N+1,fill_list(Amount_of_Tail,Sorted,N1,L).
The second argument Z in your call corresponds to the variable Sorted in the last clause of mysort/2. But that clause never uses that variable, so it can never be bound to the solution. You will have to add arguments to fill_list/4 and count_numbers/2 that you bind to the solution when you are done, at the same point where you now do a write. (You might be able to reuse existing arguments; your code is badly formatted and your variable names do not help understand it.)
Related
This recursion should slice IL to IR out of the list Lin and hand result LOut...
slice(_,IL,IR,LOut) :-
IR<IL,
[LOut].
slice(Lin,IL,IR,LOut) :-
nth0(IL,Lin,X),
append(LOut,[X],LOut2),
IK is IL + 1,
slice(Lin,IK,IR,LOut2).
Input / Output:
?- slice([1,2,3,4],2,3,X).
ERROR: source_sink `'3'' does not exist
ERROR: source_sink `'4'' does not exist
X = [] .
I m also new to Prolog, but I think this recursion must somehow work. Also I'm not really known to the error codes in Prolog, but after checking multiple times I just have to give up... I hope you guys can help me.
slice(_,IL,IR,LOut) :-
IR<IL,
[LOut]. % <-- this line causes source_sink error.
That syntax [name] tries to load the file name.pl as Prolog source code. By the time your code gets there, LOut is [3,4] so it tries to load the files 3.pl and 4.pl, and they don't exist (thankfully, or else who knows what they could do).
I think this recursion must somehow work
It won't; you are appending to a list as you go down into the recursion, which means you will never see the result.
The following might be a close version which works, at least one way:
slice(_,IL,IR,[]) :-
IR < IL.
slice(Lin,IL,IR,[X|LOut]) :-
IR >= IL,
nth0(IL,Lin,X),
IK is IL + 1,
slice(Lin,IK,IR,LOut).
?- slice([0,1,2,3,4,5,6,7,8,9], 2, 5, X).
X = [2, 3, 4, 5]
See how [X|LOut] in the second rule's header puts X in the result that you get, and append/3 is not needed, and LOut finishes down in the recursion eventually as [] the empty list from the first rule, and all the X's are prepended on the front of it to make the result on the way down into the recursion, which is tail recursion, so it doesn't need to go back up, only forward, since there's nothing left to be done after the recursive call.
Since the "cons" is done before the recursion, this is known as "tail recursion modulo cons" in other languages, but in Prolog it is just tail, and the list is being built top-down on the way forward, as opposed to being built bottom up on the way back:
Lin=[0,1,2,3,4,5,6,7,8,9], slice( Lin, 2, 5, R)
:-
nth0(2,Lin,X2), R=[X2|R2], slice( Lin, 3, 5, R2)
:-
nth0(3,Lin,X3), R2=[X3|R3], slice( Lin, 4, 5, R3)
:-
nth0(4,Lin,X4), R3=[X4|R4], slice( Lin, 5, 5, R4)
:-
nth0(5,Lin,X5), R4=[X5|R5], slice( Lin, 6, 5, R5)
:-
R5 = [].
I think findall/3 provides a readable readable solution for your problem:
slice(Lin,IL,IR,LOut) :-
findall(E,(nth0(P,Lin,E),between(IL,IR,P)),LOut).
yields
?- slice([1,2,3,4],2,3,X).
X = [3, 4].
If you expect a different outcome, use standard arithmetic comparison operators (=<,>=) instead of between/3.
I think you want:
list_elems_slice(Start, End, Lst, Slice) :-
list_elems_slice_(Lst, 1, Start, End, Slice).
list_elems_slice_([H|T], N, N, End, [H|Slice]) :-
list_elems_slice_capture_(T, N, End, Slice).
list_elems_slice_([_|T], N, Start, End, Slice) :-
N1 is N + 1,
list_elems_slice_(T, N1, Start, End, Slice).
list_elems_slice_capture_(_, N, N, []).
list_elems_slice_capture_([H|T], N, End, [H|Slice]) :-
N1 is N + 1,
list_elems_slice_capture_(T, N1, End, Slice).
Result in swi-prolog:
?- list_elems_slice(S, E, [a,b,c], Slice).
S = E, E = 1,
Slice = [a] ;
S = 1,
E = 2,
Slice = [a, b] ;
S = 1,
E = 3,
Slice = [a, b, c] ;
S = E, E = 2,
Slice = [b] ;
S = 2,
E = 3,
Slice = [b, c] ;
S = E, E = 3,
Slice = [c] ;
false.
Assuming that the point of this exercise is to teach you to think recursively, I would approach the problem as follows.
To get what you want is essentially two separate operations:
You first must discard some number of items from the beginning of the list, and then
Take some number of items from what's left over
That gives us discard/3:
discard( Xs , 0 , Xs ) .
discard( [_|Xs] , N , Ys ) :- N > 0 , N1 is N-1, discard(Xs,N1,Ys) .
and take/3, very nearly the same operation:
take( _ , 0 , [] ) .
take( [X|Xs] , N , [Y|Ys] ) :- N > 0 , N1 is N-1, take(Xs,N1,Ys) .
Once you have those two simple predicates, slice/4 itself is pretty trivial:
%
% slice( List , Left, Right, Sublist )
%
slice( Xs, L, R, Ys ) :- % to slice a list,
L =< R, % - the left offset must first be less than or equal to the right offset
N is R-L, % - compute the number of items required, and then
discard(Xs,L,X1), % - discard the first L items, and
take(X1,N,Ys). % - take the next N items
. % Easy!
Another approach would be to use append/3:
slice( Xs , L, R, Ys ) :-
length(Pfx,L), % - construct of list of the length to be discarded
append(Pfx,Sfx,Xs), % - use append to split Xs
N is R-L, % - compute the number of items required
length(Ys,N), % - ensure Ys is the required length
append(Ys,_,Sfx) % - use append to split off Ys
. % Easy!
I just start learning Prolog and find it's hard to handle list related problem.
If I have a list. Inside this list, I have three inner lists.
[[a,b,c], [d,e,f],[h,g]]
I need to write a predicate called "move(L, X, From, To, R)" where X is the character I want to move (this character has to be the last element in the inner list), From is the index of list I want to move from, To is the index of list I want to move to. e.g.
move([[a,b,c], [d,e,f],[h,g]], f, 2, 3, R).
returns
R = [[a,b,c], [d,e],[h,g,f]]
One more example:
move([[a,b,c], [d,e,f],[h,g]], f, 2, 1, R).
returns
R = [[a,b,c,f], [d,e],[h,g]]
I wrote a helper predicates to determine if a character is the last element in the list:
last([A], C):- A == C.
last([_|T], C):- last_one(T, C).
I spent a few hours thinking about it, but no working solutions. Any help please?
I think you must prove the following:
move(L, X, From, To, R) is the predicate you want run, so the #1 argument is a list of list (in the sample: L = [[a,b,c], [d,e,f],[h,g]] ); the #3 and #4 arguments are members of L, so you can use the predicate nth1(N, L, E), where N is the order of the element, L is the list and E the Element; each element is another list, and now you must delete the X from the list From and add it to the list To.
For it, first you can use the predicate 'select/3'; for the second, you can use 'append/3'.
I tried the folowwing rules, but it give me a different order of the main list:
move(L, X, F, T, R) :-
nth1(F, L, Lf),
nth1(T, L, Lt),
select(X, Lf, Rf),
append(Lt, [X], Rt),
select(Lf, L, Ra),
select(Lt, Ra, Rb),
append(Rb, [Rf], Rc),
append(Rc, [Rt], R).
with this code, you obtain the following:
move([[a,b,c], [d,e,f],[h,g]], f, 2, 3, R).
R = [[a,b,c], [d,e],[h,g,f]]
but:
move([[a,b,c], [d,e,f],[h,g]], f, 2, 1, R).
R = [[h,g], [d,e], [a,b,c,f]]
Basically I want to remove the first N numbers from a list, the function that checks whether a number is prime or not seems to work well but the program itself doesn't
For example for input [2,4,5,7,6,9,11] and N = 3 I should get [4, 6, 9, 11] but I get only [4, 6, 9].
divisible(X,Y) :-
0 is X mod Y, !.
divisible(X,Y) :-
X > Y+1,
divisible(X, Y+1).
%isPrime function check whether or not the argument is a prime number
isPrime(2) :- true,!.
isPrime(X) :- X < 2,!,false.
isPrime(X) :- not(divisible(X, 2)).
%delFunction (input_list, N, output_list)
delFunction([],_,_).
delFunction(_,0,_).
delFunction([H|T], N, [H|Res]):-
not(isPrime(H)), !,
delFunction(T, N, Res).
delFunction([_|T], N, Res):-
N1 is N-1,
delFunction(T,N1,Res).
delFunction([2,4,5,7,6,9,11],3,X) -> [4,6,9] (which is not the correct answer)
Honestly, I don't know where I went wrong, the implementation idea seems pretty easy and straight forward, so is the code.
Also, when I run it it stops at [4] and I have to keep on clicking next to get me to the end of the execution (thus the result). Any idea how to fix it? I'm thinking maybe I need some cuts but not sure where.
P.S: I'd rather not use built-in functions (if there are any that would help in this scenario)
Fists of all, instead of
delFunction([],_,_).
you should write
delFunction([],_,[]).
because when the input list (the left one) is empty, you have to construct the base for the output list: an empty list; with delFunction([], _, _) you don't unify the output list with the empty list so the result end with an not unified variable.
Second. Instead of
delFunction(_,0,_).
you should write
delFunction(L,0,L).
The problem is the same: when number is zero you can "copy" the input in the output; that is, you can unify they; that is delFunction(L,0,L). With delFunction(_,0,_) you don't unify and the result ends with a not unified variable.
Third. In the is-prime clause
delFunction([_|T], N, Res):-
N1 is N-1,
delFunction(T,N1,Res).
you should check that N is greater than zero
delFunction([_|T], N, Res):-
N > 0,
N1 is N-1,
delFunction(T,N1,Res).
or, if you prefer, you should add a cut (!) in the zero clause
delFunction(L,0,L) :- !.
Just to avoid that Prolog, via backtracking, can give multiple undesired answers.
--- EDIT ---
As Guy Coder, I avoid cuts like a plague; so I propose the following solution to avoid unwanted repetitions.
delFunction([], _, []).
delFunction([H | T], 0, [H | T]).
delFunction([H | T], N, [H | Res]) :-
N > 0,
not(isPrime(H)),
delFunction(T, N, Res).
delFunction([H | T], N, Res):-
N > 0,
isPrime(H),
N1 is N-1,
delFunction(T, N1, Res).
I made a function which calculates a list length. Below is my code.
listLength(LIST) :- solve(LIST, LENGTH), write(LENGTH).
solve([], _).
solve([_|T], LENGTH) :- ADD is LENGTH + 1, solve(T, ADD).
When I run this code with input
?- listLength([1, 2, 3, 4, 5, 6, 7]).
then, interpreter showed me error message solve/2 : Arguments are not sufficiently instantiated.
when I modified above code like below.
listLength(LIST) :- LENGTH is 0, solve(LIST, LENGTH), write(LENGTH).
solve([], _).
solve([_|T], LENGTH) :- ADD is LENGTH + 1, solve(T, ADD).
When I run this code with the same input, then always 0 is written.
I want to calculate LENGTH, and I want to use the variable in listLength function.
What's wrong with me? ( Please kindly note that I am using swi-prolog. )
The first mistake is in the base case. Instead of solve([], _). you should write solve([], 0). because if you don't know the length of empty list how will you find recursively for bigger lists.
There is also another issue in :
solve([_|T], LENGTH) :- ADD is LENGTH + 1, solve(T, ADD).
when trying to calculate ADD is LENGTH + 1 length is not instantiated-calculated. You need to change the order like:
listLength(LIST) :- solve(LIST, LENGTH), write(LENGTH).
solve([], 0).
solve([_|T], LENGTH) :- solve(T, ADD), LENGTH is ADD+ 1.
Now querying:
?- listLength([1, 2, 3, 4, 5, 6, 7]).
7
true.
I want to create a list consisting of N elements.
I write the following code:
DOMAINS
list = integer*
PREDICATES
create(integer, integer, list)
CLAUSES
create(_, 0, []).
create(Start, End, [Start|T]):-
Start < End + 1,!,
Counter = Start + 1,
create(Counter, End, T).
GOAL
create(1, 5, L).
But it returns me No Solution.
On the other hand if I change the direction of my Counter like this:
DOMAINS
list = integer*
PREDICATES
create(integer,list)
CLAUSES
create(0,[]).
create(N,[N|T]):-
N > 0,
NN = N - 1,
create(NN,T).
GOAL
create(5,L).
It returns me 1 Solution: L=[5,4,3,2,1]. It's working good, but not in the order.
What wrong in my first variant of code?
You need to make some adjustments to your program:
The stop clause is never unified, because you don't decrement the
End term.
Counter need to be evaluated to the expression Start + 1, so use the is/2 operator.
You don't need the cut on the second clause, but on the first one.
Program:
create(X, X, [X]):- !.
create(Start, End, [Start|T]):-
Start =\= End,
Counter is Start + 1,
create(Counter, End, T).
Consult(You need the list to be instantiated, so use a variable instead of the empty list)
?- create(1,5, L).
L = [1, 2, 3, 4, 5].
In the first variant the base case is wrong:
create(_, 0, []).
Here the End argument is 0, but your non-base rule is never modifying the End, it is running on Start.
So your base case should match whenever Start is equal to the End:
create(E, E, []).