I have a function mul(f,g)
Can anyone show me how I can make a forloop that uses mul(f,g) multiple times?
For example f=(x+1)^3 becomes mul(f,mul(f,f))
Thanks in advance!
As a for loop #Julia is right an storing the value external to the loop if the right approach:
lst = [1, 2, 3]
product = lst[0]
for n in lst:
product = mult(n, product)
However there are a few other alternatives that I want to point out, that could be useful in more complex situations. First there is concept called recursion which is helpful in many cases where you need to call the same function multiple times on or within the same data structure (in this case a list):
def pow(n, p):
"""Raise n to a power p"""
if p == 0:
return n
return n * pow(n, p)
lst = [1, 2, 3]
You may also use a function from functools to reduce a list into a single value:
import functools
lst = [1, 2, 3]
product = functools.reduce(lambda n, m: n* m, lst)
Interesting exercise. Since the mul() function keeps calling itself, this is, by definition, recursion. However, it is not the way recursion is usually done, where the base case determines the depth of recursion. Here, the depth of recursion is determined by an external for loop. Here is one way to do it:
def f(x):
return x + 1
def mul(f,g):
return(f ** g)
#To calculate (x + 1)^y where x=2 and y=3 , you write the following for loop:
x = 2
y = 3
for g in range(1, y+1):
g = mul(f(x),g)
print(g) #27
#To calculate (x + 1)^y where x=4 and y=2, you write the following for loop:
x = 4
y = 2
for g in range(1, y+1):
g = mul(f(x),g)
print(g) #25
Related
I've read that one of the key beliefs of Python is that flat > nested. However, if I have several variables counting up, what is the alternative to multiple for loops?
My code is for counting grid sums and goes as follows:
def horizontal():
for x in range(20):
for y in range(17):
temp = grid[x][y: y + 4]
sum = 0
for n in temp:
sum += int(n)
print sum # EDIT: the return instead of print was a mistype
This seems to me like it is too heavily nested. Firstly, what is considered to many nested loops in Python ( I have certainly seen 2 nested loops before). Secondly, if this is too heavily nested, what is an alternative way to write this code?
from itertools import product
def horizontal():
for x, y in product(range(20), range(17)):
print 1 + sum(int(n) for n in grid[x][y: y + 4])
You should be using the sum function. Of course you can't if you shadow it with a variable, so I changed it to my_sum
grid = [range(20) for i in range(20)]
sum(sum( 1 + sum(grid[x][y: y + 4]) for y in range(17)) for x in range(20))
The above outputs 13260, for the particular grid created in the first line of code. It uses sum() three times. The innermost sum adds up the numbers in grid[x][y: y + 4], plus the slightly strange initial value sum = 1 shown in the code in the question. The middle sum adds up those values for the 17 possible y values. The outer sum adds up the middle values over possible x values.
If elements of grid are strings instead of numbers, replace
sum(grid[x][y: y + 4])
with
sum(int(n) for n in grid[x][y: y + 4]
You can use a dictionary to optimize performance significantly
This is another example:
locations = {}
for i in range(len(airports)):
locations[airports["abb"][i][1:-1]] = (airports["height"][i], airports["width"][i])
for i in range(len(uniqueData)):
h, w = locations[uniqueData["dept_apt"][i]]
uniqueData["dept_apt_height"][i] = h
uniqueData["dept_apt_width"][i] = w
I have a problem for an assignment I am working on, where I have to write a recursive function in python which returns the balanced code of size k, which is defined as the list of all binary strings of length 2k that contain an equal number of 0s in each half of the string. It is only allowed to accept one parameter, k. I have so far found a way to return a list of all possible binary strings of length 2k, but am having trouble reducing the list to only those that meet the criteria. This is my code so far:
def balanced_code(k):
if k >= 0:
if k == 0:
return ['']
else:
L = []
x = balanced_code(k - 1)
for i in range(0, len(x)):
L.append('00' + x[i])
L.append('01' + x[i])
L.append('10' + x[i])
L.append('11' + x[i])
return L
else:
return
My plan was after the for loop, I would check each item in L for the criteria mentioned (number of 0s equal in each half of the string), but quickly realized that this didn't give the right result as it would reduce L during every call, and I only want to reduce it once all calls to the function have been made. Is there any way I could track what recursion level the code is on or something like that so that I only reduce the list once all calls have been made?
How recursive does this have to be? Where does the recursion need to be?
If this were me, I'd write a recursive function:
def all_strings_of_length_k_with_n_zeros(k, n):
... you should be able to write this easily as recursion
And then
def balanced_code(k):
result = []
for zeros in range(0, k + 1):
temp = all_strings_of_length_k_with_n_zeros(k, zeros)
for left, right in itertools.product(temp, temp):
result.append(left + right)
return result
It's strange that your instructor is asking you to write some code recursively that can be written straightforwardly without recursion. (The function I left as an exercise to the reader could be written using itertools.combinations).
You can approach the recursion by adding "0" and "1" bits on each side of the k-1 results. The bits need to be added last on the right side and at every position on the left side. Since this is going to produce duplicates, using a set to return the strings will ensure distinct results.
def balancedCodes(k):
if not k: return {""}
return { code[:pos]+bit+code[pos:]+bit for code in balancedCodes(k-1)
for pos in range(k)
for bit in ("0","1") }
for bc in sorted(balancedCodes(3)): print(bc)
000000
001001
001010
001100
010001
010010
010100
011011
011101
011110
100001
100010
100100
101011
101101
101110
110011
110101
110110
111111
The 111111 result is a case of having no zeroes on each side
One way to solve this recursively without creating duplicates is by using what's described by The On-Line Encyclopedia of Integer Sequences® as the "1's-counting sequence: number of 1's in binary expansion of n (or the binary weight of n)" (sequence A000120), which can be formulated as a recurrence relation (see the function, f, below). Although we could "unpack" the sequence into our result at every stage for a self-contained recursive answer, it seemed superfluous so I left the unpacking of the sequence as a separate function we can call on the result.
def str_tuple(a, b, k):
return "{0:0{align}b}{1:0{align}b}".format(a, b, align=k)
def unpack(seq, k):
bitcounts = [[] for _ in range(k + 1)]
products = []
for n, i in enumerate(seq):
for n0 in bitcounts[i]:
products.extend([str_tuple(n0, n, k), str_tuple(n, n0, k)])
products.append(str_tuple(n, n, k))
bitcounts[i].append(n)
return products
def f(n):
if n == 1:
return [0, 1]
seq_l = f(n - 1)
seq_r = list(map(lambda x: x + 1, seq_l))
return seq_l + seq_r
k = 3
print(f(k))
print(unpack(f(k), k))
Output:
[0, 1, 1, 2, 1, 2, 2, 3]
['000000', '001001', '001010', '010001', '010010',
'011011', '001100', '100001', '010100', '100010',
'100100', '011101', '101011', '101101', '011110',
'110011', '101110', '110101', '110110', '111111']
I am currently working on practice interview questions. Attached is a screenshot of the question I'm working on below
I tried with the brute force approach of using nested loops with the intent of refactoring out the nested loop, but it still failed the tests in the brute force approach.
Here is the code that I tried:
def get_products_of_all_ints_except_at_index(int_list):
# Make a list with the products
products = []
for i in int_list:
for j in int_list:
if(i != j):
k = int_list[i] * int_list[j]
products.append(k)
return products
I am curious to both the brute force solution, and the more efficient solution without using nested loops.
Linear algorithm using cumulative products from the right side and from the left side
def productexcept(l):
n = len(l)
right = [1]*n
for i in reversed(range(n-1)):
right[i] = right[i + 1] * l[i+1]
#print(right)
prod = 1
for i in range(n):
t = l[i]
l[i] = prod * right[i]
prod *= t
return l
print(productexcept([2,3,7,5]))
>> [105, 70, 30, 42]
If you are allowed to use imports and really ugly list comprehensions you could try this:
from functools import reduce
l = [1,7,3,4]
[reduce(lambda x,y: x*y, [l[i] for i in range(len(l)) if i != k],1) for k,el in enumerate(l)]
If you are not allowed to use functools you can write your own function:
def prod(x):
prod = 1
for i in x:
prod = prod * i
return prod
l = [1,7,3,4]
[prod([l[i] for i in range(len(l)) if i != k]) for k,el in enumerate(l)]
I leave it as an exercise to the reader to put the two solutions in a function.
If you want to get the index of each elements in a list, you should try for i in range(len(int_list)). for i in int_list is in fact returning the values in the list but not the index.
So the brute force solution should be:
def get_products_of_all_ints_except_at_index(int_list):
# Make a list with the products
products = []
for i in range(len(int_list)):
k = 1
for j in range(len(int_list)):
if(i != j):
k *= int_list[j]
products.append(k)
return products
I've come up with this:
def product(larg):
result = 1
for n in larg:
result *= n
return result
List = [1, 7, 3, 4]
N = len(List)
BaseList = [List[0:i] + List[i+1:N] for i in range(N)]
Products = [product(a) for a in BaseList]
print(Products)
From the input list List, you create a list of lists where the proper integer is removed in each one. Then you just build a new list with the products of those sublists.
Here's a solution using a recursive function instead of a loop:
from functools import reduce
def get_products_of_all_ints_except_at_index(int_list, n=0, results=[]):
new_list = int_list.copy()
if n == len(int_list):
return results
new_list.pop(n)
results.append(reduce((lambda x, y: x * y), new_list))
return get_products_of_all_ints_except_at_index(int_list, n+1, results)
int_list = [1, 7, 3, 4]
print(get_products_of_all_ints_except_at_index(int_list))
# expected results [84, 12, 28, 21]
Output:
[84, 12, 28, 21]
Assume N to be a power of 2.
Brute force takes N(N-2) products. You can improve on that by precomputing the N/2 products of pairs of elements, then N/4 pairs of pairs, then pairs of pairs of pairs, until you have a single pair left. This takes N-2 products in total.
Next, you form all the requested products by multiplying the required partial products, in a dichotomic way. This takes Lg(N)-1 multiplies per product, hence a total of N(Lg(N)-1) multiplies.
This is an O(N Log N) solution.
Illustration for N=8:
Using 6 multiplies,
a b c d e f g h
ab cd ef gh
abcd efgh
Then with 16 multiplies,
b.cd.efgh
a.cd.efgh
ab.d.efgh
ab.c.efgh
abcd.f.gh
abcd.e.gh
abcd.ef.h
abcd.ef.g
The desired expressions can be obtained from the binary structure of the numbers from 0 to N-1.
Brute force
Your brute force approach does not work for multiple reasons:
(I'm assuming at least fixed indentation)
List index out of range
for i in int_list
This already gives you i which is an element of the list, not an index. When i is 7,
int_list[i]
is not possible any more.
The loops should be for ... in range(len(int_list)).
With that fixed, the result contains too many elements. There are 12 elements in the result, but only 4 are expected. That's because of another indentation issue at products.append(...). It needs to be outdented 2 steps.
With that fixed, most k are overwritten by a new value each time i*j is calculated. To fix that, start k at the identity element for multiplication, which is 1, and then multiply int_list[j] onto it.
The full code is now
def get_products_of_all_ints_except_at_index(int_list):
products = []
for i in range(len(int_list)):
k = 1
for j in range(len(int_list)):
if i != j:
k *= int_list[j]
products.append(k)
return products
Optimization
I would propose the "brute force" solution as an answer first. Don't worry about performance as long as there are no performance requirements. That would be premature optimization.
The solution with division would be:
def get_products_of_all_ints_except_at_index(int_list):
products = []
product = 1
for i in int_list:
product *= i
for i in int_list:
products.append(product//i)
return products
and thus does not need a nested loop and has linear Big-O time complexity.
A little exponent trick may save you the division: simply multiply by the inverse:
for i in int_list:
products.append(int(product * i ** -1))
I want to write a list comprehension that will give out Fibonacci number until the number 4 millions. I want to add that to list comprehension and sum evenly spaced terms.
from math import sqrt
Phi = (1 + sqrt(5)) / 2
phi = (1 - sqrt(5)) / 2
series = [int((Phi**n - phi**n) / sqrt(5)) for n in range(1, 10)]
print(series)
[1, 1, 2, 3, 5, 8, 13, 21, 34]
This is a sample code that works and I want to write similar code using list comprehension. Please do help.
a, b = 1, 1
total = 0
while a <= 4000000:
if a % 2 == 0:
total += a
a, b = b, a+b
print(total)
Since there's no actual list required for what you need to do, it's a bit wasteful having a list comprehension. Far better would be to just provide a function to do all the heavy lifting for you, something like:
def sumEvenFibsBelowOrEqualTo(n):
a, b = 1, 1
total = 0
while a <= n:
if a % 2 == 0:
total += a
a, b = b, a + b
return total
Then just call it with print(sumEvenFibsBelowOrEqualTo(4000000)).
If you really do want a list of Fibonacci numbers (perhaps you want to run different comprehensions on it), you can make a small modification to do this - this returns a list rather than the sum of the even values:
def listOfFibsBelowOrEqualTo(n):
a, b = 1, 1
mylist = []
while a <= n:
mylist.append(a)
a, b = b, a + b
return mylist
You can then use the following list comprehension to sum the even ones:
print(sum([x for x in listOfFibsBelowOrEqualTo(4000000) if x % 2 == 0]))
This is probably not too bad given that the Fibonacci numbers get very big very fast (so the list won't be that big) but, for other sequences that don't do that (or for much larger limits), constructing a list may use up large chunks of memory unnecessarily.
A better method may be to use a generator which, if you want a list, you can always construct one from it. But, if you don't need a list, you can still use it in list comprehensions:
def fibGen(limit):
a, b = 1, 1
while a <= limit:
yield a
a, b = b, a + b
mylist = list(fibGen(4000000)) # a list
print(sum([x for x in fibGen(4000000) if x % 2 == 0])) # sum evens, no list
A list comprehension is by its nature a parallel process; it's a process in which an input iterable is fed in, some function is applied to each element, and an output list is created. When this function is applied, it is applied to each element independently of other elements. Thus, list comprehensions are not suitable to iterative algorithms such as the one you present. It could be used in your closed-form formula:
sum([int((Phi**n - phi**n) / sqrt(5)) for n in range(1, 10) if int((Phi**n - phi**n) / sqrt(5))%2 == 0])
If you want to use an iterative algorithm, a generator is more suitable.
I want to solve the following problem with python, if possible with sympy.
Let n be a fixed positive number. Let p=(p_1,...p_n) be a fixed known vector of positive integers. Let d be a fixed, known positive integer. Let q=(q_1,...,q_n) be a vector of unknown nonnegative integers.
How can I get all the solutions of p.q=d?
Where . means dot product.
Actually I can solve this for each individual n. But I want to create a function
def F(n,p,d):
...
return result
Such that result is a, e.g., list of all solutions. Note that from the restrictions made above, there is a finite number of solutions for each triplet of data (n,p,d).
I can't figure a way to do this, so any suggestion will be appreciated.
Added.
Example: suppose n=3 (the case n=2 is trivial), p=(2,1,3), d=3. Then I would do something like
res=[]
for i in range (d):
for j in range (d):
k=d-p[0]*i-p[2]*j
if k>=0:
res.append([i,k,j])
Then res=[[0, 3, 0], [0, 0, 1], [1, 1, 0]] which is correct.
As you can imagine, the bigger n is, the more for loops I need if I want to follow the same idea. So I do not think this is a good way to do it for arbitrary n, say n=57 or whatever big enough...
Following the algorithm you provided:
from itertools import product
dot = lambda X, Y: sum(x * y for x, y in zip(X, Y))
p = [1, 2, 3, ...] # Whatever fixed value you have for `p`
d = 100 # Fixed d
results = []
for q in product(range(0, d+1), repeat=len(p)):
if dot(p, q) == d:
results.append(q)
However this is slightly inefficient since it is possible to determine prior to computing the entire dot product, whether k will be positive. So let's define the dot product like this:
def dot(X, Y, d):
total = 0
for x, y in zip(X, Y):
total += x * y
if total > d:
return -1
return total
Now, as soon as the total exceeds d, the calculation exits. You can also express this as a list comprehension:
results = [q for q in product(range(0, d+1), repeat=len(p)) if dot(p, q, d) == d]