N by N spiral matrix (1 to square(N)) - Unexpected Output - python

While trying to create a N by N spiral matrix for number 1 to square(N) , using the usual algorithm for spiral matrix , there is an unexpected output in one of the rows which cannot be found even on rechecking.
def getSpiralOrder(N):
matrix = [ [ 0 for i in range(N) ] for j in range(N) ]
c = 1
rS = 0
rE = len(matrix)
cS = 0
cE = len(matrix[0])
while(rS < rE and cS < cE):
for i in range(cS , cE ):
matrix[rS][i]=c
c = c + 1
rS += 1
for i in range(rS , rE):
matrix[i][cE - 1]=c
c = c + 1
cE -= 1
for i in range(cS , cE):
matrix[rE - 1][cE - i - 1]=c
c =c + 1
rE -= 1
for i in range(rS,rE):
matrix[rE - i ][cS]=c
c = c + 1
cS += 1
return(matrix)
n = int(input())
print(getSpiralOrder(n))
Output should be: [[1, 2, 3, 4], [12, 13, 14, 5], [11, 16 , 15, 6], [10, 9, 8, 7]]
But output coming is: [[1, 2, 3, 4], [12, 13, 14, 5], [16, 0, 15, 6], [10, 9, 8, 7]]
Turns out all rows are correct except the third one.

Your last two for loops are wrong:
def getSpiralOrder(N):
matrix = [ [ 0 for i in range(N) ] for j in range(N) ]
c = 1
rS = 0
rE = len(matrix)
cS = 0
cE = len(matrix[0])
while(rS < rE and cS < cE):
for i in range(cS , cE ):
matrix[rS][i]=c
c = c + 1
rS += 1
for i in range(rS , rE):
matrix[i][cE - 1]=c
c = c + 1
cE -= 1
# should go from cE - 1 not cE - cS - 1
for i in range(cE-cS):
matrix[rE - 1][cE - i - 1]=c
c =c + 1
rE -= 1
# similar here
for i in range(rE-rS):
matrix[rE - i -1][cS]=c
c = c + 1
cS += 1
return(matrix)

Related

How can I make a matrix print in a specific way in python?

I want to create a matrix thats N by N and that N is recieved as an input and when it prints its printed in a spiral. For example if the input is a 4 that means the matrix will be 4 by 4 and it will look like this when printed:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
I know how to create the matrix and make it N by N what I do not know is how can I make it look like this. Is there any guide,tutorial or anything I can watch/read to get how to make more 2d array exercises?
def llenar_matriz(n):
# Fills the matrix
for r in range(n):
fila = []
for c in range(n):
fila.append(0)
matriz.append(fila)
return matriz
def imprimir_matriz(matriz):
# Prints the matrix
filas = len(matriz)
columnas = len(matriz[0])
for f in range(filas):
for c in range(columnas):
print ("%3d" %matriz[f][c], end="")
print()
# Main program
lado = int(input("Ingrese el tamaño de la matriz: "))
while lado < 1:
print("Tamaño inválido. Debe ser mayor que 0")
lado = int(input("Ingrese el tamaño de la matriz: "))
matriz = []
llenar_matriz(lado)
imprimir_matriz(matriz)
This is my code atm and all it does is create a matrix of N by N, fills it with 0's and prints it
Algorithm :Let the array have R rows and C columns. seen[r] denotes that the cell on the r-th row and c-th column was previously visited. Our current position is (r, c), facing direction di, and we want to visit R x C total cells.
As we move through the matrix, our candidate’s next position is (cr, cc). If the candidate is in the bounds of the matrix and unseen, then it becomes our next position; otherwise, our next position is the one after performing a clockwise turn.
Code:
def spiralOrder(matrix):
ans = []
if (len(matrix) == 0):
return ans
R = len(matrix)
C = len(matrix[0])
seen = [[0 for i in range(C)] for j in range(R)]
dr = [0, 1, 0, -1]
dc = [1, 0, -1, 0]
r = 0
c = 0
di = 0
# Iterate from 0 to R * C - 1
for i in range(R * C):
ans.append(matrix[r])
seen[r] = True
cr = r + dr[di]
cc = c + dc[di]
if (0 <= cr and cr < R and 0 <= cc and cc < C and not(seen[cr][cc])):
r = cr
c = cc
else:
di = (di + 1) % 4
r += dr[di]
c += dc[di]
return ans
# Driver code
a = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]]
for x in spiralOrder(a):
print(x, end=" ")
print()
This is a Pic of how it works:
Here is a way using numpy:
# initialize test array
a = np.arange(16).reshape(4,4)
# spiral reshaping
out = []
while a.size:
out.append(a[0]) # take first row
a = np.rot90(a[1:]) # remove 1st row, rotate counter-clockwise
out = np.concatenate(out) # concatenate output
Explanation: take first row, rotate the rest of array, repeat until all the array is gone
input:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
output:
array([ 0, 1, 2, 3, 7, 11, 15, 14, 13, 12, 8, 4, 5, 6, 10, 9])

