How to iterate in python using for i in range loop? - python

I wonder how can I run the code below 4 times in which, in each run the variables in z (which are a and b) takes the new number while c stays the same?
a = [1,2,3,4]
print (a)
b = [4,5,6,7]
print (b)
c = [5]
print (c)
for i in range(4):
z = (a**2)*b+c
print (z)
The output I am looking for is:
9 ---> z = (1**4)*4+5
25---> z = (2**5)*4+5
59---> z = (3**6)*4+5
117---> z = (4**7)*4+5

for i, j in zip(a, b):
z = (i**2)*j+c[0]
print (z)

I'm not sure how you get the results on the left side from the calculations on the right. Based on your descriptions, I think what you meant is:
a = [1, 2, 3, 4]
print(a)
b = [4, 5, 6, 7]
print(b)
c = [5]
print(c)
for i in range(4):
z = (a[i] ** b[i]) * 4 + c[0]
print(z)
which gives:
9 ---> z = (1**4)*4+5
133 ---> z = (2**5)*4+5
2921 ---> z = (3**6)*4+5
65541 ---> z = (4**7)*4+5

Related

I have a polynomial equation and Y, How can I find X?

Consider it:
X = [1, 2, 3]
p = np.poly1d(X)
print('x: ', X, 'y: ', p(X))
output >> x: [1, 2, 3] y: [ 6 11 18]
what if I want to find x based on y?
x: [?, ?, ?] y: [ 6 11 18]
np.poly1d(X) means you create a polynomial of the required degree where X are its coefficients. Let's call them a, b, and c. So practically you have the expression
a*x**2 + b*x + c
When you then pass these three values for x, you get the following 3 equations
a**3 + b*a + c = 6
a*b**2 + b**2 + c = 11
a*c**2 + b*c + c = 18
There might be an algebraic way you can solve them yourself, but after a quick think I didn't come up with anything. However, sympy will happily solve this system of equations for you.
import numpy as np
import sympy as sym
def generate_y(X):
return np.poly1d(X)(X)
def solve_x(Y):
a, b, c = sym.symbols('a b c')
e1 = sym.Eq(a**3 + b*a + c, Y[0])
e2 = sym.Eq(a*b**2 + b**2 + c, Y[1])
e3 = sym.Eq(a*c**2 + b*c + c, Y[2])
return sym.solvers.solve([e1, e2, e3], [a, b, c])
For example
>>> solve_x(generate_y([1, 2, 3]))
[(1, 2, 3)]
>>> solve_x(generate_y([-5, 105, 2]))
[(-5, 105, 2)]
You could generalise this for nth order polynomials by creating the symbolic expressions dynamically, but for higher order you'll run into problems (such is life) and for 1st order you'll have multiple solutions.
def solve_x(Y):
symbols = sym.symbols('a:z')[:len(Y)]
X = sym.symbols('X')
expr = sum(s*X**i for i, s in enumerate(symbols[::-1]))
eqns = [sym.Eq(expr.subs({X: s}), y) for s, y in zip(symbols, Y)]
return sym.solvers.solve(eqns, symbols)
Usage
>>> solve_x(generate_y([1, 2]))
[(1, 2), (-1 + sqrt(2), 2*sqrt(2)), (-sqrt(2) - 1, -2*sqrt(2))]
>>> solve_x(generate_y([1, 2, 3, 4]))
# still computing...

How to get ranks from a sample in a list of values?

