I am trying to get a grid to show in prolog, rather than getting the listing of it.
Here is what I have so far
sB:-
showBoard.
showBoard(Row) :-
setof([Row,Col,Object,Visible],square(Row,Col,Object,Visible),RList),
showRow(RList),
writeln(''),
NextRow is Row - 1,
showBoard(NextRow).
This is something new that I am trying to test out to see if I can get this or not. Am I on the right track?
EDIT
For a task, we have to generate a grid through code,
Here is what I am trying to get....
I am using square/3, getting back square(x,y,object). But I hope to step it up to square/4, so I can bring in the visibility of the grid, meaning the robot can only see around him, one square left, right, up and down, until he finds his glasses.
== == == == == == == == == ==
|| x x x x x x x x ||
|| x x x x x x x x ||
|| x x x x x x x x ||
|| x x x x x x x x ||
|| x x x x x x x x ||
|| x x x x x x x x ||
|| x x x x x x x x ||
== == == == == == == == == ==
The easiest would be to "scan" your board left-to-right, top-to-bottom (as this is how we output to a console), and see if there is anything to be shown for this particular square. Assuming that you are using format for writing (easier to control the formatting of the output), and assuming that you know in advance the size of your board, and your x and y coordinates start at the top left corner, you need to:
for each row of the board:
for each position on the row
see if there is something to draw on that square, and draw it
Or, in code:
show_board(Rows, Cols) :-
show_rows(1, Rows, Cols).
show_rows(R, Rows, Cols) :-
( R =< Rows
-> show_row(R, 1, Cols),
R1 is R + 1,
show_rows(R1, Rows, Cols)
; true
).
show_row(R, C, Cols) :-
( C =< Cols
-> show_square(R, C) % or maybe show_square(C, R)?
C1 is C + 1,
show_row(R, C1, Cols)
; true
).
% show_square should always succeed!
show_square(R, C) :-
( square(R, C, Obj /* additional arguments? */)
-> draw(Obj /* additional arguments */)
; draw_not_visible
).
This could be a starting point. It could be done more "fancy" but this is a perfectly valid approach. Drawing an object depends on what your object is, and drawing the boundary around the grid is trivial.
Related
I've been given the following function written in pseudocode:
P:
{
int x, y, z;
read (x, y, z);
while (x != y) {
x = x - y;
z = z + y
};
write z;
}
Given that f(x,y,z) is the function calculated by P, I would like to know if the function "g(x,y,z)=1 if f(x,y,z) is not a total function or g(x,y,z)=0 otherwise", is computable.
My first guess is: yes, it is computable (for example for x=y).
Is there a more rigorous general approach to prove that?
P does not change the value of y, and the only way it changes the value of x is to subtract y from x until x = y. If subtracting y from x does not eventually result in x = y, then the loop continues forever. We know that subtracting y from x repeatedly can only cause x = y if initially x = cy for natural numbers c >= 1. So, g(x,y,z) = 1 because f(x,y,z) is not a total function; it is undefined when x != cy for any natural number c >= 1. Even if what you meant is that g(x,y,z) = 1 whenever f(x,y,z) is defined, it is still computable, since g(x,y,z) is the function:
g(x,y,z) = { 1, if x = cy for some natural number c >= 1 }
{ 0, otherwise }
The condition x = cy for some natural number c >= 1 is itself computable since this is equivalent to "x >= y" and "GCD(x, y) = y".
So I'm trying to find the direction that the blank tile in the 8 tile puzzle will be sliding,
I am using X/Y to determine the tiles.
Here's the code I have.
mandist( X /Y , X1 / Y1 , D, Direction):-
D is abs(X - X1 )+ abs(Y - Y1 ),
Y is Y1 ->(
( X is X1 +1 -> Direction ='left')
;
( X1 is X +1 -> Direction = 'right'))
; X is X1 ->(
( Y1 is Y +1 -> Direction ='up')
;
( Y is Y1 +1 -> Direction ='down')).
The problem I'm getting is that when calling the mandist predicate it isn't giving me the results I had hoped for.
I am sure the problem is with the if statement, I have wrote some psuedocode so you can understand what I'm trying to do,
if(Y == Y1){
// Change the X Axis
if(X == X1 +1){
This is a left move
}
else{
This is a right move
}
}else if (X == X1){
// Change the Y Axis
if(Y == Y1 + 1){
This is an up move
}
else{
This is a down move
}
}
Example:
move([1/1, 3/1, 1/3, 2/3, 3/3, 1/2, 2/2, 3/2,2,1], X, Direction)
This then calls the mandist predicate
With D set to 1, so it ensures its a legal move
Here is the unexpected result:
mandist(1/1, X,1, Direction).
Direction = up ;
false
I am also expecting it to say Direction = right because position 1/1 is the very bottom left of the 3x3 grid and the only moves from the bottom left are either up or right
1/3 2/3 3/3
1/2 2/2 3/2
1/1 2/1 3/1
Based on your question, you probably want to write the following clause:
mandist(X/Y,XD/Y,D,right) :-
XD is X+D.
mandist(X/Y,X/YD,D,up) :-
YD is Y+D.
mandist(X/Y,XD/Y,D,left) :-
XD is X-D.
mandist(X/Y,X/YD,D,down) :-
YD is Y-D.
Given you write this to the file, it will generate:
?- mandist(1/1,X,1,Direction).
X = 2/1,
Direction = right ;
X = 1/2,
Direction = up ;
X = 0/1,
Direction = left ;
X = 1/0,
Direction = down.
Furthermore it can validate whether two coordinates are located in a certain direction given D us instantiated:
?- mandist(1/1,1/2,1,Direction).
Direction = up ;
false.
However it will not work with:
?- mandist(1/1,1/2,D,Direction).
ERROR: is/2: Arguments are not sufficiently instantiated
There is however a way to do this. Please updated your question if that is a requirement.
EDIT:
Since there are bounds, you can simply add them to the clauses. If you can assume that the first pair of coordinates are valid, it is simply:
mandist(X/Y,XD/Y,D,right) :-
XD is X+D,
XD < 4.
mandist(X/Y,X/YD,D,up) :-
YD is Y+D,
YD < 4.
mandist(X/Y,XD/Y,D,left) :-
XD is X-D,
XD > 0.
mandist(X/Y,X/YD,D,down) :-
YD is Y-D,
YD > 0.
My aim is to take the numbers between X and Y and produce Z.
num_between(3,6, All)
For example, if X is 3 and Y is 6 then Z is a list of the numbers between X and Y inclusive. Something like num_between(3,6,[3,4,5,6]) should evaluate as true. Here's what I have so far:
num_between(0,0, []).
num_between(X,Y, All) :-
increase(X, New) , % increase number X++
\+(X = Y) , % check if X is not equal to Y
num_between(New,Y,[All|X]) . % requestion ???
increase(F,N) :- N is F+1 .
increase/1 is working and returns number that is required, but
when recursion is gone through num_between/3 it goes unlit: X is 6 then it fails as I want,
but I can not manage to keep numbers or to return them. All = [3,4,5,6].
All = All + F. Could anyone help please.
Your base clause is incorrect: since you never decrease X or Y, they would never get to zero (unless Y starts at zero, and X starts at a non-positive value). The base clause should look like this:
num_between(X, Y, []) :- X > Y.
This ensures that you get an empty result when the user enters an invalid "backward" range (say, from 6 to 3).
Now to the main clause: all you need to do is to check that the range is valid, get the next value, and make a recursive call, like this:
num_between(X, Y, [X|Tail]) :-
X =< Y,
Next is X + 1,
num_between(Next, Y, Tail).
Demo.
Your original code made an error when constructing a list - it tried to use X as the "tail" of the list, which is incorrect:
num_between(New,Y,[All|X]).
you pass on All, the result after an "expansion", down through the recursive chain of invocation. It should be the other way around - you need to pass in a Tail to collect the result, and then pre-pend X to it when the recursive invocation is over.
You have to change both your base case and your recursive clause:
num_between(X, X, [X]).
num_between(X, Y, [X|L]):-
X < Y,
increase(X, New),
num_between(New, Y, L).
First clause is the base case, it states that the number ranging from X and X is just [X].
The recursive clause states that a number X which is less than a number Y should have it in the output list (thus the [X|L] in the third argument of the head), then it increases the value (i'm just using your helper procedure for that) and recursively calling itself now with the New value for the first argument.
I would write this along these lines:
numbers_between( X , X , [X] ) . % if X and Y have converged, we have the empty list
numbers_between( X , Y , [X|Zs] ) :- % otherwise, add X to the result list
X < Y , % - assuming X is less than Y
X1 is X+1 , % - increment X
numbers_between(X1,Y,Zs) % - recurse down
. %
numbers_between( X , Y , [X|Zs] ) :- % otherwise, add X to the result list
X > Y , % - assuming X > Y
X1 is X-1 , % - decrement X
numbers_between(X1,Y,Zs) % - recurse down
. %
After receiving the needed help from phihag on my previous post, I noticed that I didn't have result for all even numbers. However, I keep receiving a syntax error at line 47 invalid syntax with else.
else: # x, y, and z are even
What could be the issue?
#!/usr/bin/env python
# This program exmamines variables x, y, and z
# and prints the largest odd number among them
import sys
x, y, z = map(int, sys.argv[1:4])
if x % 2 != 0:
if y % 2 != 0:
if z % 2 != 0:
if x > y and x > z: # x is the biggest odd
print 'x is the biggest odd ', x
elif y > z and y > x: # y is the biggest odd
print 'y is the biggest odd ', y
elif z > x and z > y: # z is the biggest odd
print 'z is the biggest odd ', z
else: # z is even
if x > y: # x is the biggest odd
print 'x is the biggest odd ', x
else: # y is the biggest odd
print 'y is the biggest odd ', y
else: # y is even
if z % 2 != 0: # z is odd
if x > z: # x is the biggest odd
print 'x is the biggest odd ', x
else: # z is the biggest odd
print 'z is the biggest odd ', z
else: # y,z are even and x is the biggest odd
print 'x is the biggest odd ', x
else: # x is even
if y % 2 != 0 and z % 2 != 0: # y,z is odd
if y > z: # y is the biggest odd
print 'y is the biggest odd ', y
else: # z is the biggest odd
print 'z is the biggest odd ', z
else: # x and y are even
if z % 2 != 0: # z is the biggest odd
print 'z is the biggest odd ', z
else: # x and z are even
if y % 2 != 0: # y is odd
if z % 2 == 0: # z is even
print 'y is the biggest odd ', y
else: # x, y, and z are even
if z % 2 == 0:
print 'x, y, and z are even.'
print 'finished'
You have two elses at the same indentation level, one after the other, which is not valid. Did you mean for one of them to be an elif?
I am working in a grid-universe - objects only exist at integer locations in a 2 dimensional matrix.
Some terms:
Square - a discrete location. Each square has an int x and int y coordinate, and no two squares have the same x and y pair.
Adjacent: A square X is adjacent to another square Y if the magnitude of the difference in either their x or y coordinate is no greater than 1. Put more simply, all squares immediately in the N, NE, E, SE, S, SW, W, and NW directions are adjacent.
Legend:
'?' - Unknown Traversibility
'X' - Non Traversable Square
'O' - Building (Non Traversable)
' ' - Traversable Square
The problem:
Given the following generic situation:
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? O O ? ? ?
? ? ? O O ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
where the builder is adjacent to one of the four buildings, I want to build two buildings such that they both share a common adjacent square that is also adjacent to at least one of the four existing buildings, and this common adjacent square is not blocked in.
Basic Valid solutions:
X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X
X X X O O X X X X X X O O X X X X X X O O X X X
X X X O O X X X X X X O O X X X X X O O O X X X
X X X O X X X O X X X X
O O X X X O X X X X X X X X
X X X X X X X X X X X
Currently, I iterate through all traversable square adjacent to the four buildings, and look for squares that have 3 adjacent traversable squares, but this sometimes produces situations such as:
X X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X O X X X X X O X
X X X O O X X X X X O O O X X X O O O X X
X X X O O X X X X X O O X X X X O O X X
X X X X X X X X X X X X X X
X X X O O X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X
Any thoughts on how I can refine my algorithm?
EDIT: Added another failing case.
EDIT: I'd also like to be able to know if there isn't a possible configuration in which these conditions could be met. I'm not guaranteed a viable solution, and would like to not-try if there isn't a way to do this successfully.
Checking to ensure your new buildings aren't orthogonally adjacent will eliminate cases such as your problem case 1, and checking to ensure not more than one of your new buildings is adjacent to any of the originals will clear up problem case 2.
This should work if you can safely assume you are no more constricted than in problem case 2. If there is only one square of exit, then the only solutions will need to violate the "not more than one" condition proposed above.
Your invalid cases are due to the splitting of the free space into 2 parts right? In that case, a crude method would be to flood-fill the free space after building placement and see if the connected space has the correct size (2 squares less than prior to building placement). That seems excessive. You really want to know if the graph of the free-space squares is still connected. More specifically, you want to know if all the free-space squares around the new buildings are still connected. Do they have to be locally connected, or can the path be arbitrarily long? i.e. is this valid:
X X X X X X X X
X X X
X X X X X X
X X X X X X
X O X X
X X O O O X X
X X O O X X
X X X X
X X X X X X
X X X X X X
If that is OK, this is a hard problem because that path could be very long.
The only solution I can think of is to do pathfinding from the common adjacent square out to the edge of the map. It looks to me like all the problem cases boil down to "the adjacent square is blocked in" so the way to ensure it isn't blocked in is to find a path from that square to an open edge of the map.
I don't know if that's the most efficient approach but it would be fairly simple to implement, since A* pathfinding routines are pretty widely implemented. And actually since you don't need the shortest path, just a path, you could simply do a flood-fill of free spaces starting from the adjacent square until you hit the edge of the map.