How to find sum of product of min value and length of sub list

I have a list of n numbers. I want to divide the list into sub lists, such as the sub list consists of continuous increasing numbers or continuous decreasing numbers. Then take the product of each sub list's min value and it's length. Finally take the sum of all this product's
Input:
l = [1,2,6,4,2,3,1,8,9,7]
Output:
32
Details:
[1,2,6],[6,4,2],[2,3],[3,1],[1,8,9],[9,7]
(1*3) +(2*3) + (2*2)+(1*2)+(1*3)+ (7*2) = 32
Code so far:
n = 10
l = [1,2,6,4,2,3,1,8,9,7]
tot = 0
count = 0
inc=dec=False
min_val = 1001 # max value in list won't exceed 1000
for idx, e in enumerate(l):
if idx+1<=n:
if e > l[idx+1]:
count+=1
if min_val > l[idx+1]:
min_val=l[idx+1]
inc=True
dec=False
elif e < l[idx+1]:
count+=1
if min_val > e:
min_val=e
dec=True
# if not inc
inc=False
*Note: No Two adjacent value will be equal in the list.
Update-1:
itemp = [1001]
dtemp = [1001]
result=0
for e in l:
# if not itemp or not dtemp:
# itemp.append(e)
# dtemp.append(e)
if e > itemp[-1]:
if not dtemp:
itemp.append(e)
else:
result+=(min(dtemp)*(len(dtemp)-1))
dtemp=[1001]
itemp.append(e)
elif e < dtemp[-1]:
dtemp.append(e)
if not itemp:
dtemp.append(e)
else:
result+=(min(itemp)*(len(itemp)-1))
itemp=[1001]
dtemp.append(e)
print(result)
This results 0 as output. Can some one help?
l = [1,2,6,4,2,3,1,8,9,7]
local_max= [i for i in range(1, len(l)-1) if l[i-1]<l[i]>l[i+1]]
local_min= [i for i in range(1, len(l)-1) if l[i-1]>l[i]<l[i+1]]
idx= sorted(local_max+local_min +[0,len(l)-1])
idx_pairs = zip(idx[:-1],idx[1:])
sum(min(l[i_1],l[i_2])*(i_2+1-i_1) for i_1,i_2 in idx_pairs)
You could identify the breaking positions (peaks and bottoms) using zip to detect changes of increasing/decreasing values between each sequence of 3 elements. Then use these breaks to form the sub-lists and apply the calculation in a comprehension.
L = [1,2,6,4,2,3,1,8,9,7]
breaks = [i+1 for i,(a,b,c) in enumerate(zip(L,L[1:],L[2:])) if (a<b)==(b>c)]
subL = [ L[s:e+1] for s,e in zip([0]+breaks,breaks+[len(L)]) ]
result = sum(min(s)*len(s) for s in subL)
print(breaks) # [2, 4, 5, 6, 8] indices of peaks and bottoms
# [1,2,6,4,2,3,1,8,9,7]
# ^ ^ ^ ^ ^
# 0 1 2 3 4 5 6 7 8 9
print(subL) # [ [1, 2, 6], [6, 4, 2], [2, 3], [3, 1], [1, 8, 9], [9, 7]]
# 0..2+1 2..4+1 4..5+1 5..6+1 6..8+1 8..len(L)
# | | | | | | | | | | | |
# [0] | + [2, | 4, | 5, | 6, | 8] |
# [2, 4, 5, 6, 8] + [len(L)]
print(result) # 32
tot = start = m = n = 0
direc = -1
for n, x in enumerate(lis):
if n == 0:
m = x
else:
old = lis[n - 1]
if (x > old and direc == 0) or (x < old and direc == 1):
tot += m * (n - start)
start = n - 1
m = min(old, x)
direc ^= 1
else:
direc = 1 if x > old else 0
m = min(m, x)
ln = n - start + 1
if ln > 1:
tot += m * ln