I'm new with Python and have a quite simple problem on paper but difficult to me in Python.
I have two samples of values (which are lists) :
X = [2, 2, 4, 6]
Y = [1, 3, 4, 5]
I have a concatenated list which is sorted as
Z = [ 1 , 2 , 2 , 3 , 4 , 4 , 5 , 6]
#rank: 1 2.5 4 5.5 7 8
I would like to get the sum of ranks of X values in Z. For this example, the ranks of 2, 2, 4 and 6 in Z are 2.5 + 2.5 + 5.5 + 8 = 18.5
(ranks of Y values in Z are 1 + 4 + 5.5 + 7 = 17.5)
Here is what I've done but it doesn't work with these lists X and Y (it works if each value appears only one time)
def funct(X, Z):
rank = []
for i in range(len(Z)):
for j in range(len(X)):
if Z[i] == X[j]:
rank = rank + [(i+1)]
print(sum(rank))
return
I would like to solve my problem with not too much complicated functions (only loops and quite easy ways to get a solution).
You can use a dictionary to keep track of the rank sums and counts once you've sorted the combined list.
X = [2, 2, 4, 6]
Y = [1, 3, 4, 5]
Z = sorted(X + Y)
ranksum = {}
counts = {}
for i, v in enumerate(Z):
ranksum[v] = ranksum.get(v, 0) + (i + 1) # Add
counts[v] = counts.get(v, 0) + 1 # Increment count
Then, when you want to look up the rank of an element, you need ranksum[v] / count[v].
r = [ranksum[x] / counts[x] for x in X]
print(r)
# Out: [2.5, 2.5, 5.5, 8]
Here's a solution for how to build the list of ranks:
X = ...
Y = ...
Z = sorted(X + Y)
rank = [1]
z = Z[:1]
for i, e in enumerate(Z[1:], start=2):
if e == z[-1]:
rank[-1] += 0.5
else:
rank.append(i)
z.append(e)
Now you can convert that into a dictionary:
ranks = dict(zip(z, rank))
That will make lookup easier:
sum(ranks[e] for e in X)
Here's another option where you build a dictionary of the rank indexes and then create a rank dictionary from there:
from collections import defaultdict
X = [2, 2, 4, 6]
Y = [1, 3, 4, 5]
Z = sorted(X + Y)
rank_indexes = defaultdict(lambda: [])
for i,v in enumerate(Z):
rank_indexes[v].append(i+1)
ranks = {k:(sum(v)/len(v)) for (k,v) in rank_indexes.items()}
print("Sum of X ranks:", sum([ranks[v] for v in X]))
print("Sum of Y ranks:", sum([ranks[v] for v in Y]))
Output:
Sum of X ranks: 18.5
Sum of Y ranks: 17.5
You can do the same thing without defaultdict, but it's slightly slower and I'd argue less Pythonic:
rank_indexes = {}
for i,v in enumerate(Z):
rank_indexes.setdefault(v, []).append(i+1)
ranks = {k:(sum(v)/len(v)) for (k,v) in rank_indexes.items()}

Python: Iterating through loops and list

How to iterate through lists to accommodate for more number of element, if 'U' list had more elements?
Specifically, line below:
for i in range(u+1):
x_matrix[i] = [pow(x[i],U[0]),pow(x[i],U[1]),pow(x[i],U[2]),pow(x[i],U[3])]
Full code:
import numpy as np
x = [-3, -2, -1, 0, 1, 2, 3]
y = [0, -4, 0, 6, 8, 0,-24]
ys = []
def check(lst):
result = False;
if len(lst) > 0 :
result = all(elem == lst[0] for elem in lst)
if result is True:
print("All Elements in List are Equal")
print(lst)
else:
print("All Elements in List are Not Equal")
print(lst)
a = []
a = [j-i for i, j in zip(lst[:-1], lst[1:])]
ys.append(a)
check(a)
check(y)
u = len(ys)
print('\nThe coordinates results in {}-th order polynomial.\n'.format(u))
U = list(range(u+1))
list.reverse(U)
x_matrix = [None]*(u+1)
for i in range(u+1):
x_matrix[i] = [pow(x[i],U[0]),pow(x[i],U[1]),pow(x[i],U[2]),pow(x[i],U[3])]
y_matrix = [v for k,v in enumerate(y[0:u+1])]
# AX = Y, Ainv dot Y = X
A = np.array(x_matrix)
Y = np.array(y_matrix)
Ainv = np.linalg.inv(A)
X = Ainv.dot(Y)
print(X)
Thank you.
Here is one way to vectorize the for loop. The [None] and [:,None] are needed to make sure that the arrays have compatible shape.
import numpy as np
x = np.array([-3, -2, -1, 0, 1, 2, 3])
n = 5
x[:,None] ** np.arange(n+1,0,-1)[None]
# note that x[:,None].shape[1] == np.arange(n+1,0,-1)[None].shape[0]
print(x[:,None] ** np.arange(n+1,0,-1)[None])
[[ 729 -243 81 -27 9 -3]
[ 64 -32 16 -8 4 -2]
[ 1 -1 1 -1 1 -1]
[ 0 0 0 0 0 0]
[ 1 1 1 1 1 1]
[ 64 32 16 8 4 2]
[ 729 243 81 27 9 3]]
Do you want something like this?
for i in range(u+1):
x_matrix[i] = [pow(x[i], elem) for elem in U]
If yes, there is a better way. Why you don't try like this:
x_matrix = [[pow(x[idx_elem], elem) for elem in U] for idx_elem in range(u+1)]

