Ignoring zero division error - python

I'm writing a program that reads integer values from an input file, divides the numbers, then writes percentages to an output file. Some of the values that my program may be zero, and bring up a 0/0 or 4/0 occasion.
From here, I get a Zerodivisionerror, is there a way to ignore this error so that it simply prints 0%??
Thanks.

The easiest option is to check if divisor is 0 and if that's the case skip the division and just use 0 as result:
n = [(1, 3), (5, 2), (0, 0), (3, 3), (4, 0)]
res = [x / float(y) if y else 0 for x, y in n] # [0.3333333333333333, 2.5, 0, 1.0, 0]
Other option is to catch ZeroDivisionError with try/except:
res = []
for x, y in n:
try:
res.append(x / float(y))
except ZeroDivisionError:
res.append(0)

Related

How to compare two numbers with tolerance?

I have been struggling with this part of my code. I created a function with three parameters, two of which are the numbers being compared and the third is the allowed tolerance. I can compare the two numbers if the tolerance is zero but how would I be able to test them with a tolerance not equal to zero?
For example:
function_name((1, 2, 3), (1, 2, 3), 0)) #Should return True
function_name((1, 2, 3), (1, 3, 3), 0)) #Should return False
function_name((1, 2, 3), (1, 3, 3), 1)) #Should return True
For tolerance 0:
if tolerance == 0:
if t1 == t2:
return True
else:
return False
If you want the tolerance between the two whole tuples to be equal or less then the tolerance, this function should suffice:
import numpy as np
def bar(t1, t2, tolerance):
off = abs((np.array(t1)-np.array(t2))).sum()
return True if off <= tolerance else False
If you mean to check if the difference between each element in the two tuples is less then the tolerance, this works:
def bar(t1, t2, tolerance):
for e1, e2 in zip(t1, t2):
if (abs(e1-e2) > tolerance): return False
return True

Is there a simpler approach to store tic-tac-toe state as an integer using binary literals?

