Counting contiguous numbers within a list - python-3.x

I am completely new to the topic of programming but interested.
I am coding in python 3.x and have a question to my latest topic:
We have a list, containing a few tenthousands of randomly generated integers between 1 and 7.
import random
list_of_states = []
n = int(input('Enter number of elements:'))
for i in range(n):
list_of_states.append(random.randint(1,7))
print (list_of_states)
Afterwards, I would like to count the contiguous numbers in this list and put them into an numpy.array
example: [1, 2, 3, 4, 4, 4, 7, 3, 1, 1, 1]
1 1
2 1
3 1
4 3
7 1
3 1
1 3
I would like to know whether someone has a hint/an idea of how I could do this.
This part is a smaller part of a markov chain wherefor I need the frequency of each number.
Thanks for sharing
Nadim

Below is a crude way of doing this. I am creating a list of lists and then converting it to a numpy array. Please use this only a guidance and improvise on this.
import numpy as np
num_list = [1,1,1,1,2,2,2,3,4,5,6,6,6,6,7,7,7,7,1,1,1,1,3,3,3]
temp_dict = {}
two_dim_list = []
for x in num_list:
if x in temp_dict:
temp_dict[x] += 1
else:
if temp_dict:
for k,v in temp_dict.items():
two_dim_list.append([k,v])
temp_dict = {}
temp_dict[x] = 1
for k,v in temp_dict.items():
two_dim_list.append([k,v])
print ("List of List = %s" %(two_dim_list))
two_dim_arr = np.array(two_dim_list)
print ("2D Array = %s" %(two_dim_arr))
Output:
List of List = [[1, 4], [2, 3], [3, 1], [4, 1], [5, 1], [6, 4], [7, 4], [1, 4], [3, 3]]
2D Array = [[1 4]
[2 3]
[3 1]
[4 1]
[5 1]
[6 4]
[7 4]
[1 4]
[3 3]]

Related

Check if list element is the result of adding other elements from list

Given a list of integers like this:
[10, 5, 7, 3, 2, 1, 50]
I would like to know which elements (if there is any) are the result of adding other two (or multiple) elements from the list. In this case, the output would be like:
10 -> [5, 3, 2]
10 -> [7, 3]
10 -> [7, 2, 1]
5 -> [3, 2]
7 -> [5, 2]
3 -> [2, 1]
Is there an efficient way to get this output? Note that the input list could be a very large one.
Get all possible combinations of smallest to largest list, then compare the sum of each list, to each element in lst to see if they are the same, then print them out.
import itertools
lst = [10, 5, 7, 3, 2, 1, 50]
combs = []
for i in range(1, len(lst)+1):
[combs.append(list(x)) for x in itertools.combinations(lst, i) if len(list(x)) > 1]
for i in lst:
for c in combs:
if sum(c) == i:
print(i,c)
Note that this,
if len(list(x)) > 1
Gets rid of lists that just contain one number.
Output
10 [7, 3]
10 [5, 3, 2]
10 [7, 2, 1]
5 [3, 2]
7 [5, 2]
3 [2, 1]

Random change of rows of two matrices using indices

Any idea or clue about writing below problem code in python 3.6?
Imagine I have matrix A and B as below:
A = [1 2, 3 4, 5 6] with the dimension of 3*2
B = [1, 3, 5] with the dimension of 3*1
Now I want to change the rows randomly using indices.
for instance index 1 related to [1 2] from A and [1] from B, index 2 related to [3 4] from A and [3] from B, index 3 related to [5 6] from A and [5] from B.
Imagine randomly I order the indices as 2, 3, 1, now my output will be:
A=[3 4, 5 6, 1 2]
B=[3, 5, 1]
import numpy as np
A = [[1, 2],[3, 4], [5, 6]]
A = np.array(A)
B = [[1], [3], [5]]
B = np.array(B)
import random
def rand(n):
l = list(range(n))
random.shuffle(l)
l = np.reshape(l, (n,1)) return l l = rand(3)
print(l)
AF = []
AFF = []
BF = []
BFF = []
for i in range (0, len(A)):
AF = A[l[i]]
AFF.extend(AF)
BF = B[l[i]]
BFF.extend(BF)
B = np.array(BFF)
A = np.array(AFF)
print(B)
print(A)

Reducing time complexity in comparing contiguous subarrays?

