IndexError I just can't figure out (Python) - python

I'm trying to make a minesweeper game through text in python. This error comes up when I try to draw the little numbers. Maybe the way I'm doing this is inefficient, but I don't understand why it throws this error. I've been trying to fiddle with the code, but nothing seems to work. Does anyone have any idea for why it's not working?
import random
minenum = 12
gridsize = 10
grid = [[0] * gridsize for _ in range(gridsize)]
def setup():
global grid
global minecount
for i in range(minenum):
x = random.randrange(0,10)
y = random.randrange(0,10)
grid[y][x] = "m"
xpos = 0
ypos = 0
for n in range(10):
for z in range(10):
count = 0
try:
if grid[ypos + 1][xpos] == "m":
count += 1
except:
pass
try:
if grid[ypos + 1][xpos + 1] == "m":
count += 1
except:
pass
try:
if grid[ypos + 1][xpos - 1] == "m":
count += 1
except:
pass
try:
if grid[ypos - 1][xpos + 1] == "m":
count += 1
except:
pass
try:
if grid[ypos - 1][xpos - 1] == "m":
count += 1
except:
pass
try:
if grid[ypos - 1][xpos] == "m":
count += 1
except:
pass
try:
if grid[ypos][xpos + 1] == "m":
count += 1
except:
pass
try:
if grid[ypos][xpos - 1] == "m":
count += 1
except:
pass
grid[ypos][xpos] = count
xpos += 1
ypos += 1
def printBoard():
for i in range(10):
print(' '.join(str(v) for v in grid[i]))
setup()
printBoard()
[Edit]
here is the error:
Traceback (most recent call last):
File "main.py", line 74, in <module>
setup()
File "main.py", line 63, in setup
grid[ypos][xpos] = count
IndexError: list assignment index out of range

If you add a print(count) before the grid[ypos][xpos] = count you will see that you have 11 instances of count but grid is only 10 so that's why.
You add to the ypos and xpos even when it's at max, a quick fix below but can be better:
print(count)
grid[ypos][xpos] = count
if xpos < gridsize - 1:
xpos += 1
if ypos < gridsize - 1:
ypos += 1

Your code was not working because you never reset xpos when you incremented your ypos so your indexes looked like this (for gridsize = 4):
0 0
1 0
2 0
3 0
4 1
5 1
6 1
7 1
8 2
Instead of what you inteded, i.e.
0 0
1 0
2 0
3 0
0 1
1 1
2 1
3 1
0 2
You should have added xpos = 0 whenever you do ypos += 1
xpos += 1
ypos += 1
xpos = 0
Your code could also use a bit of cleanup:
import random
def setup(minecount, gridsize):
grid = [[0] * gridsize for _ in range(gridsize)]
for _ in range(minecount):
x = random.randrange(0,gridsize)
y = random.randrange(0,gridsize)
grid[y][x] = "m"
for xpos in range(gridsize):
for ypos in range(gridsize):
count = 0
if ypos + 1 < 10 and grid[ypos + 1][xpos] == "m":
count += 1
if ypos + 1 < 10 and xpos +1 < 10 and grid[ypos + 1][xpos + 1] == "m":
count += 1
if ypos + 1 < 10 and xpos - 1 >= 0 and grid[ypos + 1][xpos - 1] == "m":
count += 1
if ypos - 1 >= 0 and xpos + 1 < 10 and grid[ypos - 1][xpos + 1] == "m":
count += 1
if ypos - 1 >= 0 and xpos -1 >= 10 and grid[ypos - 1][xpos - 1] == "m":
count += 1
if ypos - 1 >= 0 and grid[ypos - 1][xpos] == "m":
count += 1
if xpos + 1 < 10 and grid[ypos][xpos + 1] == "m":
count += 1
if xpos - 1 >= 0 and grid[ypos][xpos - 1] == "m":
count += 1
grid[ypos][xpos] = count
return grid
def printBoard(grid):
for i in range(10):
print(' '.join(str(v) for v in grid[i]))
minecount = 12
gridsize = 10
grid = setup(minecount, gridsize)
printBoard(grid)
Didn't even have to change the logic, just switched magic numbers to proper parameters. You are also overwriting all your "m" cells when counting neighbouring bombs, you might want to avoid that.

You have to assign zero to xpos in the end of setup() function:
ypos += 1
xpos = 0

Related

IndexError: index 101 is out of bounds for axis 0 with size 101