Magic Squares - Siamese Method

Is it possible to do magic squares with the Siamese/De La Loubere method without using modulo?
I would like to make odd n x n magic squares using it.
Yes, it's possible. Written on Python 3.5:
def siamese_method(n):
assert(n % 2 != 0), 'Square side size should be odd!'
square = [[0 for x in range(n)] for x in range(n)]
x = 0
y = int((n + 1) / 2 - 1)
square[x][y] = 1
for i in range(2, n * n + 1):
x_old = x
y_old = y
if x == 0:
x = n - 1
else:
x -= 1
if y == n - 1:
y = 0
else:
y += 1
while square[x][y] != 0:
if x == n - 1:
x = 0
else:
x = x_old + 1
y = y_old
square[x][y] = i
for j in square:
print(j)
siamese_method(3)
I've got following on output:
[8, 1, 6]
[3, 5, 7]
[4, 9, 2]

Decimal expansion based on slot length summation

I'm trying to create an algorithm to produce a decimal number by certain way.
a) I have an initial number say i = 2.
b) Then I have an incremental addition method, say f(n) { n * 2 }.
c) Then I have a slot length for digits say l = 2, that creates front zeros for small numbers and limits max length of the longer numbers. 2 becomes 02, 64 is 64, but 512 = (5)12 where 5 is moved backward on previous slot
d) Max slots is the fourth parameter, m = 10
e) Finally I want to compute value by summing up digit from slots and using it as a decimal part of the 0.
So with given example:
i=2
f(n)=n*2
l=2
m=10
outcome should be produced in this manner:
step 1)
02 04 08 16 32 64 128 256 512 1024
step 2)
02 04 08 16 32 64
1 28
2 56
5 12
10 24
->
slot: 1 2 3 4 5 6 7 8 9 10
computed: 02 04 08 16 32 65 30 61 22 24
step 3)
I have a number: 02040816326530612224 or 0.02040816326530612224 as stated on part e).
Note that if max slot is bigger in this example, then numbers on slots 9 and 10 will change. I also want to have part b) as a function, so I can change it to other like fib(nx) {n1+n2}.
I prefer Python as a computer language for algo, but anything that is easy to transform to Python is acceptable.
ADDED
This is a function I have managed to create so far:
# l = slot length, doesnt work with number > 2...
def comp(l = 2):
a = []
# how to pass a function, that produces this list?
b = [[0, 2], [0, 4], [0, 8], [1, 6], [3, 2], [6, 4], [1, 2, 8], [2, 5, 6], [5, 1, 2], [1, 0, 2, 4], [2, 0, 4, 8]]
r = 0
# main algo
for bb in b:
ll = len(bb)
for i in range(0, ll):
x = r + i - ll + l
# is there a better way to do following try except part?
try:
a[x] += bb[i]
except IndexError:
a.append(bb[i])
# moving bits backward, any better way to do this?
s = a[x] - 9
d = 0
while s > 0:
d += 1
a[x] -= 10
a[x-d] += 1
s = a[x-d] - 9
r += l
return '0.' + ''.join(map(str, a))
def doub(n):
return pow(2, n)
def fibo(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
def fixed_slot_numbers(f, l, m):
b = []
for n in range(1, m):
a = [int(c) for c in str(f(n))]
while len(a) < l:
a.insert(0, 0)
b.append(a)
return b
def algo(function, fixed_slot_length = 2, max_slots = 12):
a = []
slot_numbers = fixed_slot_numbers(function, fixed_slot_length, max_slots)
for r, b in enumerate(slot_numbers):
r *= fixed_slot_length
slot_length = len(b)
for bidx in range(0, slot_length):
aidx = r + bidx - slot_length + fixed_slot_length
try:
a[aidx] += b[bidx]
except IndexError:
a.append(b[bidx])
d = 0
while a[aidx-d] > 9:
a[aidx-d] -= 10
d += 1
a[aidx-d] += 1
return '0.%s' % ''.join(map(str, a))
algo(doub, 2, 28) -> 0.020408163265306122448979591836734693877551020405424128 = 1/49
algo(fibo, 1, 28) -> 0.112359550561797752808950848 = 10/89

Categories

Resources