So say I have a list sequences such as this.
I want to remove all sequences where its total sum = N and/or it has a contiguous subarray with sum = N.
For example, if N = 4, then (1,1,2) is not valid since its total is 4. (1,1,3) is also not valid since the (1,3) is also 4. (1,3,1) is also not valid for the same reason.
lst = [
(1,1,1), (1,1,2), (1,1,3),
(1,2,1), (1,2,2), (1,2,3),
(1,3,1), (1,3,2), (1,3,3),
(2,1,1), (2,1,2), (2,1,3),
(2,2,1), (2,2,2), (2,2,3),
(2,3,1), (2,3,2), (2,3,3),
(3,1,1), (3,1,2), (3,1,3),
(3,2,1), (3,2,2), (3,2,3),
(3,3,1), (3,3,2), (3,3,3)
]
E.g.
Input: 4 3
Output: 2 1 2
So what I have right now is
lst = [t for t in list(product(range(1,n),repeat=n-1)) if not any((sum(t[l:h+1]) % n == 0) for l, h in combinations(range(len(t)), 2))]
Currently it is in O(n2) if I'm not mistaken. What would be a better way to do this?
If you can use numpy, you can concatenate the total sum of each tuple with the contiguous value sums, then check if any of your resultign elements are equal to 4:
arr = np.array(lst)
arr[~(np.concatenate((np.sum(arr,axis=1).reshape(-1,1),
(arr[:,:-1]+ arr[:,1:])),axis=1) == 4).any(1)]
# or:
arr[(np.concatenate((np.sum(arr,axis=1).reshape(-1,1),
(arr[:,:-1]+ arr[:,1:])),axis=1) != 4).all(1)]
Returning:
array([[1, 1, 1],
[1, 2, 3],
[2, 1, 2],
[2, 3, 2],
[2, 3, 3],
[3, 2, 1],
[3, 2, 3],
[3, 3, 2],
[3, 3, 3]])

Python 3, difference between print("x:\n{}".format(x)) and print("x:\n",x)?

import numpy as np
x = np.array([[1, 2, 3], [4, 5, 6]])
print("x:\n{}".format(x))
print("x:\n",x)
what is the difference between print("x:\n{}".format(x)) and print("x:\n",x) ?
I do not understand the concept of print("x:\n{}".format(x)) and how it works!
when you say .format what is the dot referring to? to what ever is inside ""?
why we need {}?
Thanks
The curly braces are to contain "replacement" fields that describe to the format engine what should be placed in the output. That is, they are special characters the parser uses to determine how to format a particular string object.
If you had multiple arguments to your print function the utility becomes a little clearer:
import numpy as np
x = np.array([[1, 2, 3], [4, 5, 6]])
y = np.array([[1, 2, 3], [4, 5, 6]])
z = np.array([[1, 2, 3], [4, 5, 6]])
print("x:\n", x, y, z)
Out:
x:
[[1 2 3]
[4 5 6]] [[1 2 3]
[4 5 6]] [[1 2 3]
[4 5 6]]
And:
print("x:\n{}\n\n{}\n\n{}".format(x, y, z))
Out:
x:
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
Or even:
a_list_of_terms = ['the', 'knights', 'who', 'say', 'ni']
print("{}".format(a_list_of_terms))
Out:
['the', 'knights', 'who', 'say', 'ni']
Or you can unpack a list using * for:
print("We are {} {} {} and we demand a shrubbery.".format(*a_list_of_terms))
Out:
'We are the knights who and we demand a shrubbery.'
You can find the official documentation here

Returning the N largest values' indices in a multidimensional array (can find solutions for one dimension but not multi-dimension)

I have a numpy array X, and I'd like to return another array Y whose entries are the indices of the n largest values of X i.e. suppose I have:
a =np.array[[1, 3, 5], [4, 5 ,6], [9, 1, 7]]
then say, if I want the first 5 "maxs"'s indices-here 9, 7 , 6 , 5, 5 are the maxs, and their indices are:
b=np.array[[2, 0], [2 2], [ 2 1], [1 1], [0 , 2])
I've been able to find some solutions and make this work for a one dimensional array like
c=np.array[1, 2, 3, 4, 5, 6]:
def f(a,N):
return np.argsort(a)[::-1][:N]
But have not been able to generate something that works in more than one dimension. Thanks!
Approach #1
Get the argsort indices on its flattened version and select the last N indices. Then, get the corresponding row and column indices -
N = 5
idx = np.argsort(a.ravel())[-N:][::-1] #single slicing: `[:N-2:-1]`
topN_val = a.ravel()[idx]
row_col = np.c_[np.unravel_index(idx, a.shape)]
Sample run -
# Input array
In [39]: a = np.array([[1,3,5],[4,5,6],[9,1,7]])
In [40]: N = 5
...: idx = np.argsort(a.ravel())[-N:][::-1]
...: topN_val = a.ravel()[idx]
...: row_col = np.c_[np.unravel_index(idx, a.shape)]
...:
In [41]: topN_val
Out[41]: array([9, 7, 6, 5, 5])
In [42]: row_col
Out[42]:
array([[2, 0],
[2, 2],
[1, 2],
[1, 1],
[0, 2]])
Approach #2
For performance, we can use np.argpartition to get top N indices without keeping sorted order, like so -
idx0 = np.argpartition(a.ravel(), -N)[-N:]
To get the sorted order, we need one more round of argsort -
idx = idx0[a.ravel()[idx0].argsort()][::-1]

Resources