I am fairly new to python, and I am trying to design a class to solve the N Queen Problem.
This is my class def:
class QueenSolver:
def genEmptyBoard(self, n):
# Generates an empty board of n width and n height
board = []
for _ in range(n):
board.append([0 for _ in range(n)])
return board
def genLegalBoard(self, q1, q2, n):
# Returns legal board or false
board = self.genEmptyBoard(self, n)
try:
board[q1[0]][q1[1]] = 'q'
except IndexError:
print("Queen placed outside of board constraints")
return False
try:
if board[q2[0]][q2[1]] == 'q':
print("Queens cannot be placed in the same position")
return False
board[q2[0]][q2[1]] = 'Q'
except IndexError:
print("Queen placed outside of board constraints")
return False
return board
However, when I call this method outside of the class, like this:
board = QueenSolver.genLegalBoard([0, 0], [7, 7], 8)
I get an error that looks like this:
Exception has occurred: TypeError
QueenSolver.genLegalBoard() missing 1 required positional argument: 'n'
Apparently I have to supply the "self" variable when calling it from outside the class definition? I thought the "self" parameter doesn't require any value, because it is assumed? What am I missing here?
You need to Instantiate an object of QueenSolver class before calling the method of the class. As well as, remove self from board = self.genEmptyBoard(self, n).
class QueenSolver:
def genEmptyBoard(self, n):
# Generates an empty board of n width and n height
board = []
for _ in range(n):
board.append([0 for _ in range(n)])
return board
def genLegalBoard(self, q1, q2, n):
# Returns legal board or false
board = self.genEmptyBoard(n)
............
............
return board
QS = QueenSolver()
board = QS.genLegalBoard([0, 0], [7, 7], 8)
Output:
[['q', 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 'Q']]
Related
I writing a Battleship game, however I'm not sure on how to change the 1 in the first players grid to a 0, so that the player can not see where the ship is.
import random
# formatt to access certain grid point print (grid_1[1][2])
grid_1 = [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
row_random = random.randint(0,3)
column_random = random.randint(0,3)
ship_1 = grid_1[row_random][column_random] = 1
# creates a random spot in the grid where the ship will be
def Player_1():
for i in grid_1:
print (i)
#loops through grid so the output is in row and column form
x = int(input("Enter row:"))
y = int(input("Enter column:"))
co_ordinates_1 = (grid_1[x][y])
# user guses where the ship will be
if co_ordinates_1 == 1:
print("BATTLESHIP HIT")
elif co_ordinates_1 != 1:
print("You missed!")
# shows the user if they hit the target or not
Player_1()
You need to check if a value is equal to 1 (ship). Here is the code below
for i in grid_1:
row = i.copy()
for j in range(0, 4):
if row[j] == 1:
row[j] = 0
print(row)
This code loops through each item and checks if it equal to 1. If it is, then the value is set to 0. This should print out
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
I need to calculate the eigenvalues of an 8x8-matrix and plot each of the eigenvalues for a symbolic variable occuring in the matrix. For the matrix I'm using I get 8 different eigenvalues where each is representing a function in "W", which is my symbolic variable.
Using python I tried calculating the eigenvalues with Scipy and Sympy which worked kind of, but the results are stored in a weird way (at least for me as a newbie not understanding much of programming so far) and I didn't find a way to extract just one eigenvalue in order to plot it.
import numpy as np
import sympy as sp
W = sp.Symbol('W')
w0=1/780
wl=1/1064
# This is my 8x8-matrix
A= sp.Matrix([[w0+3*wl, 2*W, 0, 0, 0, np.sqrt(3)*W, 0, 0],
[2*W, 4*wl, 0, 0, 0, 0, 0, 0],
[0, 0, 2*wl+w0, np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W],
[0, 0, np.sqrt(3)*W, 3*wl, 0, 0, 0, 0],
[0, 0, 0, 0, wl+w0, np.sqrt(2)*W, 0, 0],
[np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W, 2*wl, 0, 0],
[0, 0, 0, 0, 0, 0, w0, W],
[0, 0, np.sqrt(2)*W, 0, 0, 0, W, wl]])
# Calculating eigenvalues
eva = A.eigenvals()
evaRR = np.array(list(eva.keys()))
eva1p = evaRR[0] # <- this is my try to refer to the first eigenvalue
In the end I hope to get a plot over "W" where the interesting range is [-0.002 0.002]. For the ones interested it's about atomic physics and W refers to the rabi frequency and I'm looking at so called dressed states.
You're not doing anything incorrectly -- I think you're just caught up since your eigenvalues look so jambled and complicated.
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
W = sp.Symbol('W')
w0=1/780
wl=1/1064
# This is my 8x8-matrix
A= sp.Matrix([[w0+3*wl, 2*W, 0, 0, 0, np.sqrt(3)*W, 0, 0],
[2*W, 4*wl, 0, 0, 0, 0, 0, 0],
[0, 0, 2*wl+w0, np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W],
[0, 0, np.sqrt(3)*W, 3*wl, 0, 0, 0, 0],
[0, 0, 0, 0, wl+w0, np.sqrt(2)*W, 0, 0],
[np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W, 2*wl, 0, 0],
[0, 0, 0, 0, 0, 0, w0, W],
[0, 0, np.sqrt(2)*W, 0, 0, 0, W, wl]])
# Calculating eigenvalues
eva = A.eigenvals()
evaRR = np.array(list(eva.keys()))
# The above is copied from your question
# We have to answer what exactly the eigenvalue is in this case
print(type(evaRR[0])) # >>> Piecewise
# Okay, so it's a piecewise function (link to documentation below).
# In the documentation we see that we can use the .subs method to evaluate
# the piecewise function by substituting a symbol for a value. For instance,
print(evaRR[0].subs(W, 0)) # Will substitute 0 for W
# This prints out something really nasty with tons of fractions..
# We can evaluate this mess with sympy's numerical evaluation method, N
print(sp.N(evaRR[0].subs(W, 0)))
# >>> 0.00222190090611143 - 6.49672880062804e-34*I
# That's looking more like it! Notice the e-34 exponent on the imaginary part...
# I think it's safe to assume we can just trim that off.
# This is done by setting the chop keyword to True when using N:
print(sp.N(evaRR[0].subs(W, 0), chop=True)) # >>> 0.00222190090611143
# Now let's try to plot each of the eigenvalues over your specified range
fig, ax = plt.subplots(3, 3) # 3x3 grid of plots (for our 8 e.vals)
ax = ax.flatten() # This is so we can index the axes easier
plot_range = np.linspace(-0.002, 0.002, 10) # Range from -0.002 to 0.002 with 10 steps
for n in range(8):
current_eigenval = evaRR[n]
# There may be a way to vectorize this computation, but I'm not familiar enough with sympy.
evaluated_array = np.zeros(np.size(plot_range))
# This will be our Y-axis (or W-value). It is set to be the same shape as
# plot_range and is initally filled with all zeros.
for i in range(np.size(plot_range)):
evaluated_array[i] = sp.N(current_eigenval.subs(W, plot_range[i]),
chop=True)
# The above line is evaluating your eigenvalue at a specific point,
# approximating it numerically, and then chopping off the imaginary.
ax[n].plot(plot_range, evaluated_array, "c-")
ax[n].set_title("Eigenvalue #{}".format(n))
ax[n].grid()
plt.tight_layout()
plt.show()
And as promised, the Piecewise documentation.
for some reason this code throws this error:
player.py:
class player():
def __init__(self, x, y, width, height):
self.collisionXY[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
error:
line 21, in __init__
self.collisionXY[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
AttributeError: 'player' object has no attribute 'collisionXY'
what i want is to store the x1, x2, y1, y2 coordinates of a colliding rect as ints within the collisionXY list how can the code be fixed to do this
If you want to assign a list to that variable, it would be
self.collisionXY = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
or just
self.collisionXY = [0]*16
When you write
self.collisionXY[16] =...
that is interpreted as trying to write to index 16 in self.collisionXY, which generates an error because self.collisionXY hasn't been defined yet.
You are trying to create an array of 16 ints initialize to 0.
You can either use a list
self.collisionXY = [0]*16
a tuple:
self.collisionXY = (0,)*16
or an array:
import array
...
self.collisionXY = array.array('l', [0]*16)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am trying to make a 2D array that is 8x8 for a checkers game in python. How would I go about doing this?
Here is my current code:
class Board():
board = [[]]
def __init__(self,width,height):
self.width = width
self.height = height
def __repr__(self):
print(self.board)
def setup(self):
for y in range(self.height):
for x in range(self.width):
self.board[y].append(0)
board = Board(8,8)
board.setup()
print(board.board)
board = [[0]*8 for i in range(8)] # This makes you 8x8 list
>>>[[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]
def setup(self):
board = [[0]*self.height for i in range(self.width)]
You only change 8's with your instance attributes(self.heigth,self.width)
At the point where your code does
self.board[y].append(0)
self.board has only one element, so for y>0 this will fail. You need to make self.board contain not one empty list but self.height empty lists for this to work.
I am not going into more detail because, as one commenter has mentioned, this sounds a lot like homework and in such cases it's best for everyone not to fill in all the details.
Nested lists can sometimes be difficult to work with. If you don't absolutely need a 2D list, I recommend using a dict. Creating a 2D array with a dict is easy. You can use a tuple of (row,column) as the index.
For example:
board = {}
for row in range(8):
for column in range(8):
board[(row, column)] = 0
So I am having a strange problem in python. I am using the code below to create a plot of places where the object has been. Here is my code:
def GoForward(self, duration):
if (self.TowardsX - self.X == 0):
Myro.robot.motors(self.Speed, self.Speed)
Myro.wait(abs(duration))
Myro.robot.stop()
#get the amount of points forward
divisible = (int) (duration / self.Scale)
#add them to the direction
self.TowardsY += divisible
tempY = self.Y
for y in xrange(self.Y, divisible + tempY):
if (y % self.Scale == 0):
self.Plot[(int) (self.X)][y] = 1
return
#calc slope
slope = (self.TowardsY - self.Y) / (self.TowardsX - self.X)
tempX = self.X
tempY = self.Y
#go forward
#get the amount of points forward
divisible = duration / self.Scale
#add them to the direction
self.TowardsX += divisible
self.TowardsY += divisible
Xs = []
Ys = []
for x in xrange(self.X, tempX + divisible):
#find out if it is a plottable point
if (((slope * (x - self.X)) + self.Y) % self.Scale == 0.0):
Xs.append(x)
Ys.append((int)((slope * (x - self.X)) + self.Y))
#Plot the points
for i in xrange(0, len(Xs)):
for j in xrange(0, len(Ys)):
if (self.Plot[Xs[i]][Ys[j]] == 0):
self.Plot[Xs[i]][Ys[j]] = 1
self.X += divisible
self.Y += divisible
But, when I call GoForward(2) it fills five columns with ones, instead of the few points. Example:
[[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]
[0,0,0,0,1,1,0,0,0,0]]
Based off the parameter given to GoForward(n) it creates that many columns full of 0s... Why is this behavior happening? My code should not produce this effect, but I am inexperienced with python so is that why this is happening? Thanks in advance
EDIT
So I have changed the code for plotting the points to
for i in xrange(0, len(Xs)):
if (self.Plot[Xs[i]][Ys[i]] == 0):
self.Plot[Xs[i]][Ys[i]] = 1
Which will have the correct values, however it is still producing this strange behavior, and the problem lies in this code here.
EDIT 2
When I use the code:
self.Plot[3][3] = 1
It still produces an array of:
[[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]]
So to produce that grid you are showing you are printing self.Plot? And your saying this grid gets initialized to 0? What exactly is self.Plot? A list of lists and that's it? When you print self.Plot before running that loop does it print what you expect (which I assume should be all zeros)?
So if Xs and Ys are the points that should be 1 you could simplify the code to using one list of plottable points:
plottable_points = []
# for loop
plottable_points.append( (x, int((slope * (x - self.X)) + self.Y)) )
for x, y in plottable_points:
self.Plot[x][y] = 1
I'm not sure exactly how self.Plot is being initialized or used, but if you print things before and after each step you should be able to figure out where your logic is wrong.
Edit 1:
Extra little python tip:
for x, y in zip(Xs, Ys):
self.Plot[x][y] = 1
Does the same thing as my first code example does, but with your variables.
Edit 2:
The problem is actually with how you are initializing self.Plot. When you repeat a list like that, your outer list becomes a list of pointers...all pointing to the same object (in this case a list). So when you say self.Plot[3][3] = 1, you are actually setting that column in each row. Try initializing self.Plot with something like this (there may be a better way to do this, but I'm tired):
self.Plot = []
for col in range(height * multiplyBy):
self.Plot.append([0] * width * multiplyBy)
# or:
self.Plot = [ [0] * width * multiply for col in range(height * multiplyBy) ]
I would say that you should do a simple import (from future import division) before doing any more modifications. To me it seems the problem is the division. In Python 2.7 it returns you an integer.
Take a look at this:
>>> 4/3
1
>>> 4//3
1
But if you import the new division functionality...
>>> from __future__ import division
>>> 4/3
1.3333333333333333