I'm trying to create a maze through recursive backtracking but I can't seem to call create_maze() properly. From my main menu I call the maze class like this
maze = Maze.create_maze(NoOfRows, NoOfColumns)
However, I get an argument error from create_maze saying I'm missing an additional "y" or my self.path(0 is missing an additional y
Where am I going wrong?
from numpy.random import random_integers as rand
from Generate import ascii_representation
from constants import *
import numpy as np
WALL_TYPE = np.int8
WALL = 0
EMPTY = 1
RED = 2
BLUE = 3
class Maze:
def __init__(self, Width, Height):
self.Width = Width
self.Height = Height
self.board = np.zeros((Width, Height), dtype=WALL_TYPE)
self.board.fill(EMPTY)
def set_borders(self):
self.board[0, :] = self.board[-1, :] = WALL
self.board[:, 0] = self.board[:, -1] = WALL
def is_wall(self, x, y):
return self.board[x][y] == WALL
def set_wall(self, x, y):
self.board[x][y] = WALL
def remove_wall(self, x, y):
self.board[x][y] = EMPTY
def in_maze(self, x, y):
return 0 <= x < self.Width and 0 <= y < self.Height
def write_to_file(self, filename):
f = open(filename, 'w')
f.write(ascii_representation(self))
f.close()
def set_path(self, x, y):
self.board[y][x] = False
#staticmethod
def load_from_file(filename):
with open(filename, 'r') as f:
content = f.readlines()
# remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content]
xss = []
for line in content:
xs = []
for c in line:
if c == ' ':
xs.append(EMPTY)
elif c == 'X':
xs.append(WALL)
else:
raise ValueError('unexpected character found: ' + c)
xss.append(xs)
maze = Maze(len(xss), len(xss[0]))
for xs in xss:
assert len(xs) == maze.Height
for i in range(maze.Width):
for j in range(maze.Height):
if xss[i][j] == EMPTY:
maze.remove_wall(i, j)
else:
maze.set_wall(i, j)
return maze
#staticmethod
def complete_maze(Width, Height):
maze = Maze(Width, Height)
for i in range(Width):
for j in range(Height):
maze.board[i][j] = WALL
return maze
def create_maze(x, y):
Maze.set_path(x, y)
all_directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]
random.shuffle(all_directions)
while len(all_directions) > 0:
direction_to_try = all_directions.pop()
node_x = x + (direction_to_try[0] * 2)
node_y = y + (direction_to_try[1] * 2)
if Maze.is_wall(node_x, node_y):
link_cell_x = x + direction_to_try[0]
link_cell_y = y + direction_to_try[1]
self.set_path(link_cell_x, link_cell_y)
self.create_maze(node_x, node_y)
return
Take a look at the definition for set_path:
def set_path(self, x, y):
This expects three parameters. When you call it with Maze.set_path(x,y), you're only giving it two: x and y. Python expects three and in the order self, then x, then y. Python is interpreting the x you give to be self, then the y to be x and then gives an error that y isn't given. But what is actually missing is self!
To fix this, you need to change this call to self.set_path(x, y) (which is a shortcut for Maze.set_path(self, x, y)). You'll also need to pass self to create_maze as well by changing its definition to def create_maze(self, x, y). And finally, change the way you call create_maze() to something like
maze = Maze(NoOfRows, NoOfCols).create_maze(NoOfRows, NoOfColumns)
As an aside, it seems you never use self.Width or self.Height. You should either remove them from __init__ and just take the x and y passed in create_maze(), or change create_maze() to use self.Width and self.Height instead of taking x and y as parameters.
Related
I have a question but I don't know exactly how to explain it, so let me put some code here:
class 2DVector:
def __init__(self, x, y):
self.x = x
self.y = y
def multiply(self, scalar):
self.x *= scalar
self.y *= scalar
is it posible to do something like this
vector1 = 2DVector(1, 1).multiply(3)
# x == 3, y == 3
or do I always have to do it like this
vector2 = 2DVector(1, 1)
# x == 1, y == 1
vector2.multiply(3)
# x == 3, y == 3
Adding return self at the end of the multiply method allows you to use the first option:
class TwoDVector:
def __init__(self, x, y):
self.x = x
self.y = y
def multiply(self, scalar):
self.x *= scalar
self.y *= scalar
return self
if __name__ == '__main__':
vector = TwoDVector(2, 3).multiply(2)
# vector.x == 4, vector.y == 6
They are equivalent in that they both scale the vector.
But your first example is not very useful it doesn't keep a reference to the class instance. Instead it keeps a reference to the return value of multiply (which is just None) so your vector reference is lost.
As mentioned you could modify multiply to return self.
You could also add a scale factor to the constructor:
class 2DVector:
def __init__(self, x, y, scale=1):
self.x = x
self.y = y
self.multiply(scale)
# scales vector to (3, 3)
vector1 = 2DVector(1, 1, 3)
If you want to use vector2.multiply(3) directly, you need to adapt your method and return something.
def multiply(self, scalar):
self.x *= scalar
self.y *= scalar
return self
But I do not like this solution and prefer :
def multiply(self, scalar):
return 2DVector(self.x * scalar, self.y * scalar)
and treat vector as immutables objects.
Or keeping your first implementation and do
vector2 = 2DVector(1, 1)
# x == 1, y == 1
vector2.multiply(3)
# x == 3, y == 3
The perfect, but impossible, scenario would be:
class example(object):
def __init__(self,x,y):
self.x = x
self.y = y
def foo(self, x = self.x, y = self.y):
return x + y
It doesn't work because self isn't defined. I have done lots of research, looked on decorators, descriptors, metaclasses, almost everything. The solution may be the most obvious and known to all, but I couldn't find it. I could manage two workarounds, as follows:
def prep(argslist, argsprovided, attributes):
argsout = []
for name in argslist:
if name in argsprovided:
argsout.append(argsprovided[name])
else:
argsout.append(getattr(attributes,name))
return argsout
class example(object):
# I can create a default instance or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
# I can wrap a function to use the self argument
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
# I can wrap 'joo' alongside with foo, and make 'wrapper' return a list
def joo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + 2*w
# I can use my custom 'prep' function to to the job
def foo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + w
# Creates a default instance and a custom one
c = example()
d = example(2,2,2,2)
# I can use 'foo' with the instance's default values with both wrapping and 'prepping'
print(c.wrapper()())
print(d.wrapper()())
print(c.foo())
print(d.foo())
# I can use 'foo' with a mix of default values and provided values with both wrapping and 'prepping'
print(c.wrapper()(1,2,3))
print(d.wrapper()(1,2,3))
print(c.foo(y = 3,z = 4,w = 5))
print(d.foo(y = 3,z = 4,w = 5))
The code prints out:
4
8
4
8
7
8
13
14
I have a huge class with lots of functions, every one needs the behavior of 'foo'. My prep solution is too time consuming. After profiling the code, I figured it spent 12 seconds inside prep only. What is a clever and less time consuming way of doing this? I'm completely lost.
I'm not sure it will help but how about using None as a default value and use a clause to determine the value. For example:
def foo(self, x=None, y=None):
real_x = x if x != None else self.x
real_y = y if y != None else self.y
return real_x + real_y
I found six ways of doing what I wanted. After profiling the code, the result was:
afoo foo noo1 noo2 wrap1 wrap2
6.730 28.507 3.98 4.097 10.256 3.468
6.407 28.659 4.096 3.924 9.783 3.529
6.277 28.450 3.946 3.889 10.265 3.685
6.531 30.287 3.964 4.149 10.077 3.674
As you will see ahead, noo1, noo2 and wap2 are quite similar on code. The conventional method afoo is not that efficient. My custom method foo is terrible and wrap1 was just tested for the sake of completeness.
afoo.py
The drawback is that you need an extra line for each function argument.
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def afoo(self, x = None, y = None, z = None, w = None):
x = x if x != None else self.x
y = y if y != None else self.y
z = z if z != None else self.z
w = w if w != None else self.w
return x + y + z + w
c = example(2,2,2,2)
for i in range(0, 10000000):
c.afoo(1,2,3,4)
foo.py
This one is the slower method.
def prep(argslist, argsprovided, attributes):
argsout = []
for name in argslist:
if name in argsprovided:
argsout.append(argsprovided[name])
else:
argsout.append(getattr(attributes,name))
return argsout
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def foo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + w
c = example(2,2,2,2)
for i in range(0, 10000000):
c.foo(x = 1,y = 2,z = 3,w = 4)
wrapper1.py
By far less efficient than wrapper2.py.
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
c = example(2,2,2,2)
for i in range(0, 10000000):
c.wrapper()(1,2,3,4)
wrapper2.py
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
c = example(2,2,2,2)
k = c.wrapper()
for i in range(0, 10000000):
k(1,2,3,4)
noo1.py
class example(object):
# I can create a default class or a custom one
def __init__(self,U,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def noo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
self.noo = noo
c = example(2,2,2,2)
for i in range(0, 10000000):
c.noo(1,2,3,4)
noo2.py
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def __call__(self):
def noo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
self.noo = noo
c = example(2,2,2,2)
c()
for i in range(0, 10000000):
c.noo(1,2,3,4)
When testing these codes I included the prep function in all of them, just to be shure they had the same basic structure, and thus the time difference would be from the loops.
I'm trying to set a class property of a cell contained in the multidimensional array Board.grid. I get the following error message:
File "newbs1.py", line 133, in get_and_set_board_item
self.grid[x, y].set_cell(value, secondary)
File "newbs1.py", line 129, in __getitem__
return self.grid[x][y]
File "newbs1.py", line 128, in __getitem__
x, y = tup
TypeError: 'int' object is not iterable
The idea of having the x and y entered how they are came from a post by someone else, it fixed their problem but it hasn't worked for me.
class Board(object):
def __init__(self):
self.grid = []
self.width = 10
self.height = 10
def __getitem__(self, tup):
x, y = tup
return self.grid[x][y]
def get_and_set_board_item(self, x, y, value, secondary):
print (x, y, value, secondary)
self.grid[(x, y)].set_cell(value, secondary)
class Cell():
def __init__(self):
self.is_ship = False
self.is_hidden = False
self.ship_symbol = ""
def set_cell(self, value, secondary):
if secondary == None:
self.is_hidden = value
else:
self.is_ship = value
self.ship_symbol = secondary
I'm not sure how the rest of your code looks, but on line:133, self.grid[(x, y)].set_cell(value, secondary), it doesn't look like the tuple (x, y) is a Cell type.
Maybe try:
class Board(object):
def __init__(self):
self.grid = []
self.width = 10
self.height = 10
def __getitem__(self, tup):
x, y = tup
return self.grid[x][y]
def get_and_set_board_item(self, x, y, value, secondary):
print (x, y, value, secondary)
# add this line #
self.grid[x][y] = Cell() # set this to a cell type
# ************* #
self.grid[x][y].set_cell(value, secondary)
class Cell():
def __init__(self):
self.is_ship = False
self.is_hidden = False
self.ship_symbol = ""
def set_cell(self, value, secondary):
if secondary == None:
self.is_hidden = value
else:
self.is_ship = value
self.ship_symbol = secondary
from threading import *
from random import *
class Ant(Thread):
def __init__(self, x, y):
Thread.__init__(self)
self.x = x
self.y = y
def move(self, x, y):
self.x = x
self.y = y
class Ant_farm():
def __init__(self, x, y):
self.x = x
self. y = y
self.matrix = matrix(x, y)
self.condition = Condition()
def move(self, ant):
with self.condition:
x1, y1 = next_post(ant)
while self.matrix[x1][y1]:
self.condition.wait()
self.matrix[ant.x][ant.y] = False
ant.move(x1, y1)
self.matrix[ant.x][ant.y] = True
self.condition.notify_all()
def next_pos(self, ant):
while True:
choice = {0: (ant.x, ant.y - 1),
1: (ant.x + 1, ant.y),
2: (ant.x, ant.y + 1),
3: (ant.x - 1, ant.y)}
x1, y1 = choice[randrange(0, 4)]
try:
self.matrix[x1][y1]
except IndexError:
pass
else:
return x1, y1
def __str__(self):
res = '\n'
for i in range(self.x):
aux = ''
for j in range(self.y):
aux += str(self.matrix[i][j]) + ' '
aux += '\n'
res += aux
return res
def matrix(x, y):
return [[False for j in range(y)] for i in range(x)]
if __name__ == '__main__':
ant_farm = Ant_farm(7, 7)
for i in range(4):
# t = Ant(target = ant_farm.move)
pass
I want to run move function inside Ant threads. I tried to do:
t = Ant(target = ant_farm.move)
But the interpreter says this:
TypeError: init() got an unexpected keyword argument 'target'
I understand the error, but I don't know how to do what I said.
I'm new to python, and programming in general and am struggling to understand why I can't access the x, y coordinates of the list I created ranlist to use as variables in my math module distance formula.
Here is the entirety of my code, however the step of defining the function closestpt is where I am hung up, and within the function, ranlist.x, ranlist.y is where I get an
AttributeError: list object has no attribute 'x'
Can someone explain to me why ranlist does not have 'x' and 'y' as attributes, and how I can access the x,y points in the list ranlist? When I step through the code and debug I can see the random float values generated
import math
class Point():
def __init__(self, x, y, z=0):
self.x=x
self.y=y
self.z=z
self.dem=2
if (z!=0):
self.dem=3
def print_coordinate(self):
print "The x coordinate is %s, the y coordinate is %s, and the z coordinate is %s" % (self.x, self.y, self.z)
def calc_distance(self, next1):
try:
if (self.z==0):
dx = self.x - next1.x
dy = self.y - next1.y
return math.hypot(dx,dy)
else:
threedist = ((self.x - next1.x)^2 + (self.y - next1.y)^2 + (self.z - next1.z)^2)
return math.sqrt(threedist)
except(SyntaxError, IndexError, TypeError) as e:
print e
cord1 = Point(0,1,4)
cord2 = Point(0,4,0)
print cord1.print_coordinate()
print cord1.calc_distance(cord2)
import random
a = 10
b = 20
val = random.uniform(a,b)
ranlist = []
def ranpoint(num_point, dimension, lower_bound, upper_bound):
for i in range(num_point):
x = random.uniform(lower_bound, upper_bound)
y = random.uniform(lower_bound, upper_bound)
ranlist.append(Point(x,y,0))
return ranlist
print ranpoint
print ranpoint(100, "2d", 0, 100)
rantest = ranpoint(100, '2d', 0, 100)
def closestpt():
cordt = Point(50,50)
dist1 = []
for i in range(0, 100):
ndx = cordt.x - ranlist.x
ndy = cordt.y - ranlist.y
dist2 = math.hypot(ndx,ndy)
dist1.append(dist2)
return dist1
print closestpt()
You have ranlist which is a list. You append a Point to it. So now ranlist has 1 object inside it of type Point.
To access this object you could run ranlist[0].x and ranlist[0].y which will access the first member of the list (in index 0) and retrieve the value of x and y respectively.