Think Python exercise 6.1 - python

This is an exercise 6.1 in the book "Think Python". The question is to find the print result.
This is what I can get so far.
x = 1, y = 2
bring to a(x, y), return 4
b(z), return z**2 + z
I couldn't find the valve z from c(x, y, z) function.
def b(z):
prod = a(z, z)
print(z, prod)
return prod
def a(x, y):
x = x + 1
return x * y
def c(x, y, z):
total = x + y + z
square = b(total)**2
return square
x = 1
y = x + 1
print(c(x, y+3, x+y))

The x and y in def a(x, y): are not the same x and y defined elsewhere in the script. It might as well say def a(j, k):. When you see prod = a(z, z), you need to know what the value of z is, and then go to the definition of def a(j, k): and think j = z and k = z.
If we just tell you what the output is, then you wouldn't learn to "Think Python"

Related

Count collisions in n-Queens problem in Python

I started working on python for AI and I'm having some problems:
I have an n- Queens problem here is a detailed explanation of the problem
The fitness function receives a an array of the form:
decoded = [3, 1, 2, 5 ... n]
where the element corresponds to the X coordinate and the index corresponds to the Y coordinate
i.e. taking the coordinates from the example above:
# [X, Y]
pairCoords = [[3,0], [1, 1], [2, 2], [5, 1], ... [n, z]]
so I have the fitness function which recieves a similar array to the first example.
var record starts with the max number of collisions n(n-1)* and decreases with each collision found
def fitness(self, decodedGenes):
record = self.numeroN * (self.numeroN-1)
for y in range(len(decodedGenes)):
if self.positionIsAtacking(decodedGenes, decodedGenes[y], y):
record = record - 1
return record
so a best case world return n(n-1)* and a worst case would return 0
the auxiliar function it calls checks a given X and Y coordinates and returns if there is a collision but it's not working
def positionIsAtacking(self, coords, X, Y):
for i in range(len(coords)):
# Check Y
if (coords[i] == Y):
return True
# Check Diagonals
if (coords[i] - Y == i - X):
return True
if (coords[i] - Y == X - i):
return True
return False
I have tried changing the parameters but I do not know where to search anymore I think the second function doesn`t work or maybe y changed x and y
def fitness(self, cromosoma):
record = self.numeroN * (self.numeroN - 1)
for row in range(len(board)):
decodedGenes.append(self.decodeGene(board[row]))
for y in range(len(decodedGenes)):
x = decodedGenes[y]
record = record - self.collisions(decodedGenes, x, y)
return record
def collisions(self, coords, X, Y):
board = []
r = 0
for i in range(len(coords)):
board.append([0] * self.numeroN)
for y in range(len(coords)):
board[y][coords[y]] = 1
for y in range(len(board)):
for x in range(len(board)):
# if has Queen and is not the same
if board[y][x] == 1 and y != Y:
# check x
if x == X:
r = r + 1
# check Diagonals
if self.crash_diagonal(x, y, X, Y):
r = r + 1
return r
def crash_diagonal(self, x1, y1, x2, y2):
dx = abs(x1 - x2)
dy = abs(y1 - y2)
return dx == dy

Picking classes based on given parameters [duplicate]

This question already has answers here:
pick a subclass based on a parameter
(4 answers)
Closed 7 years ago.
So i have a class:
class Unit(object):
def __init__(self, name, x , y, z):
self.name = name
self.strength = x + y
self.intelligence = x + z
self.speed = y + z - x
and two species of these Units
class Red(Unit):
def __init__(self, name, x, y, z):
Unit.__init__(self,name, x, y, z)
self.strength = self.strength * 2
class Blue(Unit):
def__init__(self, name, x, y, z):
Unit.__init__(self, name, x, y, z)
self.speed = self.speed * 2
I want the race to be decided based on what x, y, z, was used as input (z > x means the unit belongs to class Red and x > z means the unit belongs to class Blue) without having to set one before hand, how do I do this?
You could create function for that:
def builder(name, x, y, z):
if z > x:
return Red(name, x, y, z)
elif x > z:
return Blue(name, x, y, z)
You can set the __class__ attribute in your __init__:
class Unit(object):
def __init__(self, name, x , y, z):
self.name = name
self.strength = x + y
self.intelligence = x + z
self.speed = y + z - x
if z > x:
self.__class__ = Red
else:
self.__class__ = Blue
red = Unit("foo", 1,2,3)
blue = Unit("bar", 3,2,1)
You can also create a factory method that instantiates the appropriate class. You can do this as a stand-alone function, or you could make a class method. Here's the stand-alone version:
def unit_factory(name, x, y, z):
if x > z:
return Red(name, x, y, z)
return Blue(name, x, y, z)
red = unit_factory("foo", 1, 2, 3)
blue = unit_factory("bar", 3, 2, 1)

efficient sign function in python for case of periodic boundary conditions

I have cython code I'm using to speed up a bottleneck in an otherwise pure python calculation. I have a pair of points in a periodic box of length Lbox (1d case is fine for this question). I need to compute the sign of y-x, and I need to flip this sign when the periodic boundary conditions are operative.
In the absence of PBCs, the following question provides the solution: Is there a standard sign function (signum, sgn) in C/C++?. That solution is what I use to compute the sgn function.
def sgn(x, y):
""" If x > y, returns 1.
If x < y, returns -1.
If x == y, returns 0.
"""
return (y < x) - (x < y)
The sgn_pbc function as written below returns the correct result, but is written inefficiently: the control flow within the sgn_pbc is the culprit for slowing down the PBC version. How can I write sgn_pbc in an analogous way to the sgn function, so that I avoid the clumsy control flow?
def sgn_pbc(x, y, Lbox):
d = abs(x-y)
if d <= Lbox/2.:
return sgn(x, y)
else:
return -1*sgn(x, y)
First,
-1*sgn(x, y) == sgn(y, x)
then,
def sgn_pbc(x, y, Lbox):
d = abs(x-y)
if d <= Lbox/2.:
return sgn(x, y)
else:
return sgn(y, x)
Also in Python, function calls are the most expensive operations. You can inline your sgn.
def sgn_pbc(x, y, Lbox):
d = abs(x-y)
if d <= Lbox/2.:
return (y < x) - (x < y)
else:
return (x < y) - (y < x)
But then the if can be (mostly) rewritten as:
def sgn_pbc(x, y, Lbox):
d = abs(x-y)
w = sgn(Lbox/2., d)
return w * sgn(x, y)
And again, inlining the sgn,
def sgn_pbc(x, y, Lbox):
d = abs(x-y)
w = sgn(Lbox/2., d)
return w * (y < x) - (x < y)
I say mostly because the case where d == Lbox/2. this returns a wrong value.
Haven't timed it, though.

A bijective function from N*N*N to N

Can anyone help me in finding a bijective mathematical function from N * N * N → N that takes three parameters x, y, and z and returns a number n?
I would like to know the function f and its inverse f' in a way that if I have n I will be able to determine x, y, z by applying f'(n).
Defining f as a composition of a simpler function g
Suppose g is a bijection from N × N to N and let g-1 be its inverse. Then we can define f in terms of g as follows.
f(x, y, z) = g(g(x, y), z) = n
f-1(n) = (x, y, z) where g-1(n) = (w, z) and g-1(w) = (x, y)
Defining g as a bijection from N × N to N
We now have the much simpler problem of defining g.
g(x, y) = (x + y)(x + y + 1) / 2 + y = n
g-1(n) = (x, y) where m = ⌊(2n)1/2⌋ and exactly one of the following two conditions hold.
x + y = m and y = n - m(m + 1) / 2
x + y = m - 1 and y = n - m(m - 1) / 2
Python implementation
def f(x, y, z):
return g(g(x, y), z)
def f_inv(n):
w, z = g_inv(n)
x, y = g_inv(w)
return (x, y, z)
def g(x, y):
return (x + y) * (x + y + 1) / 2 + y
def g_inv(n):
m = math.floor(math.sqrt(2 * n))
while True:
y = n - m * (m + 1) / 2
if y >= 0:
break
m -= 1
x = m - y
return x, y
your function is not surjective, let p is a prime number, we can't find any x,y,z in N such that p=2^x3^y5^z...
F(x,y,z) = 2^x*3^y*5^z
In fact you can choose any distinct set of prime numbers. And inverse is simply by factorizing to corresponding prime factors.

"Properly" organise (spread out) x and y data

Not really sure how to word this question, so I will give an example of what I want.
I have two variables xsteps and ysteps.
If xsteps is 4 and ysteps is 2, then I would like a variable result to be "x, x, y, x, x, y"
If xsteps is 10 and ysteps is 5, then I would like result to be
"x, x, y, x, x, y, x, x, y, x, x, y, x, x, y"
If xsteps is 15 and ysteps is 5 then I would like result to be "x, x, x, y, x, x, x, y, x, x, x, y, x, x, x, y, x, x, x, y"
If xsteps is 1 and ysteps is 6, I would like result to be "x, y, y, y, y, y, y"
If xsteps is 4 and ysteps is 4, I would like result to be "x, y, x, y, x, y, x, y"
If xsteps is 10 and ysteps is 4, I would like result to be "x, x, y, x, x, y, x, x, y, x, x, y, x, x"
Xsteps and ysteps are not always easily divisible. If they do not divide, then I would just like them to be kind of separated out. It does not need to be perfect, just so it spreads them out reasonable well.
Really, I need the xsteps and ysteps variables organised into one variable that spreads them out.
You can try something like this:
from __future__ import division
def spreadout(X, Y):
ratio = len(X) / len(Y)
result = []
while X or Y:
if not Y or len(X)/len(Y) >= ratio:
result.append(X.pop())
else:
result.append(Y.pop())
return result
The idea behind the algorithm is to determine the ratio of the X andY lists and to alternately pop elements from either of the lists to keep the ratio in the result list similar.
This implementaiton works with lists of arbitrary elements and will return the result as a list. If you want just your x,y string, the code can be simplified and optimized some, e.g. using len this often would be wasteful is you have very long lists of xs and ys. Or you can just write a wrapper for that:
def xy_wrapper(x, y):
return ",".join(spreadout(['x'] * x, ['y'] * y))
Example Output:
>>> spreadout(range(6), list("ABC"))
[5, 'C', 4, 3, 'B', 2, 1, 'A', 0]
>>> xy_wrapper(5, 17)
'x,y,y,y,y,x,y,y,y,x,y,y,y,y,x,y,y,y,x,y,y,y'
def spread_generator(xsteps, ysteps):
ratio = xsteps / ysteps
while xsteps > 0 or ysteps > 0:
if xsteps > ratio * ysteps:
yield "x"
xsteps -= 1
else:
yield "y"
ysteps -= 1
xsteps = 7
ysteps = 3
result = [x for x in spread_generator(xsteps, ysteps)]
# Next line will make result variable hold desired value
result.reverse()
print result
# ['x', 'x', 'y', 'x', 'x', 'y', 'x', 'x', 'y', 'x']
# And if you want string
result_as_str = ",".join(result)
print result_as_str
# x,x,y,x,x,y,x,x,y,x
The crucial value is the ratio between x and y steps.
The list is reversed in the beginning, so we reverse it.
Remember that list.reverse() modifies the list in place and returns None.
Looks like someone beat me to the punch with a much nicer response, but I've written it now!
This would do close to what you want, but your example for (10, 4) doesn't work the way you have specified it.
def xy_spread(xsteps, ysteps):
out = []
if xsteps == 0:
out = ['y'] * ysteps
else:
y_per_x = float(ysteps) / float(xsteps)
y_budget = 0.0
for _ in xrange(xsteps):
out.append('x')
y_budget += y_per_x
while y_budget >= 1:
y_budget -= 1
out.append('y')
return ','.join(out)
Not necessarily pretty, but functional.
Basically it seems you want to split the xsteps into chunks, and intersperse a "y" between the chunks until either the x's or y's run out.
def get_chunks(mylist, n):
"""
Adapted from:
http://www.how2code.co.uk/2013/04/how-to-split-a-list-into-chunks-in-python/
"""
if n == 0:
return mylist
else:
return [mylist[x:x+n] for x in range(0, len(mylist), n)]
def combine(xs=0, ys=0):
"""
>>> combine(xs=4, ys=2)
x,x,y,x,x,y
>>> combine(xs=10, ys=5)
x,x,y,x,x,y,x,x,y,x,x,y,x,x,y
>>> combine(xs=15, ys=5)
x,x,x,y,x,x,x,y,x,x,x,y,x,x,x,y,x,x,x,y
>>> combine(xs=1, ys=6)
x,y,y,y,y,y,y
>>> combine(xs=4, ys=4)
x,y,x,y,x,y,x,y
>>> combine(xs=10, ys=4)
x,x,y,x,x,y,x,x,y,x,x,y,x,x
"""
output = list()
x = ['x'] * xs
y = ['y'] * ys
step = xs // ys
xchunks = get_chunks(x, step)
while xchunks or y:
if xchunks:
output += xchunks.pop()
if y:
output += y.pop()
print ','.join(output)

Categories