I am getting the error:
if r[(i-1)]%2 == 0:
IndexError: index 101 is out of bounds for axis 0 with size 101
By trying to run this piece of code :
import numpy as np
r = np.array(list(range(0,101)));
i = 1
condition = True
while condition:
if r[(i-1)]%2 == 0:
r[(i-1)] = 0
i = i + 1
if r[(i-1)] % 3 == 0:
r[(i-1)] = 0
i = i + 1
if r[(i-1)] % 5 == 0:
r[(i-1)] = 0
i = i + 1
else:
i = i + 1
print(r)
I tried to look some stuff up and I think I understand the meaning of the error but I don't understand why it's popping up for me

How to get try: except: working without going on infinitely

So I have a 2d list, named tour:
tour = [ [3, 2, 1,],
[4, 7, 9,],
[5, 6, 8,], ]
I want my code to check through this list and see if a king (chess) can go through it normally.
The code I made can be applicable on a N×N 2d list. What it does is that it starts on number 1, and checks all 9 spaces around it if there is a number 2, repeating the process till N×N. The problem is that when the number is at a side of the list the code gives an IndexError, to overcome this I made a try: except: IndexError but now when it gets to i = 6 it keeps on going infinitely
def in_list(number, listname):
"""
this function detects where a certain number is in a 2d list and returns the index of
it
"""
for i, sublist in enumerate(listname):
if (number in sublist):
return [i, sublist.index(number)]
return -1
def is_king_tour_3by3(tour):
"""
this function checks for all 9 areas around this number and if it's an IndexError
i.e. it's at the end of the list it ignores that case
"""
start = in_list(1, tour)
i = 2
counter = len(tour) * len(tour)
while True:
counter -= 1
print(i)
print(start)
try:
if(tour[start[0]][start[1] - 1] == i): #starting from checking the number on the left and going counter-clockwise
i += 1
start[1] -= 1
elif(tour[start[0] + 1][start[1] - 1] == i):
i += 1
start[0] += 1
start[1] -= 1
elif(tour[start[0] + 1][start[1]] == i):
i += 1
start[0] += 1
elif(tour[start[0] + 1][start[1] + 1] == i):
i += 1
start[0] += 1
start[1] += 1
elif(tour[start[0]][start[1] + 1] == i):
i += 1
start[1] += 1
elif(tour[start[0] - 1][start[1] + 1] == i):
i += 1
start[0] -= 1
start[1] += 1
elif(tour[start[0] - 1][start[1]] == i):
i += 1
start[0] -= 1
elif(tour[start[0] - 1][start[1] - 1] == i):
i += 1
start[0] -= 1
start[1] -= 1
except IndexError:
pass
if(i == (len(tour) * len(tour))):
return True
break
elif(counter == 0):
return False
break
By adding start[0] < len(tour)-1 and start[1] > 0 to the rows you can check that you are not outside the 2d list instead of using a try: except:. This code will solve it as long as start is > 0 and < len(tour) (if start[0] or start[1] is -1 or len(tour) it might fail):
def in_list(number, listname):
"""
this function detects where a certain number is in a 2d list and returns the index of
it
"""
for i, sublist in enumerate(listname):
if (number in sublist):
return [i, sublist.index(number)]
return -1
def is_king_tour_3by3(tour):
"""
this function checks for all 9 areas around this number and if it's an IndexError
i.e. it's at the end of the list it ignores that case
"""
start = in_list(1, tour)
i = 2
counter = len(tour) * len(tour)
while True:
counter -= 1
print(i)
print(start)
if(start[1] > 0 and tour[start[0]][start[1] - 1] == i): #starting from checking the number on the left and going counter-clockwise
i += 1
start[1] -= 1
elif(start[0] < len(tour)-1 and start[1] > 0 and tour[start[0] + 1][start[1] - 1] == i):
i += 1
start[0] += 1
start[1] -= 1
elif(start[0] < len(tour)-1 and tour[start[0] + 1][start[1]] == i):
i += 1
start[0] += 1
elif(start[0] < len(tour)-1 and start[1] < len(tour)-1 and tour[start[0] + 1][start[1] + 1] == i):
i += 1
start[0] += 1
start[1] += 1
elif(start[1] < len(tour)-1 and tour[start[0]][start[1] + 1] == i):
i += 1
start[1] += 1
elif(start[0] > 0 and start[1] < len(tour)-1 and tour[start[0] - 1][start[1] + 1] == i):
i += 1
start[0] -= 1
start[1] += 1
elif(start[0] > 0 and tour[start[0] - 1][start[1]] == i):
i += 1
start[0] -= 1
elif(start[0] > 0 and start[1] > 0 and tour[start[0] - 1][start[1] - 1] == i):
i += 1
start[0] -= 1
start[1] -= 1
if(i == (len(tour) * len(tour))):
return True
break
elif(counter == 0):
return False
break
tour = [ [3, 2, 1,],
[4, 7, 9,],
[5, 6, 8,], ]
is_king_tour_3by3(tour)

