Related
I need to take a tuple of any length and preforming an operation to return the midpoint. However, I need to function to work with a tuple of any length so I'm not sure how to go about it.
def findMidpoint(P: tuple, Q: tuple) -> tuple:
user_input1 = input('Enter space-separated integers: ')
P = tuple(int(item) for item in user_input1.split())
user_input2 = input('Enter space-separated integers: ')
Q = tuple(int(item) for item in user_input2.split())
Midpoint
pass
def main():
# use to test the findMidpoint function
pass
if __name__ == "__main__":
main()
Okay, taking some liberties here with what you're asking, but assuming what you want is to find the midpoint of any two points in an N-dimensional space, you can average the value of each point axis-wise. For example:
P = (px, py)
Q = (qx, qy)
midpoint = ( (px + qx)*0.5, (py + qy)*0.5 )
Obviously, for more dimensions you have to extend this. A general N-dimensional solution, with your code, can make use of zip:
def findMidpoint(P: tuple, Q: tuple) -> tuple:
return tuple((q + p) / 2 for p, q in zip(P, Q))
def main():
# use to test the findMidpoint function
assert findMidpoint(P=(0, 0), Q=(2, 2)) == (1, 1)
assert findMidpoint(P=(0, 0, 0), Q=(2, 2, 2)) == (1, 1, 1)
assert findMidpoint(P=(-2, -2, -2), Q=(2, 2, 2)) == (0, 0, 0)
if __name__ == "__main__":
main()
This assumes P and Q are the same length. If they're not, you could go one further and use zip_longest:
from itertools import zip_longest
def findMidpoint(P: tuple, Q: tuple) -> tuple:
return tuple((q + p) / 2 for p, q in zip_longest(P, Q, fillvalue=0))
def main():
# use to test the findMidpoint function
assert findMidpoint(P=(0, 0), Q=(2, 2, 2)) == (1, 1, 1)
if __name__ == "__main__":
main()
This would essentially say "if no coordinate is given for an axis, assume it is zero".
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
I'm trying to solve this question:
We want to make a row of bricks that is goal inches long. We have a
number of small bricks (1 inch each) and big bricks (5 inches each).
Return True if it is possible to make the goal by choosing from the
given bricks. This is a little harder than it looks and can be done
without any loops.
make_bricks(3, 1, 8) → True
make_bricks(3, 1, 9) → False
make_bricks(3, 2, 10) → True
— codingbat.com
For that, I made this code:
def make_bricks(small, big, goal):
tam = small + big*5
ex_gran = goal - small
if goal <= small:
return True
elif ex_gran > big*5:
return False
elif ex_gran <= big * 5 and (ex_gran % 5 <= small) :
return True
else:
return False
And this is the result os the tests:
Expected Run
make_bricks(3, 1, 8) → True True OK
make_bricks(3, 1, 9) → False False OK
make_bricks(3, 2, 10) → True True OK
make_bricks(3, 2, 8) → True True OK
make_bricks(3, 2, 9) → False True X
make_bricks(6, 1, 11) → True True OK
make_bricks(6, 0, 11) → False False OK
make_bricks(1, 4, 11) → True True OK
make_bricks(0, 3, 10) → True True OK
make_bricks(1, 4, 12) → False True X
make_bricks(3, 1, 7) → True False X
make_bricks(1, 1, 7) → False False OK
make_bricks(2, 1, 7) → True True OK
make_bricks(7, 1, 11) → True True OK
make_bricks(7, 1, 8) → True True OK
make_bricks(7, 1, 13) → False False OK
make_bricks(43, 1, 46) → True True OK
make_bricks(40, 1, 46) → False False OK
make_bricks(40, 2, 47) → True True OK
make_bricks(40, 2, 50) → True True OK
make_bricks(40, 2, 52) → False False OK
make_bricks(22, 2, 33) → False False OK
make_bricks(0, 2, 10) → True True OK
make_bricks(1000000, 1000, 1000100) → True True OK
make_bricks(2, 1000000, 100003) → False True X
make_bricks(20, 0, 19) → True True OK
make_bricks(20, 0, 21) → False False OK
make_bricks(20, 4, 51) → False False OK
make_bricks(20, 4, 39) → True True OK
Only 4 of them was wrong, but I still can't figure it out the error.
What is wrong?
Try first to use as many big bricks as possible, then complete with the small ones. Note that this works because the size of the big ones is a multiple of the size of the small ones, you would need another approach if the sizes were for example 2 and 5.
def make_bricks(small, big, goal):
max_big = goal // 5 # max number of big we can use
nb_big = min(big, max_big) # big ones we really use
return small >= goal - 5 * nb_big # True if we have enough small ones to complete
Error is simple :) it lies on line 16. Although the code could be shorten a lot.
First if all, notice that condition ex_gran <= big * 5 is irrelevant since the conditional before was already false (elif ex_gran > big*5:) and we are assuming small, big and goal are all integers, so you can take that away from the code. (Althogh this is not what is bringing troubles to the code, that's more of a style remark).
Trouble is generated by this conditional: (ex_gran % 5 <= small).
As I understand, in the example make_bricks(1, 4, 12) your code returns True when it should return False. What happens is that the code checks whether (12 - 1) <= 4*5 which is True, and if (12 - 1) % 5 <= 1 which is also True and returns True in line 18 because of this.
Let's "fix" the code. Remember that from math we know there are integers m and r such that goal = 5*m + r (moreover r = goal % 5). After we know (goal-small) <= big*5 (from false evaluation in line 12) we have two cases:
Case 1: (goal - small) = big*5, which implies goal = big*5 + small and so we should return True.
Case 2: (goal - small) < big*5, then we know goal < big*5 + small. Here you should check whether (goal % 5) <= small. If this is false, then we can't arrange the bricks to obtain the goal length (since we don't have enough 1s to fill the residual, as in the example above). Otherwise, you should return True, since we have enough bricks to surpass the goal length and enough 1s to fill the residual.
Your code ends up looking like this (I took the liberty of renaming the variables):
def make_bricks(small_bricks, big_bricks, goal):
if ( (5*big_bricks + small_bricks) < goal ): #we can't reach the length
return False
elif (small_bricks < (goal%5)) : #we can surpass the length but we don't have
#enough 1s to fill goal's residual w.r.t. 5 div
return False
else: #We can reach the length and have enough 1s to fill residual
return True
notice I took away some case goal <= small as it's not needed here.
# This code works with those 3 tests but got some other one # wrong can some help fixed it?
def make_bricks(small, big, goal):
big = big * 5
if small == goal or big == goal:
return true
elif small + big == goal or big - small == goal:
return True
else:
return False
print(make_bricks(3, 1, 8)) # → True
print(make_bricks(3, 1, 9)) # → False
print(make_bricks(3, 2, 10)) # → True
This should work...
def make_bricks(small, big, goal):
total_bricks = (1 * small) + (5 * big)
if total_bricks >= goal:
if goal%5 == 0:
if goal/5 <= goal:
x = True
elif goal%5 <= small:
x = True
else:
x = False
else:
x = False
return x
This is probably not the most efficient way but it will work..
Probably Not the most Readable
def make_bricks(small, big, goal):
if (big is not 0 and (big*5+small*1 > goal) and goal % 5 <= small) or goal < small or big*5+small*1 == goal:
return True
else:
return False
def make_bricks(small, big, goal):
return small >= goal - 5*min(goal//5,big)
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
...
Is there is a simple, pythonic way of rounding to the nearest whole number without using floating point? I'd like to do the following but with integer arithmetic:
skip = int(round(1.0 * total / surplus))
==============
#John: Floating point is not reproducible across platforms. If you want your code to pass tests across different platforms then you need to avoid floating point (or add some hacky espilon stuff to your tests and hope it works). The above may be simple enough that it would be the same on most/all platforms, but I'd rather not make that determination as it is easier to avoid floating point altogether. How is that "not in the spirit of Python"?
You can do this quite simply:
(n + d // 2) // d, where n is the dividend and d is the divisor.
Alternatives like (((n << 1) // d) + 1) >> 1 or the equivalent (((n * 2) // d) + 1) // 2 may be SLOWER in recent CPythons, where an int is implemented like the old long.
The simple method does 3 variable accesses, 1 constant load, and 3 integer operations. The complicated methods do 2 variable accesses, 3 constant loads, and 4 integer operations. Integer operations are likely to take time which depends on the sizes of the numbers involved. Variable accesses of function locals don't involve "lookups".
If you are really desparate for speed, do benchmarks. Otherwise, KISS.
skip = (((total << 1) // surplus) + 1) >> 1
Shifting things left by one bit effectively multiplies by two, shifting things right by one bit divides by two rounding down. Adding one in the middle makes it so that "rounding down" is actually rounding up if the result would have been above a .5 decimal part.
It's basically the same as if you wrote...
skip = int((1.0*total/surplus) + 0.5)
except with everything multplied by 2, and then later divided by 2, which is something you can do with integer arithmetic (since bit shifts don't require floating point).
TL;DR:
q, r = divmod(total, surplus)
skip = q if q % 2 == 0 and 2*r == surplus else q + (2*r // surplus) # rounds to nearest integer; half to nearest even
This solution:
rounds to the nearest integer as demanded by OP
works for both positive and negative integers
rounds 0.5 fractional parts to nearest even integer (rnd(0.5)=0, rnd(1.5)=2) which matches the behavior of python's round function used by OP
sticks to integer arithmetic as demanded by OP (see documentation of divmod)
Full story
Inspired by zhmyh's answer answer, which is
q, r = divmod(total, surplus)
skip = q + int(bool(r)) # rounds to next greater integer (always ceiling)
, I came up with the following solution (UPDATE: that only works for non-negative total and surplus, as pointed out in the comments):
q, r = divmod(total, surplus)
skip = q + int(2 * r >= surplus) # rounds to nearest integer (floor or ceiling) if total and surplus are non-negative
Since the OP asked for rounding to the nearest whole number, zhmhs's solution is in fact slightly incorrect, because it always rounds to the next greater whole number, while my solution works as demanded works for non-negative total and surplus only. A correct solution that also works for negative numbers is:
q, r = divmod(total, surplus)
skip = q + (2 * r // surplus) # rounds to nearest integer (positive: half away from zero, negative: half toward zero)
Please note though that if 2 * r == surplus, it will basically perform ceiling for both positive and negative results, e.g. ceil(-1.5) == -1 whereas ceil(1.5) == 2. This is still correct behavior in terms of rounding to the nearest integer (because of equal distance to next lower and next greater integer) but it is asymmetrical in reference to zero. To also fix this, that is, round half away from zero, we can add a boolean condition:
q, r = divmod(total, surplus)
skip = q if q < 0 and 2*r == surplus else q + (2*r // surplus) # rounds to nearest integer; half away from zero
And even better, to round half to nearest even like python's round function used by the OP:
q, r = divmod(total, surplus)
skip = q if q % 2 == 0 and 2*r == surplus else q + (2*r // surplus) # rounds to nearest integer; half to nearest even
In case you wonder how divmod is defined: According to its documentation
For integers, the result is the same as (a // b, a % b).
We therefore stick with integer arithmetic, as demanded by the OP.
Yet another funny way:
q, r = divmod(total, surplus)
skip = q + int(bool(r))
Simply take care of the rounding rule before you ever divide. For the simplest round-half-up:
if total % surplus < surplus / 2:
return total / surplus
else:
return (total / surplus) + 1
Tweak a little bit if you need to do a proper round-to-even.
The question is the rounding strategy you are after.
Here are several that I came up with - note that integer floor and ceiling are cases, but in "round to nearest" there are many strategies. The IEEE 754 and the most professional and industrial and even elegant way of doing it is Round To Nearest Even. I've never seen a single example anywhere of doing this for integer arithmetic. You cannot go through float as the 53-bit mantissa may cause precision issues and it already applies round-to-nearest-even mode if desiring to do a different rounding strategy. The correct techniques should always stay in the integer domain
def roundNegInf(n, d): #floor
return n // d
def roundPosInf(n, d): #ceil
return (n + d + -1*(d >= 0)) // d
def roundTowardsZero(n, d):
return (n + ((d + -1*(d >=0)) if (n < 0) ^ (d < 0) else 0)) // d
def roundAwayFromZero(n, d):
return (n + (0 if (n < 0) ^ (d < 0) else (d + -1*(d >= 0)))) // d
def roundNearestPosInf(n, d):
#return (((n << 1) // d) + 1) >> 1
#return (((n * 2) // d) + 1) // 2
q, r = divmod(n, d)
return q + (2 * r <= d if d < 0 else 2 * r >= d)
def roundNearestNegInf(n, d):
q, r = divmod(n, d)
return q + (2 * r < d if d < 0 else 2 * r > d)
def roundNearestEven(n, d): #round only when for positive numbers guard, round, sticky are 11X or 1X1
q, r = divmod(n, d)
return q + (q & 1) * (2 * r == d) + ((2 * r < d) if d < 0 else (2 * r > d))
def roundNearestToZero(n, d):
q, r = divmod(n, d)
return q + (q < 0) * (2 * r == d) + ((2 * r < d) if d < 0 else (2 * r > d))
def roundNearestAwayZero(n, d):
q, r = divmod(n, d)
return q + (q >= 0) * (2 * r == d) + ((2 * r < d) if d < 0 else (2 * r > d))
def testRounding():
pairs = ((1, 2), (-1, 2), (1, -2), (-1, -2), (3, 2), (-3, 2), (3, -2), (-3, -2),
(1, 3), (-1, 3), (1, -3), (-1, -3), (2, 3), (-2, 3), (2, -3), (-2, -3))
funcs = (roundNegInf, roundPosInf, roundTowardsZero, roundAwayFromZero,
roundNearestPosInf, roundNearestNegInf,
roundNearestToZero, roundNearestAwayZero, roundNearestEven)
res = [[f(*p) for p in pairs] for f in funcs]
expected = [[0, -1, -1, 0, 1, -2, -2, 1, 0, -1, -1, 0, 0, -1, -1, 0],
[1, 0, 0, 1, 2, -1, -1, 2, 1, 0, 0, 1, 1, 0, 0, 1],
[0, 0, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, -1, -1, 1, 2, -2, -2, 2, 1, -1, -1, 1, 1, -1, -1, 1],
[1, 0, 0, 1, 2, -1, -1, 2, 0, 0, 0, 0, 1, -1, -1, 1],
[0, -1, -1, 0, 1, -2, -2, 1, 0, 0, 0, 0, 1, -1, -1, 1],
[0, 0, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 1, -1, -1, 1],
[1, -1, -1, 1, 2, -2, -2, 2, 0, 0, 0, 0, 1, -1, -1, 1],
[0, 0, 0, 0, 2, -2, -2, 2, 0, 0, 0, 0, 1, -1, -1, 1]
]
assert(all([x == y for x, y in zip(res, expected)]))
This should work too:
def rint(n):
return (int(n+.5) if n > 0 else int(n-.5))