Python create a sequence of non repeating numbers - python

I want to create a sequence something like this [[1,2],[3,4],[5,6],..].
Here is what I tried and got:
n = 3 # I need three lists
for i in range(0,n+1,1):
print(i+1,i+2)
1 2
2 3
3 4
4 5
Expected output:
1 2
3 4
5 6

n = 3
pairs = [list([i, i + 1]) for i in range (1, 2 * n, 2)]
for pair in pairs:
for x in pair:
print(x, end = ' ')
print()
This prints:
1 2
3 4
5 6
And the list pairs so formed is:
[[1, 2], [3, 4], [5, 6]]

Take step of 2 and end at n*2
n=3
output = []
for i in range(0,n*2,2):
print(i+1,i+2)
output.append([i+1,i+2])
print(output)
1 2
3 4
5 6
[[1, 2], [3, 4], [5, 6]]

After a trial, I found the following answer:
for i in range(0,n,1):
print(2*i+1,2*i+2)

Related

What will be the best approach for a digit like pattern in python?

i was trying a pattern in Python
if n == 6
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
after trying to think a lot
i did it like this --->
n = 6
for i in range(1,n):
x = 1
countj = 0
for j in range(i,n):
countj +=1
print(j,end=" ")
if j == n-1 and countj < n-1 :
while countj < n-1:
print(x , end =" ")
countj +=1
x +=1
print()
but i don't think it is the best approach, I was trying to search some better approach , but not able to get the proper one, So that I came here,, is there any possible better approach for the problem?
I would do like this, using a rotating deque instance:
>>> from collections import deque
>>> n = 6
>>> d = deque(range(1, n))
>>> for _ in range(1, n):
... print(*d)
... d.rotate(-1)
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
There is a similar/shorter code possible just using range slicing, but maybe it's a bit harder to understand how it works:
>>> ns = range(1, 6)
>>> for i in ns:
... print(*ns[i-1:], *ns[:i-1])
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
You could also create a mathematical function of the coordinates, which might look something like this:
>>> for row in range(5):
... for col in range(5):
... print((row + col) % 5 + 1, end=" ")
... print()
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
A too-clever way using list comprehension:
>>> r = range(5)
>>> [[1 + r[i - j - 1] for i in r] for j in reversed(r)]
[[1, 2, 3, 4, 5],
[2, 3, 4, 5, 1],
[3, 4, 5, 1, 2],
[4, 5, 1, 2, 3],
[5, 1, 2, 3, 4]]
more-itertools has this function:
>>> from more_itertools import circular_shifts
>>> circular_shifts(range(1, 6))
[(1, 2, 3, 4, 5),
(2, 3, 4, 5, 1),
(3, 4, 5, 1, 2),
(4, 5, 1, 2, 3),
(5, 1, 2, 3, 4)]
You can use itertools.cycle to make the sequence generated from range repeat itself, and then use itertools.islice to slice the sequence according to the iteration count:
from itertools import cycle, islice
n = 6
for i in range(n - 1):
print(*islice(cycle(range(1, n)), i, i + n - 1))
This outputs:
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
Your 'pattern' is actually known as a Hankel matrix, commonly used in linear algebra.
So there's a scipy function for creating them.
from scipy.linalg import hankel
hankel([1, 2, 3, 4, 5], [5, 1, 2, 3, 4])
or
from scipy.linalg import hankel
import numpy as np
def my_hankel(n):
x = np.arange(1, n)
return hankel(x, np.roll(x, 1))
print(my_hankel(6))
Output:
[[1 2 3 4 5]
[2 3 4 5 1]
[3 4 5 1 2]
[4 5 1 2 3]
[5 1 2 3 4]]
Seeing lots of answers involving Python libraries. If you want a simple way to do it, here it is.
n = 5
arr = [[1 + (start + i) % n for i in range(n)] for start in range(n)]
arr_str = "\n".join(" ".join(str(cell) for cell in row) for row in arr)
print(arr_str)

An efficient way to concatenate rows of a 2-dim array according to a given list of pairs of indexes

Suppose I have a 2 dimensional array with a very large number of rows, and a list of pairs of indexes of that array. I want to create a new 2 dim array, whose rows are concatenations of the rows of the original array, made according to the list of pairs of indexes. For example:
a =
1 2 3
4 5 6
7 8 9
0 0 0
indexes = [[0,0], [0,1], [2,3]]
the returned array should be:
1 2 3 1 2 3
1 2 3 4 5 6
7 8 9 0 0 0
Obviously I can iterate the list of indexes, but my question is whether there is a more efficient way of doing this. I should say that the list of indexes is also very large.
First convert indexes to a Numpy array:
ind = np.array(indexes)
Then generate your result as:
result = np.concatenate([a[ind[:,0]], a[ind[:,1]]], axis=1)
The result is:
array([[1, 2, 3, 1, 2, 3],
[1, 2, 3, 4, 5, 6],
[7, 8, 9, 0, 0, 0]])
Another possible formula (with the same result):
result = np.concatenate([ a[ind[:,i]] for i in range(ind.shape[1]) ], axis=1)
You can do this in one line using NumPy as:
a = np.arange(12).reshape(4, 3)
print(a)
b = [[0, 0], [1, 1], [2, 3]]
b = np.array(b)
print(b)
c = a[b.reshape(-1)].reshape(-1, a.shape[1]*b.shape[1])
print(c)
'''
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
[[0 0]
[1 1]
[2 3]]
[[ 0 1 2 0 1 2]
[ 3 4 5 3 4 5]
[ 6 7 8 9 10 11]]
'''
You can use horizontal stacking np.hstack:
c = np.array(indexes)
np.hstack((a[c[:,0]],a[c[:,1]]))
output:
[[1 2 3 1 2 3]
[1 2 3 4 5 6]
[7 8 9 0 0 0]]