How to make a Number/Letter interval in Python

So ...
Am writing a code that makes a Matrix table then calculate how many ( uppercase Letter , Lowercase Letter , Numbers , Symbols )
That's the code i tried :
def Proc_Affiche(T,P,X):
Nb_Maj = 0
Nb_Min = 0
Nb_chiffre = 0
Nb_symbole = 0
for i in range(P):
for j in range(X):
if T[i] in ["A","Z"]:
Nb_Maj = Nb_Maj + 1
elif T[i] in ["a","z"] :
Nb_Min = Nb_Min + 1
elif T[i] in range(1,9):
Nb_chiffre = Nb_chiffre + 1
else :
Nb_symbole = Nb_symbole + 1
print("Nb_Maj= ",Nb_Maj)
print("Nb_Min= ",Nb_Min)
print("Nb_chiffre= ",Nb_chiffre)
print("Nb_symbole= ",Nb_symbole)
So the Output should be like that :
Nb_Maj= ...
Nb_Min= ...
Nb_chiffre= ...
Nb_symbole= ...
The Problem is on the part of intervals Like ["A","Z"]
Strings have some functions you can use to check what they contain
.isalpha() is true for letters
.isnumeric() is true for numbers
.isalnum() is true for letters and numbers
.isupper() is true for uppercase
Thus you could do something like
if T[i].isalpha():
if T[i].isupper():
Nb_Maj += 1
else:
Nb_Min += 1
elif T[i].isnumeric():
Nb_chiffre += 1
else:
Nb_symbole += 1
Yes it is , here is the whlole code if that would help :
from math import*
def Proc_saisie():
X = -1
while X < 1 or X > 20 :
X = int(input("Donner un entier entre 5 et 20 : "))
return X
def Proc_Remplir(P,X):
T= [[] for i in range(P)]
for i in range(P):
for j in range(X):
d = input("T["+str(i)+","+str(j)+"]=")
T[i].append(d)
return T
def Proc_Affiche(T,P,X):
Nb_Maj = 0
Nb_Min = 0
Nb_chiffre = 0
Nb_symbole = 0
for i in range(P):
for j in range(X):
if T[i] in ["A","Z"]:
Nb_Maj = Nb_Maj + 1
elif T[i] in ["a","z"] :
Nb_Min = Nb_Min + 1
elif T[i] in range(1,9):
Nb_chiffre = Nb_chiffre + 1
else :
Nb_symbole = Nb_symbole + 1
print("Nb_Maj= ",Nb_Maj)
print("Nb_Min= ",Nb_Min)
print("Nb_chiffre= ",Nb_chiffre)
print("Nb_symbole= ",Nb_symbole)
#---------------------------
L = Proc_saisie()
C = Proc_saisie()
print("L =",L)
print("C =",C)
TAB = []
TAB = Proc_Remplir(L,C)
TAB = Proc_Affiche(TAB,L,C)
I'm not sure I understand what you want 100%, but I think something like follows would fit:
def Proc_Affiche(T,P,X):
Nb_Maj = 0
Nb_Min = 0
Nb_chiffre = 0
Nb_symbole = 0
for i in range(P):
for j in range(X):
if "A" <= T[i][j] <= "Z":
Nb_Maj = Nb_Maj + 1
elif "a" <= T[i][j] <= "z" :
Nb_Min = Nb_Min + 1
elif 1 <= T[i][j] <= 9:
Nb_chiffre = Nb_chiffre + 1
else :
Nb_symbole = Nb_symbole + 1
print("Nb_Maj= ",Nb_Maj)
print("Nb_Min= ",Nb_Min)
print("Nb_chiffre= ",Nb_chiffre)
print("Nb_symbole= ",Nb_symbole)

Variable takes negative value while it is restricted to be nonnegative