How to add elliptic curve points in python?

I'm trying to implement a simple elliptic curve encryption program but I can't get the expected output of doubling and adding a Point P till 12P .The curve equation isy^2 = x^3 +ax + b mod p. According to this site 3P = [10, 6] when P = [5, 1] while I get 3p = [10, 5]. The equations I use can be found on Wikipedia.
P = [5, 1]
prime = 17
a = 2
b = 2
def gcdExtended(a, b):
if a == 0:
return b, 0, 1
gcd, x1, y1 = gcdExtended(b % a, a)
x = y1 - (b // a) * x1
y = x1
return gcd, x, y
def double_point(point: list):
x = point[0]
y = point[1]
s = ((3*(x**2)+a) * (gcdExtended(2*y, prime)[1])) % prime
newx = (s**2 - x - x) % prime
newy = (s * (x - newx) - y) % prime
return [newx, newy]
def add_points(P: list, Q: list):
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
s = ((y2 - y1) * ((gcdExtended(x2-x1, prime))[1] % prime)) % prime
newx = (s**2 - x1 - x2) % prime
newy = (s * (x1 - newx) - y1) % prime
return [newx, newy]
Q = P
index = 2
while True:
if Q[0] == P[0] and Q[1] == P[1]:
print("doubling")
Q = double_point(P)
else:
print("adding")
Q = add_points(Q, P)
if index == 12 :
break
print(f"{index}P = {Q}")
index += 1
If the point [5,1] is added successively, the following sequence is obtained:
1P = [ 5, 1]
2P = [ 6, 3]
3P = [10, 6]
4P = [ 3, 1]
5P = [ 9, 16]
6P = [16, 13]
7P = [ 0, 6]
8P = [13, 7]
9P = [ 7, 6]
10P = [ 7, 11]
11P = [13, 10]
12P = [ 0, 11]
13P = [16, 4]
14P = [ 9, 1]
15P = [ 3, 16]
16P = [10, 11]
17P = [ 6, 14]
18P = [ 5, 16]
19P = point at infinity
This can be verified e.g. here.
The problem in the posted code is that the method to determine the modular inverse, gcdExtended(a, b), is only valid for positive a and b. While in double_point and add_points b has the value prime (= 17 > 0), a can take negative values.
gcdExtended generally returns wrong values for negative a:
The modular inverse of 5 or -12 is 7: 5 x 7 mod17 = 35 mod17 = 1 and 7 x (-12) mod17 = -84 mod17 = 85 mod17 = 1.
The gcdExtended returns for these values: gcdExtended(5, 17)[1] = 7 (which is true) and gcdExtended(-12, 17)[1] = -7 (which is false).
To allow negative values for a, e.g. the following methods can be defined, see here:
def sign(x):
return 1 if x >= 0 else -1
def gcdExtendedGeneralized(a, b):
gcd, x1, y1 = gcdExtended(abs(a), b)
return gcd, (sign(a) * x1) % b, y1 % b
Replacing gcdExtended with gcdExtendedGeneralized in double_point and add_points provides the correct values (note that the current implementation does not consider the point at infinity).
You interchanged P and Q in add_points. Also a small simplification in your calculation of s:
def add_points(P: list, Q: list):
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
#s = ((y2 - y1) * ((gcdExtended(x2-x1, prime))[1] % prime)) % prime
s = (y2-y1) * (gcdExtended(x2-x1, prime)[1] % prime)
newx = (s**2 - x1 - x2) % prime
newy = (s * (x1 - newx) - y1) % prime
return [newx, newy]
Q = P
index = 2
while True:
if Q[0] == P[0] and Q[1] == P[1]:
print("doubling")
Q = double_point(P)
else:
print("adding")
Q = add_points(P, Q)
if index == 12 :
break
print(f"{index}P = {Q}")
index += 1
which results in
doubling
2P = [6, 3]
adding
3P = [10, 6]
adding
4P = [3, 1]
adding
5P = [9, 16]
adding
6P = [16, 13]
adding
7P = [0, 6]
adding
8P = [13, 8]
adding
9P = [8, 7]
adding
10P = [8, 10]
adding
11P = [13, 9]
adding

I kept getting "ModuleNotFoundError: No module named 'error'"

I was given an outline of this code from my teacher, however I kept getting ModuleNotFoundError: No module named 'error'. I know that I need a module named error, however when I couldn't find a code for a module named error.
I am trying to solve this question:
Solve the tridiagonal equations Ax = b by Doolittle’s decomposition method, where:
A = [6 2 0 0 0
−1 7 2 0 0
0 −2 8 2 0
0 0 3 7 −2
0 0 0 3 5]
b = [2
−3
4
−3
1].
Here is the code that I was using:
from numpy import argmax, dot, zeros, array, asarray, tril, triu
def swapRows(v,i,j):
if len(v.shape) == 1: v[i],v[j] = v[j],v[i]
else:
temp = v[i].copy()
v[i] = v[j]
v[j] = temp
def swapCols(v,i,j):
temp = v[:,j].copy()
v[:,j] = v[:,i]
v[:,i] = temp
import error
def LUdecomp(a,tol=1.0e-9):
n = len(a)
seq = array(range(n))
# Set up scale factors
s = zeros(n)
for i in range(n):
s[i] = max(abs(a[i,:]))
for k in range(0,n-1):
# Row interchange, if needed
p = argmax(abs(a[k:n,k])/s[k:n]) + k
if abs(a[p,k]) < tol: error.err('Matrix is singular')
if p != k:
swapRows(s,k,p)
swapRows(a,k,p)
swapRows(seq,k,p)
# Elimination
for i in range(k+1,n):
if a[i,k] != 0.0:
lam = a[i,k]/a[k,k]
a[i,k+1:n] = a[i,k+1:n] - lam*a[k,k+1:n]
a[i,k] = lam
return a,seq
def LUsolve(a,b,seq):
n = len(a)
# Rearrange constant vector; store it in [x]
x = b.copy()
for i in range(n):
x[i] = b[seq[i]]
# Solution
for k in range(1,n):
x[k] = x[k] - dot(a[k,0:k],x[0:k])
x[n-1] = x[n-1]/a[n-1,n-1]
for k in range(n-2,-1,-1):
x[k] = (x[k] - dot(a[k,k+1:n],x[k+1:n]))/a[k,k]
return x
A = asarray( [ [ 6, 2, 0, 0, 0 ],
[ -1, 7, 2, 0, 0 ],
[ 0, -2, 8, 2, 0 ],
[ 0, 0, 3, 7, -2 ],
[ 0, 0, 0, 3, 5 ] ], dtype=float ) A_orig = A.copy() b = asarray( [ 2, -3, 4, -3, 1 ], dtype=float ) b_orig = b.copy()
A,seq = LUdecomp(A) # A is overwritten as L\U L = tril( A, -1 ) # extract L for ii in range(L.shape[0]): L[ii,ii] = 1.0 # add in 1's on the diagonal U = triu( A, 0 ) # extract U print ("L = ") print (L) print ("U = ") print (U) if False:
print ("A[seq,:]= ")
print (A_orig[seq,:])
print ("LU= ")
print (dot(L,U))
x = LUsolve(A,b,seq) print ("Solution= ", x)
If your intention is to throw an error at some point, then you can reach that without the import error statement. Raising an exception might be a solution.
See the documentation on errors and exceptions.
You can remove import error and edit
if abs(a[p,k]) < tol: error.err('Matrix is singular')
in LUdecomp() as follows:
if abs(a[p,k]) < tol:
raise Exception('Matrix is singular')

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