Prolog - Appending to list recursively - prolog

I wrote this function where I have as a parameter a set of coordinates and I want to create a new list with all the coordinates to the left of them (so basically X-1) but at the end it doesn't ask me if the option given is correct, it just prints yes.
Here is the code:
all_valid_moves([], L):-
write('------------------------'),
nl,
write(L),
nl,
write('------------------------'),
nl,
!.
all_valid_moves([Head|Tail], All_Valid):-
nth0(0, Head, X),
nth0(1, Head, Y),
NewX is X - 1,
append([[NewX, Y]], All_Valid, New_All_Valid),
write(All_Valid),
nl,
all_valid_moves(Tail, New_All_Valid).
Test case all_valid_moves([[1,1],[2,2],[3,3]], X)..
Should return [[0,1],[1,2],[2,3]].
If anyone can point out the mistake(s) I made, please do so!
Thanks alot for your time,
Have a good one

Final answer
I added a new variable to the function so I could return it in a new list, this was the final result:
all_valid_moves(Board, [], L, New):-
New = L.
all_valid_moves(Board, [Head|Tail], Previous, All_Valid):-
nth0(0, Head, X),
nth0(1, Head, Y),
NewX is X - 1,
append([[NewX, Y]], All_Valid, New_All_Valid),
all_valid_moves(Board, Tail, New_Prev3, New_All_Valid),
All_Valid = New_All_Valid.

Simplify, simplify, simplify. No need for nth0/3. No need for append/3. Just this:
all_valid_moves( [] , [] ) .
all_valid_moves( [[X,Y]|As] , [[X1,Y]|Bs] ) :- X1 is X-1, all_valid_moves(As,Bs).

Related

Prolog - Deleting Nth Row From A Matrix

I'm trying to create a query elimrow(_, [H|T], X) that deletes the nth row in a matrix array.
Sample:
?- elimrow(-3,[[1,2],[3,4],[5,6]], X). => X = [[1,2],[3,4],[5,6]]
?- elimrow(2,[[1,2],[3,4],[5,6]], X). => X = [[1,2],[5,6]]
So far I was able to create this:
elimrow(1, [H|_], H).
elimrow(I, [H|T], X) :-
I1 is I-1, elimrow(I1, T, X), delete(X, [H|T], B), writeln(B).
delete(A, [A|B], B).
delete(A, [B, C|D], [B|E]) :- delete(A, [C|D], E).
This is currently able to select the row which I want to delete. However the delete function isn't functioning fully as expected.
?- elimrow(2,[[1,2],[3,4],[5,6]],X).
[[1,2],[5,6]]
X = [3, 4]
It outputs the correct deleted array [[1,2], [5,6]], however it also outputs a X = [3,4]
I'm confused as to why there was a second output. (I only had one writeln(B)).
I also tried checking it with my first sample and it returned with false when it's not supposed to delete anything.
?- elimrow(-3, [[1,2],[3,4],[5,6]],X).
false.
Appreciate any help on this. Many thanks!
I think you make it too complicated. Your matrix is just a list of lists. So you can delete the I-th element of a list:
eliminate(_, [], []).
eliminate(0, [_|T], T).
eliminate(I, [H|T], [H|R]) :-
I > 0,
I1 is I-1,
eliminate(I1, T, R).

Find minimum of various predicates

I want to find the minimum value of all permutations called from main predicate. For simplicity, I have removed my entire code, assume that I just want to find the minimum of head elements of all permutations.
appendlist([], X, X).
appendlist([T|H], X, [T|L]) :- appendlist(H, X, L).
permutation([], []).
permutation([X], [X]) :-!.
permutation([T|H], X) :- permutation(H, H1), appendlist(L1, L2, H1), appendlist(L1, [T], X1), appendlist(X1, L2, X).
%min(X, A, B) X is the minimum of A, B
min(X, X, Y) :- X =< Y.
min(Y, X, Y) :- Y < X.
solve([Head|Rest], Head):-
writeln([Head|Rest]).
main :-
Sort = [1, 2, 3],
PrvAns is 1000,
permutation(Sort, X),
solve(X, Here),
min(Ans, Here, PrvAns),
writeln(Ans),
PrvAns = Ans,
!, fail;
true,
writeln(PrvAns).
I want to calculate the minimum on fly for each permutation. Now, permute is working fine, and you can see that solve prints all permutations and even returns the first value Head properly, but PrvAns = Ans is wrong.
Expected output PrvAns : 1
I'm sorry if I didn't understand properly (and tell me, so I can help you), but, you mean something like this?
findMinHead(X,Z):-
findall( Y, ( permutation(X,[Y|_]) ), Z1 ),
min_list(Z1,Z).
in this predicate we find all the Y values where Y is the head of a permutation of X, put all that values in a bag, and then find the min.

