I'd like to create two list (appearantly it doesnt need to be a list, can be tuple, array, numpy.array, see edit below) of a certain partern, lets call them list_1 and list_2
list_1 has the patern that can be described as (i is an integer)
{i}, {i, i + 17}, {i, i+17 , i + 17 + 17}, {i, i + 17, i + 17 + 17, i + 17 + 17 + 17},
But the pattern occurs twice, which means that the resulting list will look like
list_1 = [i, i, i + 17, i, i + 17 , i + 34, i, i + 17, i + 34, i + 51,
i, i, i + 17, i, i + 17 , i + 34, i, i + 17, i + 34, i + 51]
Currently I'm doing it as (with i = 2 in this example)
some_limit = 5
list_1 = [17 * x + i for b in range(some_limit + 1) for x in range(b)]
list_1 += list_1
result
[2, 2, 19, 2, 19, 36, 2, 19, 36, 53, 2, 19, 36, 53, 70, 2, 2, 19, 2, 19, 36, 2, 19, 36, 53, 2, 19, 36, 53, 70]
When some_limit is a big number this takes time. Is there a faster way?
list_2 has a pattern that can be described as (j is an integer)
{j} {j+1, j+1}, {j+2, j+2, j+2}, {j+3, j+3, j+3, j+3}
This pattern also occours twice but with a shift which means that the resulting list will look like
list_2 = [j, j+1, j+1, j+2, j+2, j+2, j+3, j+3, j+3, j+3,
j+shift, j+1+shift, j+1+shift, j+2+shift, j+2+shift, j+2+shift, j+3+shift, j+3+shift, j+3+shift, j+3+shift,
Currently I'm doing it as (with j = 0 in this example)
some_limit = 5
arithemic_list = [k for k in range(some_limit + 1)]
rows_index_temp = [item -1 + some_limit * j * 2 for item, count in zip(arithemic_list, arithemic_list) for k in range(count)]
rows_index_temp += [some_limit + elem for elem in rows_index_temp]
result
[0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9]
When some_limit is a big number this takes time. Is there a faster way?
Edit
This is used to create sparse matrices for the optimization package cvxopt. A matrix is built by providing elements with their row and column indicies. For example a 3x3 identity matrix is created by 3 lists, elements = [1,1,1], rows = [0, 1, 2] and columns = [0, 1, 2]. My matrix is very large which implies that the lists will be very large.
From the documentation
cvxopt.spmatrix(x, I, J[, size[, tc ] ])
I and J are sequences of integers (lists, tuples, array arrays, . . . ) or integer matrices (matrix objects with
typecode 'i'), containing the row and column indices of the nonzero entries. The lengths of I and J must
be equal. If they are matrices, they are treated as lists of indices stored in column-major order, i.e., as lists
list(I), respectively, list(J)
https://readthedocs.org/projects/cvxopt/downloads/pdf/1.2.0/
Example
Lets say we would like to create the following matrix:
[ 1.00e+00 0 0 0 0 ]
[ 2.00e+00 0 0 3.00e+00 0 ]
[ 0 0 0 0 4.00e+00]
We are only interested in the non-zero-elements and we can group them as
element row column
1 0 0
2 1 0
3 1 3
4 2 4
Thus, by having
elements = [1,2,3,4,0]
rows = [0,1,1,2, 3]
columns = [0,0, 3, 4, 4]
print(spmatrix(elements, rows, columns))
[ 1.00e+00 0 0 0 0 ]
[ 2.00e+00 0 0 3.00e+00 0 ]
[ 0 0 0 0 4.00e+00]
Notice that the order doesnt mather, as long as the element,row,column are grouped together. Thus this would be equivalent.
elements = [4,2,3,1]
rows = [2,1,1,0]
columns = [4,0, 3,0]
print(spmatrix(elements, rows, columns))
[ 1.00e+00 0 0 0 0 ]
[ 2.00e+00 0 0 3.00e+00 0 ]
[ 0 0 0 0 4.00e+00]
What am I trying to create? (some_limit = 3)
This is basically a concatination of two lower triangual matrix, with a constant shift between its elements. So how would we describe this matrix?
If we focus on the "upper" lower triangual part which contains -1:s.
We can group as
element row column
-1 0 2
-1 1 2
-1 1 19
-1 2 2
-1 2 19
-1 2 36
The "lower" triangular part with only 1:s can be grouped as
We can group as
element row column
1 3 2
1 4 2
1 4 19
1 5 2
1 5 19
1 5 36
Together this become
element row column
-1 0 2
-1 1 2
-1 1 19
-1 2 2
-1 2 19
-1 2 36
1 3 2
1 4 2
1 4 19
1 5 2
1 5 19
1 5 36
Or,
element row column
-1 0 2
-1 1 2
-1 1 2 + 17
-1 2 2
-1 2 2 + 17
-1 2 2 + 2*17
1 1 + 2 2
1 2 + 2 2
1 2 + 2 2 + 17
1 3 + 2 2
1 3 + 2 2 + 17
1 3 + 2 2 + 2*17
Since the order doesnt mather, as long as element, row, column is grouped togethere, there might be a "better" pattern which I havent consider.
The size of this matrix is directly correlated with the number of elements in the list describing the elements, rows, and columns. I wish to have some_limit >=4343 => the lenght of each of the list elements, rows, and columns will be
(4343*(4343 + 1)/2)*2 which explodes quite fast...
some_limit
4343
len(list_1)
18865992
#size_of_matrix
<34744x73831 sparse matrix, tc='d', nnz=75463969>
You can convert your list comprehensions to generator expressions, then you do not have to create the entire list at once but can generate values as needed. In particular note the additional loop I added so that you do not have to create the entire list, then add a copy to itself.
i, j, limit, shift = 2, 0, 5, 10
gen_1 = (17 * x + i for _ in range(2) # repeat twice
for b in range(limit) # len of subsegments
for x in range(b+1)) # multiplier
gen_2 = (j + b + s for s in (0, 10) # repeat with shift
for b in range(limit) # len of subsegments
for _ in range(b+1)) # repeat b times
You can then either iterate the values as needed (or still create a list from all the values):
for x in gen_1:
print(x)
print(list(gen_2))
Write a program that displays 12 digits,
each digit is equal to three times the digit before him.
I tried to code like this
a , b , c = 1 , 1 , 1
print(c)
while c < 12 : # for looping
c = c + 1 # c for counting
b = a+b
y = 3*b
print(c,y)
can any one help me to correct the result
You can use power operator for that:
from itertools import islice
def numbers(x, base=3):
n = 0
while True:
yield x * base ** n
n += 1
for n in islice(numbers(1), 12):
print(n)
Or if you really like your way of doing that, here's a fixed version of your code:
b, c = 1, 0
while c < 12:
print(c, b)
b *= 3
c += 1
You can start with a list where first element is the beginning of the multiples:
-- start with 1 or the number you like
multiples = [1]
for i in range(1, 12):
multiples.append(3 * multiples[i - 1])
print(multiples)
-- Output : [1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147]
I have a file with two columns, lets say A and B
A B
1 10
0 11
0 12
0 15
1 90
0 41
I want to create a new column (a list), lets call the empty list C = []
I would like to loop through A, find if A == 1, and if it is I want to append the value of B[A==1] (10 in the first case) to C until the next A == 1 arrives.
So my final result would be:
A B C
1 10 10
0 11 10
0 12 10
0 15 10
1 90 90
0 41 90
I have tried using the for loop, but only to my dismay:
for a in A:
if a == 1:
C.append(B[a==1])
elif a == 0:
C.append(B[a==1])
You could use another variable to keep the value of the last index in A that had a value of 1, and update it when the condition is met:
temp = 0
for index, value in enumerate(A):
if value == 1:
C.append(B[index])
temp = index
else:
C.append(B[temp])
enumerate() gives you a list of tuples with index and values from an utterable.
For A, it will be [(0, 1), (1, 0), (2, 0), (3, 0), (4, 1), (5, 0)].
P.S: When you try to address a list using a boolean (B[a == 1]) it will return the item in the first place if the condition is false (B[a != 1] => B[False] => B[0]) or the item in the second place if it's true (B[a == 1] => B[True] => B[1]).
You may also try using groupby.
Though solution I have come up with looks a bit convoluted to me:
>>> from itertools import izip, groupby, count
>>> from operator import itemgetter
>>> def gen_group(L):
acc = 0
for item in L:
acc += item
yield acc
>>> [number_out for number,length in ((next(items)[1], 1 + sum(1 for _ in items)) for group,items in groupby(izip(gen_group(A), B), itemgetter(0))) for number_out in repeat(number, length)]
[10, 10, 10, 10, 90, 90]
The idea is to prepare groups and then use them to group your input:
>>> list(gen_group(A))
[1, 1, 1, 1, 2, 2]
I have to read a file from the command line, and also set the matrix rows and cols. When I run my program(below):
python3 transpose.py matrix 3 4
(current code below) (file with numbers 1 2 3 4 5 6 7 8 9 10 11 12 13) (matrix row,cols)
printed all together should return:
The empty matrix is:[[0,0,0,0],[0,0,0,0],[0,0,0,0]]
The original matrix is:
1 2 3 4
5 6 7 8
9 10 11 12
The transposed matrix is:
1 5 9
2 6 10
3 7 11
4 8 12
Here is my transpose.py Ive spent around 10 hours on it and can't get it to work, I just can't figure out what else to do!
import sys
from scanner import *
def main():
readinput(sys.argv[1],[2])
size = 3
rows = size
cols = rows
makeList(size)
matrix(rows,cols)
manipulateMatrix(matrix(rows,cols))
print(manipulateMatrix(matrix(rows,cols)))
print("The original matrix is: ")
displayMatrix(manipulateMatrix(matrix(rows,cols)))
transposeSquare(manipulateMatrix(matrix(rows,cols)),size)
print (transposeSquare(manipulateMatrix(matrix(rows,cols)),size))
print("The transposed matrix: ")
displayMatrix(transposeSquare(manipulateMatrix(matrix(rows,cols)),size))
def readinput(filename,matrix):
s = Scanner(filename)
r = s.readtoken()
while r != "":
r = int(r)
c = s.readint()
v = s.readint()
matrix[r][c]=v
r = s.readtoken()
s.close()
def makeList(size):
lyst = []
for i in range(size):
lyst = lyst + [None]
return lyst
def matrix(rows,cols):
matrix = makeList(rows)
for i in range(rows):
matrix[i] = makeList(cols)
return matrix
def manipulateMatrix(m):
rows = len(m)
cols = len(m[0])
count = 1
for r in range(0,rows,1):
for c in range(0,cols,1):
m[r][c] = count
count += 1
return m
def transposeSquare(m,size):
for r in range(0,size):
for c in range(0,size):
m[r][c],m[c][r] = m[c][r],m[r][c]
return m
def displayMatrix(m):
m == rows == cols
for r in range(0,size):
for c in range(0,cols,1):
print(m[r][c],end = "")
print()
return
main()
right now I am currently stuck at
Traceback (most recent call last):
File "transpose.py", line 66, in <module>
main()
File "transpose.py", line 6, in main
readinput(sys.argv[1],[2])
File "transpose.py", line 27, in readinput
matrix[r][c]=v
IndexError: list index out of range
Transposing a 2D list is much simpler. Use the zip() function together with the * unpacking operator:
>>> matrix = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
>>> new = list(zip(*matrix)) # call to list not necessary in Python 2
>>> new
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
or, if you don't want tuples:
>>> new = [list(tup) for tup in zip(*matrix)]
>>> new
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
Use the numpy library. it is designed for this purpose, runs the numerical in C/C++ code and much faster than doing it in python and having to debug it.
import numpy as np
m = np.array(<your list matrix here>)
print m.shape # to see the shape of your matrix
mt = m.T #m.T transpose the matrix
print m.shape
print m