How to understand the Python code I wrote for a problem

If I give 2 output is
2 2 2
2 1 2
2 2 2
and for 3 is
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
The code is as follows:
def square(arr, val):
if val is 1:
return [[1]] //self understandable
n = val + (val - 1) //getting array size, for 2 its 3
sideAdd = [val] * n
arr.insert(0, sideAdd) //for 2 it add [2,2,2] at first
arr.append(sideAdd) //append [2,2,2]
for i in range(1, n-1): //for inner elements add val to either sides
arr[i].insert(0, val) // like, for 2 [val,1,val]
arr[i].append(val)
return(arr)
array = square([[2, 2, 2], [2, 1, 2], [2, 2, 2]], 3)
# print(array)
for i in array:
print(*i)
The output goes like:
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
which is a correct answer.
But when I tried to complete the whole solution by giving values through for loop and sending returned array as parameter again through the same function like
n = 3
arr = []
for i in range(1, n+1):
arr = square(arr, i)
the whole code is
def square(arrx, val):
if val is 1:
return [[1]]
n1 = val + (val - 1)
sideAdd = [val] * n1
arrx.insert(0, sideAdd)
arrx.append(sideAdd)
for i in range(1, n1-1):
arrx[i].insert(0, val)
arrx[i].append(val)
return arrx
n = 3
arr = []
for i in range(1, n+1):
arr = square(arr, i)
for i in arr:
print(*i)
This returns the answer as:
3 3 3 3 3
3 3 2 2 2 3 3
3 2 1 2 3
3 3 2 2 2 3 3
3 3 3 3 3
which is wrong
I already tried running in debug mode in pycharm, there I got an unusual thing. Check the screenshot below. When j = 1 (index), the code inserts 2 in blue underline but also in red which should not because the red underline index is 3 (insertion of 2 should occur at j = 3), and when j = 3 again insertion at index 1 (j = 1) is happening which makes the output 3 3 2 2 2 3 3 instead of 3 2 2 2 3.
I can't understand how that's happening. The screenshot is as follows:
https://imgur.com/yce47Pi
I think you are making this more complicated than it needs to be. You can determine the correct value of any cell from their indexes alone. Given a size n and row/column [i,j], the value is:
max(abs(n - 1 - j) + 1, abs(n - 1 - i) + 1)
For example:
def square(n):
arr = []
for i in range(n + n-1):
cur = []
arr.append(cur)
for j in range(n + n -1):
cur.append(max(abs(n - 1 - j) + 1, abs(n - 1 - i) + 1))
return arr
Then
> square(3)
[[3, 3, 3, 3, 3],
[3, 2, 2, 2, 3],
[3, 2, 1, 2, 3],
[3, 2, 2, 2, 3],
[3, 3, 3, 3, 3]]
> square(5)
[[5, 5, 5, 5, 5, 5, 5, 5, 5],
[5, 4, 4, 4, 4, 4, 4, 4, 5],
[5, 4, 3, 3, 3, 3, 3, 4, 5],
[5, 4, 3, 2, 2, 2, 3, 4, 5],
[5, 4, 3, 2, 1, 2, 3, 4, 5],
[5, 4, 3, 2, 2, 2, 3, 4, 5],
[5, 4, 3, 3, 3, 3, 3, 4, 5],
[5, 4, 4, 4, 4, 4, 4, 4, 5],
[5, 5, 5, 5, 5, 5, 5, 5, 5]]
Edit
The problem with current code is this:
sideAdd = [val] * n
arr.insert(0, sideAdd)
arr.append(sideAdd)
You adding a reference to the same array (sideAdd) twice. So later when you add columns with:
arrx[i].insert(0, val)
arrx[i].append(val)
these two array are the same if they were added in an earlier loop. Adding to the first array also adds one to the second and adding to the second adds to the first. So you end up doing it twice. There are a couple ways to fix that, but the easiest is adding a copy the second time:
sideAdd = [val] * n
arr.insert(0, sideAdd)
arr.append(sideAdd[:]) # Make a copy — don't add the same reference
We can make use of numpys broadcasting rules here:
>>> np.maximum(np.abs(np.arange(-2, 3)[:, None]), np.abs(np.arange(-2, 3))) + 1
array([[3, 3, 3, 3, 3],
[3, 2, 2, 2, 3],
[3, 2, 1, 2, 3],
[3, 2, 2, 2, 3],
[3, 3, 3, 3, 3]])
So we can render the cube with:
import numpy as np
def cube(n):
ran = np.abs(np.arange(-n+1, n))
cub = np.maximum(ran[:, None], ran) + 1
return '\n'.join(' '.join(map(str, row)) for row in cub)
For example:
>>> print(cube(1))
1
>>> print(cube(2))
2 2 2
2 1 2
2 2 2
>>> print(cube(3))
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
>>> print(cube(4))
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
>>> print(cube(5))
5 5 5 5 5 5 5 5 5
5 4 4 4 4 4 4 4 5
5 4 3 3 3 3 3 4 5
5 4 3 2 2 2 3 4 5
5 4 3 2 1 2 3 4 5
5 4 3 2 2 2 3 4 5
5 4 3 3 3 3 3 4 5
5 4 4 4 4 4 4 4 5
5 5 5 5 5 5 5 5 5