I am programming a vehicle routing problem in Python with PuLP. I got all my code in it, but for some reason I get a negative value for one of my decision variables, even though I restricted all of them to be nonnegative.
My code is as follows (Traveltimes is a two dimensional np array, with travel times between each pair of customers (i,j), where c(i,j) = c(j,i) and c(i,i) = 0.):
My code:
numVehicles = 2
numCustomers = 2
prob = LpProblem("DSP", LpMinimize)
var = [[[0 for k in range(numVehicles)] for j in range(numCustomers+1)] for i in range(numCustomers+1)]
for i in range(numCustomers+1):
for j in range(numCustomers+1):
for k in range(numVehicles):
var[i][j][k] = LpVariable("x"+str(i)+","+str(j)+","+str(k), 0,1, cat='Binary')
# ADD OBJECTIVE
obj = ""
for i in range(numCustomers+1):
for j in range(numCustomers+1):
for k in range(numVehicles):
obj += traveltimes[i][j]*var[i][j][k]
prob += obj
# ADD CONSTRAINTS
# All customers visited
for j in range(numCustomers+1):
for k in range(numVehicles):
nr = ""
for i in range(numCustomers+1):
nr += var[i][j][k]
prob += nr == 1
# Enter each customer exactly once
for i in range(numCustomers+1):
nr = ""
for k in range(numVehicles):
for j in range(1, numCustomers+1):
nr += var[i][j][k]
prob += nr == 1
# Leave each customer exactly once
for j in range(numCustomers+1):
nr = ""
for k in range(numVehicles):
for i in range(1, numCustomers+1):
nr += var[i][j][k]
prob += nr == 1
# Per vehicle only one customer can be visited as first
nrFirst = ""
for k in range(numVehicles):
for j in range(numCustomers+1):
nrFirst += var[0][j][k]
prob += nrFirst <= 1
# Max num vehicles
nrOut = ""
for k in range(numVehicles):
for j in range(numCustomers+1):
nrOut += var[0][j][k]
prob += nrOut <= numVehicles
# Restrict x(0,j,k) to be nonpositive
for j in range(numCustomers+1):
for k in range(numVehicles):
prob += var[0][j][k] >= 0
print(prob)
# Solve LP
prob.solve()
for v in prob.variables():
print(v.name, "=", v.varValue)
print("objective=", value(prob.objective))
The first output is the formulation printed
MINIMIZE
1.731*x0,1,0 + 1.731*x0,1,1 + 2.983*x0,2,0 + 2.983*x0,2,1 + 1.731*x1,0,0 + 1.731*x1,0,1 + 9.375*x1,2,0 + 9.375*x1,2,1 + 2.983*x2,0,0 + 2.983*x2,0,1 + 9.375*x2,1,0 + 9.375*x2,1,1 + 0.0
SUBJECT TO
_C1: x0,0,0 + x1,0,0 + x2,0,0 = 1
_C2: x0,0,1 + x1,0,1 + x2,0,1 = 1
_C3: x0,1,0 + x1,1,0 + x2,1,0 = 1
_C4: x0,1,1 + x1,1,1 + x2,1,1 = 1
_C5: x0,2,0 + x1,2,0 + x2,2,0 = 1
_C6: x0,2,1 + x1,2,1 + x2,2,1 = 1
_C7: x0,1,0 + x0,1,1 + x0,2,0 + x0,2,1 <= 1
_C8: x1,1,0 + x1,1,1 + x1,2,0 + x1,2,1 <= 1
_C9: x2,1,0 + x2,1,1 + x2,2,0 + x2,2,1 <= 1
_C10: x0,0,0 + x0,1,0 + x0,2,0 <= 1
_C11: x0,0,0 + x0,0,1 + x0,1,0 + x0,1,1 + x0,2,0 + x0,2,1 <= 1
VARIABLES
0 <= x0,0,0 <= 1 Integer
0 <= x0,0,1 <= 1 Integer
0 <= x0,1,0 <= 1 Integer
0 <= x0,1,1 <= 1 Integer
0 <= x0,2,0 <= 1 Integer
0 <= x0,2,1 <= 1 Integer
0 <= x1,0,0 <= 1 Integer
0 <= x1,0,1 <= 1 Integer
0 <= x1,1,0 <= 1 Integer
0 <= x1,1,1 <= 1 Integer
0 <= x1,2,0 <= 1 Integer
0 <= x1,2,1 <= 1 Integer
0 <= x2,0,0 <= 1 Integer
0 <= x2,0,1 <= 1 Integer
0 <= x2,1,0 <= 1 Integer
0 <= x2,1,1 <= 1 Integer
0 <= x2,2,0 <= 1 Integer
0 <= x2,2,1 <= 1 Integer
It can clearly be observed that all variables are restricted to be an integer between 0 and 1 (thus binary). However, for some reason, I do get negative values for some variable(s), as can be seen below
x0,0,0 = 0.0
x0,0,1 = -1.0
x0,1,0 = 0.0
x0,1,1 = 1.0
x0,2,0 = 0.0
x0,2,1 = 1.0
x1,0,0 = 1.0
x1,0,1 = 1.0
x1,1,0 = 1.0
x1,1,1 = 0.0
x1,2,0 = 0.0
x1,2,1 = 0.0
x2,0,0 = 0.0
x2,0,1 = 1.0
x2,1,0 = 0.0
x2,1,1 = 0.0
x2,2,0 = 1.0
x2,2,1 = 0.0
objective= 11.159
Really looking forward to any suggestions on how to solve this problem, since I clearly do not want negative values!
As a few others have suggested you should write a Minimum Complete and Verifiable Example.
That said, if you are getting constraints violated, and you are sure you've implemented them correctly, I reckon you have an infeasible problem (i.e. if you looked at your constraints carefully you would find there is a combination which makes solving impossible).
To check this add:
print (("Status:"), LpStatus[prob.status])
Just after you do prob.solve(). I reckon you'll find it's infeasible.
prob += nr == 1
"+=" is for assignment
"==" is checking for equivalence, and belongs in an "if" statement or a "while".
For instance:
if prob + nr == 1: #execute what follows if prob + nr is equal to 1

