I'm looking for a method to have a variable number of nested for loops instead of the following code. For example if the variable n represents the number of nested for loops and n = 3, my code would be:
p = []
for i in range(26):
for j in range(26):
for k in range(26):
p.append([i,j,k])
Instead, if n = 2 my code would be:
p = []
for i in range(26):
for j in range(26):
p.append([i,j])
I understand this can be done using recursion but I'm a bit confused as to how I'd go about doing this.
It's important for one to develop the skills to reason about these problems. In this case, Python includes itertools.product but what happens the next time you need to write a behaviour specific to your program? Will there be another magical built-in function? Maybe someone else will have published a 3rd party library to solve your problem?
Below, we design product as a simple recursive function that accepts 1 or more lists.
def product (first, *rest):
if not rest:
for x in first:
yield (x,)
else:
for p in product (*rest):
for x in first:
yield (x, *p)
for p in product (range(2), range(2), range(2)):
print ('x: %d, y: %d z: %d' % p)
# x: 0, y: 0 z: 0
# x: 1, y: 0 z: 0
# x: 0, y: 1 z: 0
# x: 1, y: 1 z: 0
# x: 0, y: 0 z: 1
# x: 1, y: 0 z: 1
# x: 0, y: 1 z: 1
# x: 1, y: 1 z: 1
Assuming you want a more conventional iteration ordering, you can accomplish do so by using an auxiliary loop helper
def product (first, *rest):
def loop (acc, first, *rest):
if not rest:
for x in first:
yield (*acc, x)
else:
for x in first:
yield from loop ((*acc, x), *rest)
return loop ((), first, *rest)
for p in product (range(2), range(2), range(2)):
print ('x: %d, y: %d z: %d' % p)
# x: 0, y: 0 z: 0
# x: 0, y: 0 z: 1
# x: 0, y: 1 z: 0
# x: 0, y: 1 z: 1
# x: 1, y: 0 z: 0
# x: 1, y: 0 z: 1
# x: 1, y: 1 z: 0
# x: 1, y: 1 z: 1
Something like this should work:
import itertools
n=3
fixed=26
p = list(itertools.product(range(fixed), repeat=n))
This solution uses the optimized functions of itertools, so it should be quite fast.
Mind that itertools.product returns an iterator, so one needs to transform it to get an array.
Related
First of all, I`m sorry if I might ask this question and if it was already answered somewhere else. I couldnt find any solution for the following Problem:
I want to create a list where I apply multiple restricions. But instead of using over hundreads of if statements i just want to use a dictionary in one if statement to apply the requirements. So to say I want to use the keys of the dictionary as requirements and its values as factors for the data.
Lets take a look at a small example:
I want to create data for a countourplot where x/y range from [-50,50] in steps of 1 and the z function has requirements based on the if statements:
The following code is what works, but the more requirements I add the longer and more unreadalbe the code gets:
x = np.linspace(-50 , 50, 100)
y = np.linspace(-50 , 50, 100)
z = []
z_0 = 100
for i in x:
for j in y:
if i**2 + j**2 <= 10**2:
z.append(1.9 * z_0)
elif i**2 + j**2 <= 20**2:
z.append(1.5 * z_0)
elif i**2 + j**2 <= 30**2:
z.append(1.4 * z_0)
elif i**2 + j**2 <= 40**2:
z.append(1.05 * z_0)
else
z.append(z_0)
This would create a map with radial decreasing hight as a function of z on different positions. Is it possible to do this in the following way which is way less redundant? My main problem is how to assing the correct value.
x = np.linspace(-50 , 50, 100)
y = np.linspace(-50 , 50, 100)
z = []
requirements_dict = {10:1,9, 20:1.5, 30:1.4, 40:1.05}
z_0 = 100
for i in x:
for j in y:
if i**2 + j**2 <= (each key of the requirements_dict) :
z.append( (corresponding value of the requirements dict) * z_0)
else
z.append(z_0)
Thanks in advance for the help and sorry again if this question was already asked.
Is this what you're looking for?
EDIT:
import numpy as np
x = np.linspace(-50 , 50, 100)
y = np.linspace(-50 , 50, 100)
z = []
requirements_dict = {10: 1.9, 20: 1.5, 30: 1.4, 40: 1.05}
z_0 = 100
for i in x:
for j in y:
for key, value in requirements_dict.items():
if i**2 + j**2 <= key:
z.append(value * z_0)
break
else:
z.append(z_0)
I have used the following code in python2 to encrypt the Radius Password attribue:
def Encrypt_Pass(password, authenticator, secret):
m = md5()
m.update(secret + authenticator)
return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(password.ljust(16, '\0')[:16], m.digest()[:16]))
That does not work in python3, error for m.update line:
TypeError: Unicode-objects must be encoded before hashing
After i do add encoding:
def Encrypt_Pass(password, authenticator, secret):
m = md5()
m.update(secret.encode('ascii') + authenticator.encode('ascii'))
return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(password.ljust(16, '\0')[:16], m.digest()[:16]))
I do still fail with:
TypeError: ord() expected string of length 1, but int found
Now i am lost and forget the details of the algorithm, are you able to help ? How to change that last line to work with python3 ? (working perfectly fine for python2).
Update: I've did troubleshooting, with the code like this:
m = md5()
m.update(secret.encode('ascii') + authenticator.encode('ascii'))
print("Secret {}, encode {}".format(secret,secret.encode('ascii')))
print("auth {}, encode {}".format(authenticator, authenticator.encode('ascii')))
print("m digest: {}".format(m.digest()[:16]))
print("passwd: {}".format(password.ljust(16, '\0')[:16]))
#return "".join(chr(ord(x) ^ y) for x, y in zip(password.ljust(16, '\0')[:16], m.digest()[:16]))
for x, y in zip(password.ljust(16, '\0')[:16], m.digest()[:16]):
print("JOIN ord x: {} y: {}".format(ord(x),y))
a = "".join(chr(ord(x) ^ y))
print("a: {}".format(chr(ord(x) ^ y)))
i got:
Secret cisco, encode b'cisco'
auth 5002CVWVKCX13QTN, encode b'5002CVWVKCX13QTN'
m digest: b'\xf8\xb9\xc2\x1foZ~h\xff#,\x87\x07\xcc:m'
passwd: cisco
JOIN ord x: 99 y: 248
a:
JOIN ord x: 105 y: 185
a: Ð
JOIN ord x: 115 y: 194
a: ±
JOIN ord x: 99 y: 31
a: |
JOIN ord x: 111 y: 111
a:
JOIN ord x: 0 y: 90
a: Z
JOIN ord x: 0 y: 126
a: ~
JOIN ord x: 0 y: 104
a: h
JOIN ord x: 0 y: 255
a: ÿ
JOIN ord x: 0 y: 64
a: #
JOIN ord x: 0 y: 44
a: ,
JOIN ord x: 0 y: 135
a:
JOIN ord x: 0 y: 7
a:
JOIN ord x: 0 y: 204
a: Ì
JOIN ord x: 0 y: 58
a: :
JOIN ord x: 0 y: 109
a: m
So it looks like instead of ord(y) i just have to use y ? But even with that password is still encoded incorrectly with python3 :(
I have a variable s and i want to divide that variable with the number of inputs there are. I am a beginner, can anyone tell me the code that can perform that action?
I haven't tried anything because i don't know the specific code that can perform that action.
x = int(input("Insert x: "))
y = int(input("Insert y: "))
s = x + y
print(s/number of inputs)
I expect the output of s/number of inputs.
Not sure why this is needed but you can define your own function that inputs and increments a global counter:
number_of_inputs = 0
def my_input(msg):
global number_of_inputs
x = input(msg)
number_of_inputs += 1
return x
x = int(my_input("Insert x: "))
y = int(my_input("Insert y: "))
s = x + y
print(s / number_of_inputs)
Input:
Insert x: 10
Insert y: 20
Output:
15.0
I have a very simple use case in which i have a list of names and i have to calculate the total length of all the words in the names list. Below is my code base but it does not work the way i expect :
In [13]: names = ['John', 'Arya', 'Maya', 'Mary']
In [14]: from functools import reduce
In [15]: check = reduce(lambda x, y: len(x) + len(y), names)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-15-39802d43150a> in <module>
----> 1 check = reduce(lambda x, y: len(x) + len(y), names)
<ipython-input-15-39802d43150a> in <lambda>(x, y)
----> 1 check = reduce(lambda x, y: len(x) + len(y), names)
TypeError: object of type 'int' has no len()
Can someone please point out where i am going wrong .
For completeness thought I'd also show map, a more functional approach:
total_length = sum(map(len, names))
Just use a generator expression with sum. reduce will only sometimes be better or clearer for specific use cases.
names = ['John', 'Arya', 'Maya', 'Mary']
total_length = sum(len(name) for name in names)
If you do want to use reduce, the first parameter is the accumulated value and the second is the next element of the list. You'll need to provide a starting value and only call len on the your y value:
total_length = reduce(lambda x, y: x + len(y), names, 0)
Here's a pure-python implementation of reduce():
>>> def reduce(fun, seq, initial=0):
... acc = initial
... for item in seq:
... acc = fun(acc, item)
... return acc
We can see that fun() receives the accumulator and the current value from seq. This is apparent when you trace the execution:
>>> def foo(x, y):
... print("foo(%s, %s) -> %s" % (x, y, x+y))
... return x+y
...
>>> reduce(foo, range(6))
foo(0, 1) -> 1
foo(1, 2) -> 3
foo(3, 3) -> 6
foo(6, 4) -> 10
foo(10, 5) -> 15
15
I have a query. In Pyspark when we need to get total(SUM) based on (Key,Value), our query reads like:
RDD1 = RDD.reduceByKey(lambda x , y: x + y)
where as when we need to find MAX / MIN value for (Key,Value) our query reads like
RDD1 = RDD.reduceByKey(lambda x , y: x if x[1] >= y[1] else y)
Why when we Sum data not using x[1], Y[1], where as same is use for MAX / MIN?. Please clarify the doubt.
Rgd's
You're wrong and you've taken this code out of context. In both cases x and y refer to values.
lambda x , y: x if x[1] >= y[1] else y
is equivalent to:
lambda x, y: max(x, y, key=lambda x: x[1])
It compares values by their second element and means that each value:
Is indexable (implements __getitem__).
Has at least two elements.
Example
sc.parallelize([(1, ("a", -3)), (1, ("b", 3))]) \
.reduceByKey(lambda x , y: x if x[1] >= y[1] else y).first()
will be (1, ('b', 3)) because 3 is larger than -3.