String-formatting two zipped NumPy arrays in Python 3

I would like to use pythons format function to print subsequent numbers of a numpy array.
I have got two numpy arrays, let's say:
x=[1 2 3 4]
y=[5 6 7 8]
Now I would like to print this:
1 5 2 6 3 7 4 8
I can almost achieve this by:
print('{} {} {} {}'.format(*zip(x,y)))
but it yields:
(1,5) (2,6) (3,7) (4,8)
Of course I could use
"{} {} {} {}".format(x[0], y[0], x[1], y[1])
and so on but this requires to know the length of the array.
Note:
This line of code does what I want
print(*["%f %f"%(a,b) for a,b in zip(x,y)])
but this does use the old formatting style and I would like to know if it's possible with the new one, too. It also looks a little bit funky, I think :-D
Do the following:
x=[1, 2, 3, 4]
y=[5, 6, 7, 8]
result = ' '.join([str(i) for e in zip(x, y) for i in e])
print(result)
Output
1 5 2 6 3 7 4 8
You can use itertools.chain to interleave the elements from both lists:
list(chain.from_iterable(zip(x, y)))
[1, 5, 2, 6, 3, 7, 4, 8]
And if you want to print all elements joined as you specify you can do:
print(*chain.from_iterable(zip(x, y)))
1 5 2 6 3 7 4 8
what about some numpy
np.array(list(zip(a,b))).flatten()
output
array([1, 5, 2, 6, 3, 7, 4, 8])
You can use zip() to iterate through two iterables at the same time.
l1 = [0, 2, 4, 6, 8]
l2 = [1, 3, 5, 7, 9]
for i, j in zip(l1, l2):
print(i)
print(j)
Output:
0
1
2
3
4
5
6
7
8
9
Since you use numpy, what about
>>> ' '.join(np.vstack((x, y)).T.flatten().astype(str))
'1 5 2 6 3 7 4 8'
It's also possible with itertools.starmap:
>>> print(*starmap("{} {}".format, zip(x, y)))
1 5 2 6 3 7 4 8
Normally, the method given by #yatu with itertools.chain is the way to go, especially if you want all elements to be separated by spaces. But starmap could come handy when you'd want to have some special formatting between the pairs, for example:
>>> print(*starmap("{}:{}".format, zip(x, y)))
1:5 2:6 3:7 4:8
Throwing another into the mix
("{} "*len(x)*2).format(*np.ravel(list(zip(x,y))))
'1 5 2 6 3 7 4 8 '

Python: finding the index of a list into a list of list

I am a beginner in python and facing difficulty while searching the index of a list into another list of list. I have two list of lists X and X_test. Sample given below:
X = [[5 1 1 1 2 '1' 3 1 1],[5 4 4 5 7 '10' 3 2 1],[3 1 1 1 2 '2' 3 1 1],[6 8 8 1 3 '4' 3 7 1],[4 1 1 3 2 '1' 3 1 1]]
X_test = [[3 1 1 1 2 '2' 3 1 1],[6 8 8 1 3 '4' 3 7 1]]
Elements of X_test are part of list X. Now, I want to find the index of every whole list of X_test within X.
For eg. X_test[0] is at the index 2 of X and X_test[1] at index 3.
Program should return the indexes of the matching lists. i.e 2 and 3.
How can I do it in python? Thanks in advance.
Your code doesn't quite run, as you need commas between the elements of each list.
So I've written my own example. This is what you can do:
X = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
X_test = [[4, 5, 6]]
for i in X_test:
print(X.index(i))
res = []
for i in X_test:
res.append(x.index(i))
Try using .index():
indexes = [X.index(test) for test in X_test]
This whole thing is a bit clearer if you experiment with a simple list (rather than a list of lists):
>>> X = [0, 1, 4, 9, 16]
>>> X_test = [9, 16]
>>> indexes = [X.index(test) for test in X_test]
[3, 4]

Categories