The following code allows me to persist the complete tic-tac-toe state as a single integer by converting the numpy array to a binary string. Each cell can be 0, 1 or 2 and therefore keeps 2 bits to represent them and then I concatenate them somehow.
import numpy as np
def convert_to_int(state):
binary = "0b"
for x in range(0, state.shape[0]):
for y in range(0, state.shape[1]):
binary += format(state[x, y].item(), '02b')
return int(binary, 0)
def convert_to_numpy(state):
cells = []
binary_string = "{0:b}".format(state).zfill(18)
for i in range(0, len(binary_string), 2):
cells.append(int(binary_string[i: i + 2], 2))
return np.array(cells).reshape((3, 3))
input_state = np.array((
(1, 2, 1),
(0, 0, 0),
(0, 0, 0)),
dtype="int32")
state_as_int = convert_to_int(input_state)
output_state = convert_to_numpy(state_as_int)
print(state_as_int)
print(output_state)
102400
[[1 2 1]
[0 0 0]
[0 0 0]]
How can I simplify the code. Is there a way to use only binary literals and bitwise operators without using string conversion?
Thank you for asking this question. I have been ignoring numpy, and this problem is an excuse to learn.
This answer uses shifting to convert to integer and vice versa.
import numpy as np
def convert_to_int(state):
a = 0
for num in state.reshape(9):
a = a + num
a = a << 2
return a
def convert_state_to_numpy(state):
cells = []
for i in range(9) :
state >>= 2
cells.insert(0,(3 & state))
return np.array(cells).reshape((3,3))
input_state = np.array((
(1, 2, 1),
(0, 0, 0),
(0, 0, 0)),
dtype="int32")
state_as_int = convert_to_int(input_state)
output_state = convert_state_to_numpy(state_as_int)
print(hex(state_as_int))
print(output_state)
This was a fun problem. Here's what I came up with:
import numpy as np
def convert_to_int(state):
binary = 0b0
for x in range(3):
for y in range(3):
binary <<= 2
binary += state[x, y].item()
return binary
def convert_to_numpy(state):
return np.array([(state & (2**(2*i + 1) + 2**(2*i))) >> 2*i for i in range(8, -1, -1)]).reshape(3, 3)
This should avoid the string conversion, and is hopefully a tad bit faster (though I didn't do any benchmarks).
I wonder if there's away to store numbers of any base in python, since you could store this as a 9 bit number in base 3...
Instead of each cell as a 32bit integer you could use two integers and store the positions as bit flags. Say for example:
Os = 0b000100000
Xs = 0b100000001
X _ _
_ _ O
_ _ X
I was intrigued by a previous comment about using base 3 numbers. Since your original question was looking for a way to compress a 3x3 array into a single integer, I will assume that you want to reduce the size of the data. The following code takes your array which may be viewed as a 9 digit base 3 number and converts it to 15 bit integer. This number is stored as an array of 2 bytes. This may be beyond the scope of your original question but, i think, it follows the spirit of the question.
import numpy as np
def encode_state(state):
a=0
for i,num in enumerate(state.reshape(9)) :
a = a + 3**i * int(num)
return a.to_bytes(2,'big')
def decode_state(byte):
encoded_value = int.from_bytes(byte,'big')
b = [0 for i in range(9)]
for i in range(9) :
num = (encoded_value // 3**i) % 3
b[i] = num
return np.array(b).reshape(3,3)
input_state = np.array((
(2, 2, 2),
(1, 2, 2),
(2, 1, 0)),
dtype="int32")
state_as_byte = encode_state(input_state)
output_state = decode_state(state_as_byte)
print (''.join('{:02x}'.format(x) for x in state_as_byte))
print(output_state)

Complex operations with Python (pygame.math.Vector2)

I'm learning Python and came across a complex expression that derives from pygame.Vector2:
import pygame
x = pygame.math.Vector2 (1,2)
b = x * 5 - (1, 2)
print (x)
print (b)
Result:
[1,2]
[4,8]
In the above case, the same x * 5 operation is performed both for the 1 and 2 values of Vector2, resulting in (5, 10) respectively; and then both results are subtracted from the tuple (1, 2), resulting in [4,8]
However if I do assign a simple tuple to x: x = (1, 2), instead of Vector2, I get the error:
TypeError: unsupported operand type (s) for -: 'tuple' and 'tuple'
My question is: At what times in Python I can perform these complex operations?
Can do something like (see comments too):
x = (1,2) # create a `tuple`
b = map(lambda x: x * 5,x) # do a `map` object for multiplying 5 to all of them
print(x) # print the `tuple`
t=iter((1,2)) # do an generator object using `iter`, so able to use `next` to access every next element
print(tuple(map(lambda x: x-next(t),b))) # do the `next` and another `map`, to subtract as you wanted
Best thing is still to create a class:
from __future__ import division
class MyClass:
def __init__(self,t):
self.t=t
def __mul__(self,other):
return MyClass(tuple(map(lambda x: x*other,self.t)))
def __truediv__(self,other):
return MyClass(tuple(map(lambda x: x/other,self.t)))
def __sub__(self,other):
gen=iter(other)
return MyClass(tuple(map(lambda x: x-next(gen),self.t)))
def __add__(self,other):
gen=iter(other)
return MyClass(tuple(map(lambda x: x+next(gen),self.t)))
def __repr__(self):
return str(tuple(self.t))
Then now can do anything:
x = MyClass((1,2))
b = x*5
print(b)
print(b-(1,2))
Output:
(5, 10)
(4, 8)
Also can do addition:
x = MyClass((1,2))
b = x*5
print(b)
print(b-(1,2)+(3,4))
Output:
(5, 10)
(7, 12)
Also division:
x = MyClass((1,2))
b = x*5
print(b)
print((b-(1,2)+(3,4))/2)
Output:
(5, 10)
(3.5, 6.0)

check validation for input for perfect maze

I'm working on a project to build a perfect maze.
I have a class Maze and a class Cell which represents each square in a maze. In my Cell class, I have four Boolean variable(north, south, east, west) to represent whether there is a wall at north or south.. of cell. There is also a boolean variable named visit to check if the cell has been visited. Here is my code for the init() for Cell class.
def __init__(self):
self.north = True
self.south = True
self.east = True
self.west = True
self.visit = False
And for the Maze class, I have self.maze(a bunch of Cell) and the self.size = N(build a N*N maze).
Here is the init() for class Maze:
def __init__(self, N):
self.size = N
self.maze = [[i for i in range(N + 2)] for i in range(N + 2)]
for r in range(self.size + 2):
for c in range(self.size + 2):
self.maze[r][c] = Cell()
While I'm updating the index of maze, I wrote two function to check whether the newX and newY is in the range of 1 <= x <= self.size and 1 <= y <= self.size, also whether the cell has been visited.
Here is the code:
def in_range(self, x, y):
if 1 <= x <= self.size and 1 <= y <= self.size:
return True
else:
return False
def is_valid(self, x, y):
if not self.maze[x][y].getVisit() and self.in_range(x,y):
return True
else:
return False
After all this, I wrote the main structure:
def walk(self, s, x, y):
neighbor = [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]
if s.size() == self.size**2: return
else:
while True:
new = choice(neighbor)#choice() is import from random
#print(self.is_valid(new[0], new[1]))
if self.is_valid(new[0], new[1]):break
else:
if len(neighbor) != 0:
neighbor.remove(new)
new = choice(neighbor)
else:
temp = s.pop(s)
self.walk(s, temp[0], temp[1])
break
print(new)
However, running my code stills give me index that is not between 1 and self.size. I couldn't figure out why, I think my checking algorithm works fine.
Here is what I got:
>>> ================================ RESTART
================================
>>>
>>> a = Maze(5)
>>> a.search()
1 2
(1, 3)
(2, 3)
(2, 4)
(1, 4)
(2, 4)
(2, 5)
(3, 5)
(4, 5)
(4, 4)
(4, 3)
(3, 3)
(3, 2)
(2, 2)
(2, 1)
(1, 1)
(0, 1)
(-1, 1)
(0, 1)
(1, 1)
(0, 1)
(-1, 1)
(-1, 2)
(-1, 1)
(0, 1)
Can someone help me out? plz, really appreciate!
In Python range starts with 0 if you don't specify another start position. Thus, when you initialize your maze, you have cells in (0, *) and (*, 0):
for r in range(self.size + 2):
for c in range(self.size + 2):
self.maze[r][c] = Cell()
When you compute your neighbors you don't check that you don't get out:
neighbor = [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]
And it's only after having assigned new to such a coordinates that you check it is valid. But then, if it is not valid and there is no neighbors, you're calling walk again. You should try to check for in_range independently of visit.
Also your loop can only run once because either new is valid and you break out of the loop or it is not valid and you break out of the loop.
Finally, you forgot to give us the search function and what s is (and s.pop(s) looks funny as usually the argument of pop is an index, not the sequence again).
You could have found this by looking closely at walk(), or splattering it with print statements to trace things.
Things are going wrong at the extremities of your grid (when either x or y == 0 or N-1). Unless you're allowing wraparound, I assume your grid initialization puts walls on the north of the grid(y==0), south, east and west.
By the way, your grid has two unnecessary rows and columns: if you want N cells, numbered O..(N-1), then use range(N), not range(N+2), Or else use range(1,N+1). (Do you pad any unneeded cells with valid==False?)
Anyway, walk() first picks a random neighbor cell and breaks out of the while-loop if it is a valid cell. But if it isn't, it cheerfully picks any remaining neighbor cell (regardless whether valid) and soldiers on. That's your bug. Always test validity.
If it has run out of valid neighbor cells, it backtracks by doing s.pop(s). s.pop(s) also looks like a bug. Why not s.pop()?
Btw, call the variable path instead of s.
Also, this is only checking the coords for validity; you never actually check if you've visited that cell before, so there's no end condition to your recursive backtracking; you could very easily go in loops.
You could help yourself a lot if you refactored walk() into using a separate generator get_random_valid_neighbor() which returns randomly-chosen neighbors already tested as valid (and None when you run out of neighbors).
def walk(self, s, x, y):
...
while True:
new = choice(neighbor)
if self.is_valid(new[0], new[1]):break # tested for validity
else:
if len(neighbor) != 0:
neighbor.remove(new)
new = choice(neighbor) # BUG: never tested for validity
...

Finding percentage of nonempty string

I am trying to write code in Python which finds the percentage of the alphabet in a given string. For example,
percent("ab", "aabccdef") should give [("a", 25), ("b", 13)] since 'a' occurs twice in a string of length 8, so its percentage is round(2 / 8), or 25.
Similarly, 'b' occurs only once. So its percentage is round(1 / 8), or 13.
Here is my code. Can someone help me debug this?
def Percent(alpha, string):
y = [e for e in string if e == alpha]
x = len(y)
return (alpha, round((x / len(string) * 100)))
You were close but the key difference is that you need to compute it for each character c in alpha:
def percent(alpha, string):
results = []
for c in alpha:
y = [e for e in string if e == c]
x = len(y)
results.append((c, round((float(x) / len(string)*100))))
return results
In your code you're comparing e == alpha but alpha is a string ab and e is a single character in the string. This won't give you the results you want.
Furthermore, you need to convert x to a float if you wish to compute the percentage properly. In Python if you write, e.g., 3 / 4 you'll get 0 instead of 0.75. To prevent this you need to convert at least one of the arguments to a float which can be done by calling float(). So you could also write x / float(len(string)*100) to ensure you won't get an integer as result.
Another way to do this, you can use str.count in a list comprehension:
>>> alpha = 'ab'
>>> string = 'aabccdef'
>>> [(x, string.count(x)/len(string)) for x in alpha]
[('a', 0.25), ('b', 0.125)]

Categories

Resources