How to find count of values within certain range in pandas?

I have a pandas dataframe which contains a list of error values. I want to find the proportion of my errors in certain ranges e.g. what percentage of my error is within +-1%, +-5%, +-10%, +-20% and +-50% etc. A histogram of my data is shown below:
So far I have looked at functions such as pd.cut() and plt.hist() but no libraries seem to give me the answer where my ranges overlap each other so I'm having to resort to a very long custom made function - which is below:
def error_distribution(df):
total_length = len(df.index)
one_perc = five_perc = ten_perc = fifteen_perc = twenty_perc = thirty_perc \
= fourty_perc = fifty_perc = over_fifty = 0
for index, row in df.iterrows():
value = abs(row['Errors'])
if value <= 0.01:
one_perc += 1
five_perc += 1
ten_perc += 1
fifteen_perc += 1
twenty_perc += 1
thirty_perc += 1
fourty_perc += 1
fifty_perc += 1
elif value <= 0.05:
five_perc += 1
ten_perc += 1
fifteen_perc += 1
twenty_perc += 1
thirty_perc += 1
fourty_perc += 1
fifty_perc += 1
elif value <= 0.1:
ten_perc += 1
fifteen_perc += 1
twenty_perc += 1
thirty_perc += 1
fourty_perc += 1
fifty_perc += 1
elif value <= 0.15:
fifteen_perc += 1
twenty_perc += 1
thirty_perc += 1
fourty_perc += 1
fifty_perc += 1
elif value <= 0.2:
twenty_perc += 1
thirty_perc += 1
fourty_perc += 1
fifty_perc += 1
elif value <= 0.3:
thirty_perc += 1
fourty_perc += 1
fifty_perc += 1
elif value <= 0.4:
fourty_perc += 1
fifty_perc += 1
elif value <= 0.5:
fifty_perc += 1
else:
over_fifty += 1
print("Sub 1%: {0:.2f}%".format(one_perc/total_length*100))
print("Sub 5%: {0:.2f}%".format(five_perc/total_length*100))
print("Sub 10%: {0:.2f}%".format(ten_perc/total_length*100))
print("Sub 15%: {0:.2f}%".format(fifteen_perc/total_length*100))
print("Sub 20%: {0:.2f}%".format(twenty_perc/total_length*100))
print("Sub 30%: {0:.2f}%".format(thirty_perc/total_length*100))
print("Sub 40%: {0:.2f}%".format(fourty_perc/total_length*100))
print("Sub 50%: {0:.2f}%".format(fifty_perc/total_length*100))
print("Over 50%: {0:.2f}%".format(over_fifty/total_length*100))
And the output I'm looking for is this:
error_distribution(error_dataset1)
Output:
Sub 1%: 16.55%
Sub 5%: 56.61%
Sub 10%: 71.62%
Sub 15%: 78.53%
Sub 20%: 82.97%
Sub 30%: 88.46%
Sub 40%: 91.09%
Sub 50%: 92.59%
Over 50%: 7.41%
Does anyone know of a standard library that could do this?
Can you try the following:
import numpy as np
arr = np.random.uniform(low=0, high=100, size=(200,))
count, division = np.histogram(arr, bins=[0, .01, 0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 1])
print(count, division)

Categories