How to connect a button to a function in xpce/prolog - user-interface

This is a button:
new(B,button(solve, message(#prolog, solve))),
send(D,display,B),
send(D, open),
This is a function:
solve(D, Row, Column) :-
assert(path([[0, 0], [-1, 0]])),
track(Row, Column),
path(P),
show_track(D,P).
How should I do?

Here goes a sample to get you started:
:- use_module(library(pce)).
test:-
new(D, dialog),
new(W, window('Test', size(100, 100))),
send(D, append, new(B,button(solve, message(#prolog, solve, D, 10, 20)))),
send(D, below, W),
send(D, open),
!.
solve(D, Row, Column) :-
writeln(solve(D, Row, Column)).
Basically you have to add the arguments to the message, in this case I used D for the dialog and the constants 10 and 20 for Row and Column, and just print them to console in the solve/3 procedure.

Related

How do I fix the following error in my prolog code for the queen problem

I can't figure out why my code isn't working. I want the code to give me possible combinations for N queens on a NxN chessboard. A possible combination would be e.g. [2, 4, 1, 3] for a 4x4 chessboard. Each digit represent the colume the queen is being placed and as we go through the list we go row by row until we reach the last one. So "2" would be place in the first row in colume 2, "4" would be placed in the second row in colume 4 and so on.
When I use the function n_queens it gives me
the follwing error:
ERROR: Arguments are not sufficiently instantiated
The code:
initliste(M,N,[M|Ns]) :- M < N, M1 is M+1, initliste(M1,N,Ns).
initliste(N,N,[N]).
safe([]).
safe([Q|Qs]) :-
\+attack(Q, Qs),
safe(Qs).
attack(X, [Y|Ys]) :-
X =\= Y,
abs(X-Y) =\= L,
L is length([Y|Ys]),
attack(X, Ys).
attack(_, []).
n_queens(N, L) :-
initliste(1,N,Board),
permutation(Board, L),
safe(L).
You try to compare L (in abs(X-Y) =\= L) before binding a value to L (as you do in L is length([Y|Ys])).

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).

Swi-prolog, need help defining my conditions

So I have a project, and I'm trying to create a predicate which has 3 different cases, which I will explain.
swapandp(L, P, Content, L) :-
refP(L, P, Content), !.
This is the first case where refP gives me the content of the list L on the position P, and if the content is equal to Content, it returns true and stops right there, because if the content is the same, I don't need to change anything in L.
swapandp(L, P, [Content], NewL) :-
swap(L, P, Content, NewL1),
relatedPs(P, Ps),
delNum(Content, NewL1, Ps, NewL).
This is the second case where, if Content is a one-element list, then it puts Content in the P position of the list L, and then uses a predicate i created to delete the same content in the positions related to P, which are put into a list Ps by another predicate relatedPs.
swapandp(L, P, Content, NewL) :-
swap(L, P, Content, NewL).
This is the third case where if Content is a list with more then 1 element, then it just puts Content into the position P of the list L.
but something is wrong. Because I'm probably not defining the 3 cases correctly, sorry for my english and thanks for helping.
EDIT 1:
Been trying out some things and now the first and third case are working so my problem is not the 2nd one.
I tried this:
?- swapandp([[[1,2], [1,2], [3], [1,4,5], [1,4]]], (1,1), [1], NewL).
NewL = [[[1], [1, 2], [3], [1, 4, 5], [1, 4]]].
but the expected result should be:
NewL = [[[1], [2], [3], [4, 5], [4]]].
cant figure it out.
EDIT 2:
refP(L, (Plin, Pcol), Content) :-
nth1(Plin,L,Line),
nth1(Pcol,Line,Content).
applyActionToL(L,_,[],L) :- !.
applyActionToL(Puz,Action,[P | R],N_Puz) :-
Action =.. Lst_Action,
append(Lst_Action, [L,P,Res],Actionwithargs),
Lit =.. Actionwithargs,
call(Lit),
applyActionToL(Res,Action,R,NewL).
But applyActionToL and refP were defined by my teacher so, i guess its working.
delNumAux(N, L, P, NewL) :-
refP(Puz, Pos, Content),
subtract(Content, Num, Content1),
swapandp(L, P, Content1, NewL).
delNum(N, L, Ps, NewL) :-
applyActionToL(L, delNumAux(Num), Ps, NewL).
Edit 3:
I ended up being able to fix it myself! Thanks anyway guys!
a wild guess:
swapandpropagate(L, P, [Content], OutL) :-
swap(L, P, Content, NewL),
relatedPs(P, Ps),
delNum(Content, NewL, Ps, OutL).

Prolog BattleShips bombing game

So i'm programming a battleship game in prolog. The game has 5x5 board where ships should be located with similar logic to real game, which means they can't be side by side and touch each other at all.
So i've came across these problems.
How to make the code recognize which board Tiles(cordinates) have been already shot?
How can i programmatically recognize ships as a whole and how to use this knowledge to recognize when the ship has sank.
Currently the prompt loop will end after first hit, but goal is to end the loop when all ships are sank.
EDIT: Board contains 2 values 0 and 1, 0 is empty Tile, 1 represents that it has an ship part on it.
board([[0, 0, 0, 0, 0],
[1, 1, 0, 0, 0],
[0, 0, 0, 0, 0],
[1, 1, 1, 1, 0],
[0, 0, 0, 0, 0]]).
row_at(X, Row) :-
board(Board),
nth0(X, Board, Row).
column_at(Y, Row, Cell) :-
nth0(Y, Row, Cell).
ship_at(X, Y) :-
row_at(X, Row),
column_at(Y, Row, Cell),
Cell = 1.
hit:-
write('hit!'), nl.
miss :-
write('miss!'), nl.
target(X, Y, State) :-
(ship_at(X, Y) ->
hit, asserta(X,Y);
miss).
prompt_number(Prompt, Number) :-
write(Prompt),
write(': '),
read(Number).
:- initialization(main).
main :-
repeat,
prompt_number('enter column number', Col),
prompt_number('enter row number', Row),
target(Row, Col, State),
(ship_at(Row, Col) ->
write('you won!'), nl, halt ;
write('keep trying!'), nl, fail).

Prolog Queue of Tuples/Pairs using List without Duplicates

I am attempting to implement a queue of tuples/pairs for use with an AI in SWI-Prolog. The goal is to first fill the structure with data and then evaluate each element. Each unique (X, Y) pair should be evaluated only once.
Currently, the problem is that my implementation is not a queue but a stack. The function dequeue is also evaluating to false prematurely. Here is a simplified portion of the code I am working with.
:- dynamic([queue/1, destination/2]).
enqueue(X, Y):-
retract(queue(List)),
\+member((X, Y), List),
assert(queue([(X, Y)|List])).
enqueue(_,_).
dequeue:-
retract(queue([(X, Y)|List])),
retractall(destination(_, _)),
assert(queue(List)),
assert(destination(X, Y)).
.........................Actual Code Below.............................
add_to_list_of_dest(X, Y):-
retract(list_of_dest(Stuff)),
\+member((X, Y), Stuff),
assert(list_of_dest([(X, Y)|Stuff])),
format("List of Dest Added : (~d, ", X),
format("~d)~n", Y).
add_to_list_of_dest(X, Y):-
format("Duplicate Element Not Added : (~d, ", X),
format("~d)~n", Y).
choose_destination:-
current_pos(X, Y),
destination(DestX, DestY),
\+(X = DestX),
\+(Y = DestY),
format("Choosing Desination : Currently Travelling~n").
choose_destination:-
retract(list_of_dest([(X, Y)|Stuff])),
retractall(destination(_, _)),
assert(list_of_dest(Stuff)),
assert(destination(X, Y)),
format("Choosing Desination : (~d, ", X),
format("~d)~n", Y).
#ChristianF's answer is fine (+1), though appending to the end of a list will become burdensome for large queues. A well-known alternative uses two stacks. Doing so gives you O(1) insertion and amortized O(1) popping. The trick is having an input stack and an output stack. Assuming the output stack is in the right order, you just return the top item when it's non-empty to pop. If it is empty, take the input stack and reverse it onto the output stack.
% empty_queue(-Queue) is det.
empty_queue(queue([], [])).
% enqueue(+Item, +Queue, -NewQueue) is det.
enqueue(Item, queue(InStack, OutStack), queue([Item|InStack], OutStack)).
% dequeue(+Queue, -Item, -NewQueue) is det.
% Handle the case where the output stack is ready to be used.
dequeue(queue(InStack, [Top|OutStack]), Top, queue(InStack, OutStack)).
% Handle the case where the input and output stacks must be swapped.
dequeue(queue(InStack, []), Top, OutStack) :-
reverse(InStack, NewOutStack),
dequeue(queue([], NewOutStack), Top, OutStack).
You can take advantage of Prolog's non-determinism to make a single predicate with both calling conventions. This makes it work more similarly to append/3:
% queue(+Item, +QueueWithoutItem, -QueueWithItem) is det.
queue(Item, QueueWithoutItem, QueueWithItem) :-
nonvar(Item), nonvar(QueueWithoutItem),
enqueue(Item, QueueWithoutItem, QueueWithItem).
% queue(-Item, -QueueWithoutItem, +QueueWithItem) is semidet.
queue(Item, QueueWithoutItem, QueueWithItem) :-
nonvar(QueueWithItem),
dequeue(QueueWithItem, Item, QueueWithoutItem).
Making a queue is really not hard if you know lists:
%% enqueue(+Queue, +Element, -NewQueue)
enqueue(L, E, L2) :- append(L, [E], L2).
%% dequeue(+Queue, -Element, -NewQueue)
dequeue([H|T], H, T).
Example use:
?- enqueue([], (2,3), L), enqueue(L, (4,5), L2), dequeue(L2, _Ignore, L3).
L = [ (2, 3)],
L2 = [ (2, 3), (4, 5)],
_Ignore = (2, 3),
L3 = [ (4, 5)].
You can use difference_list, wich append in O(1) :
init_queue(U-U).
en_queue(Q, Elem, New_Q) :-
append_dl(Q, [Elem|U]-U, New_Q).
de_queue([H|T]-U, H, T-U).
check_queue(Elem, Q) :-
Q = A-[],
member(Elem, A).
append_dl(A-B, B-C, A-C).

Resources