Inserting X in its correct position in a sorted list

In prolog how do I insert X in its correct position in a sorted list?
My Attempt:
insert(X,[Y|Rest],[X,Y|Rest]):-
X #< Y;
insert(X,Rest,BiggerRest).
You're on the right track, but you need to make this three cases.
insert(X, [], [X]).
insert(X, [Y|Rest], [X,Y|Rest]) :-
X #< Y, !.
insert(X, [Y|Rest0], [Y|Rest]) :-
insert(X, Rest0, Rest).

Prolog: Remove all elements from lister higher than X

I am trying to write a prolog program that will remove all elements in a list higher than the value X.
For example, I want to remove all elements higher than 50 from this list:
[2,8,18,34,40,44,46,51,52,54,64,66,76,90]
So I get:
[2,8,18,34,40,44,46]
It would be nice to see how far you've gotten. What is giving you problems?
The idea in most of these problems usually goes something like this:
Construct a base case, usually empty lists.
Try to recurse to the bottom of the recursion and on the way,
only keep the desired elements. Here, keeping means that you recurse
with the unwanted elemements removed.
For it to "grow back together" properly, as in, when the recursion
goes back up, you have to properly define the output list.
There are really two ways to this. Either remove elements when going down, or ignore them when going back up. These are in essence the same.
I'm not the best at explaining this. I will simply post my solution. But I strongly suggest you give it your best before looking at it. :)
delete_gt([], _, []) :- !.
delete_gt([Head|Rest], X, L) :-
Head > X, !,
delete_gt(Rest, X, L).
delete_gt([Head|Rest], X, [Head|L]) :-
delete_gt(Rest, X, L).
Using accumulator
removeHigherThan( X, List, Ans) :-
removeHigherThan( X, List, Ans, [] ), !.
removeHigherThan( _, [], Ans, Ans).
removeHigherThan( X, [H | Tail], Ans, Acc ) :-
(
( H > X, NewEl = [] )
;
( H =< X, NewEl = [H] )
),
append( Acc, NewEl, NewAcc ),
removeHigherThan( X, Tail, Ans, NewAcc).
It works like that
?- removeHigherThan(10, [1,4], X).
X = [1, 4].
?- removeHigherThan(10, [1,12,4], X).
X = [1, 4].
You could also consider this utility from apply library
del_elems_higher :-
exclude(condition, [2,8,18,34,40,44,46,51,52,54,64,66,76,90], L), writeln(L).
condition(X) :- X > 50.
test:
?- del_elems_higher.
[2,8,18,34,40,44,46]

What do results like Z = [_G305] mean in prolog?

I've got these definitions:
memberx(X, [X|_]).
memberx(X, [_|T]) :- memberx(X, T).
intersectionx([], _, []).
intersectionx([H|T], Y, [_|Z]) :- memberx(H, Y), !, intersectionx(T, Y, Z).
intersectionx([_|T], Y, Z) :- intersectionx(T, Y, Z).
I get the following result:
?- intersectionx([1], [1], Z).
Z = [_G305].
Why doesn't it result in Z = [1]??
Z = [_G305].
means that this answer is true for all terms. That is, it is not
only true for Z = [1] - as you expect, but it is also true for Z = [2].
Clearly, that is not what you expected.
So where is the error? A simple way to detect it is to watch out for anonymous
variables denoted _.
Consider:
intersectionx([H|T], Y, [_|Z]) :- memberx(H, Y), !, intersectionx(T, Y, Z).
^^^
What you have written means that the intersection of a list starting with
H and another list will be (provided the goals on the right hand side
are all true) a list starting with anything... Replace anything by that H!

Resources