Check if python list elemnts respect a pattern - python

I have a list that looks like :
L = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1]
I want to check if the sequence 2-1-2 is always respected or I have an outlier somewhere .
Is there a simple way to do this with python ?

from itertools import cycle
L = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
seq = cycle([2, 1])
for idx, el in enumerate(L):
if not el == next(seq):
raise ValueError(f"Sequence not followed at index {idx}")

What does "2-1-2 is always respected" mean, precisely?
I assume you want to check if Lis an alternating sequence of 2 and 1, starting with 2.
That's easy to check:
def check(L):
if len(L) < 3:
return False
even_indices_all_two = set(L[::2]) == {2}
odd_indices_all_one = set(L[1::2]) == {1}
return even_indices_all_two and odd_indices_all_one and L[-1] == 2
If you don't require L to end with 2, remove the and L[-1] == 2.
If you wonder about the many colons, check this post to understand slicing.
I use the set to check if a sequence contains only one distinct item.

Related

Get counters within cycles

Say I have a list as follows:
list_sequences = [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 3, 1]
I want to create another list with the count of the occurrences, but the occurrence of 2 and 3 is reset after an occurrence of 1.
Something like:
occurrence_list = [1, 1, 1, 2, 2, 2, 1, 1, 3, 1, 1, 2, 2, 3, 3, 4, 4, 4]
is there a simple pythonic way to do so?
You can use a defaultdict to keep account of what is going on:
from collections import defaultdict
list_sequences = [1, 2, 3, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3, 2, 3, 2, 3, 1]
def make_occurrence(seq):
counter = defaultdict(int)
occurrence = []
for item in seq:
count = counter[item] + 1
if item == 1:
counter.clear()
counter[item] = count
occurrence.append(count)
return occurrence
print(make_occurrence(list_sequences))
Output as requested

How to sum the values from one list to a specific section of another list in python?

I need to sum the values from a list to a specific section of a another list.
For example:
a = [... , 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...]
b = [3, 3, 3]
...
ab = [..., 1, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 1, ...]
I need a fast method because it will be repeated several times in a row and it shouldn't iterate through the whole list cause it is quite long (ca. 1000 elements). The indexes where the summation should be, are known.
Thx for any kind of help!
a = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
b = [3, 3, 3]
start_index = 5
for ind, _ in enumerate(b):
a[start_index + ind] += b[ind]
print(a)
[1, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 1]
You could try something like this:
a = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
b = [3, 3, 3]
def add_at_index(list1, list2, index_start):
for idx, v in enumerate(b):
a[idx + index_start] += b[idx]
return a
print(add_at_index(a, b, 4))
def merge_list(list1, list2, index):
if index + len(list2) > len(list1):
print("Invalid Index")
return None
for i in range(0, len(list2)):
list1[index + i] += list2[i]
return list1
# Main
a = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
b = [3, 3, 3]
# Choose an index in the third argument of the function
print(merge_list(a, b, 5))

Getting indexes of all max values in a list [duplicate]

This question already has answers here:
How to find all positions of the maximum value in a list?
(18 answers)
Closed 3 years ago.
Is there any way in Python to get all indexes of elements which contain max value of a list?
I've tried this:
list = [1, 3, 2, 2, 1, 1, 1, 2, 3, 2, 1, 1, 1, 3, 1, 1, 3]
m = list.index (max(list))
But this returns only the first index of all of those which have max value.
Try this :
l = [1, 3, 2, 2, 1, 1, 1, 2, 3, 2, 1, 1, 1, 3, 1, 1, 3]
mx = max(l)
m = [i for i,j in enumerate(l) if j==mx]
OUTPUT :
[1, 8, 13, 16]
You can compute the max then use a list comprehension to get the indices where the max is found:
l = [1, 3, 2, 2, 1, 1, 1, 2, 3, 2, 1, 1, 1, 3, 1, 1, 3]
x = max(l)
m = [i for i in range(len(l)) if l[i] == x]
print(m)
Output:
[1, 8, 13, 16]

How to find the minimum indices and break ties by the least used indices in Python?

I have a numpy array like the following:
A = np.array([[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 5, 1, 1, 1],
[1, 1, 1, 1, 3, 3, 1, 1],
[1, 1, 1, 1, 1, 1, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 4, 1, 1]])
I am looking for the minimum indices in each column. I found this using numpy.argmin as follows:
I = np.zeros(A.shape[1], dtype=np.int64)
for j in range(A.shape[1]):
I[j] = np.argmin(A[:, j])
This gives me I = [0, 0, 0, 0, 0, 0, 0, 0]. Since there are ties, I could obtain the following: I = [0, 1, 2, 3, 4, 0, 5, 1], where I break the ties by the index that is least used (from the previous indices).
In more details:
For j=0, we have np.argmin(A[:, 0]) in [0, 1, 2, 3, 4, 5] and, say, we choose np.argmin(A[:, 0]) = 0.
For j=1, we have np.argmin(A[:, 1]) in [0, 1, 2, 3, 4, 5] and we have to choose the minimum index from [1, 2, 3, 4, 5] since these indices are the least used (we already choose np.argmin(A[:, 0]) = 0 for j=0). Say, we choose np.argmin(A[:, 1])=1.
For j=2, we have np.argmin(A[:, 2]) in [0, 1, 2, 3, 4, 5] and we have to choose the minimum index from [2, 3, 4, 5] since these indices are the least used.
We continue in this way...
For j=5, we have np.argmin(A[:, 5]) in [0, 1, 3, 4] and we have to choose the minimum index from [0, 1, 3, 4] since these indices are the least used. Say we choose np.argmin(A[:, 5])=0.
For j=6, we have np.argmin(A[:, 6]) in [0, 1, 2, 4, 5] and we have to choose from [5] since these indices are the least used. We choose np.argmin(A[:, 6])=5.
For j=7, we have np.argmin(A[:, 7]) in [0, 1, 2, 3, 4, 5] and we have to choose from [1, 2, 3, 4, 5] since these indices are the least used. Say we choose np.argmin(A[:, 7])=1.
I hope it is clear. My question is how to find the minimum indices and break ties by the least used indices in Python?
You could use min combined with a dictionary for keeping the counts of each index:
import numpy as np
A = np.array([[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 5, 1, 1, 1],
[1, 1, 1, 1, 3, 3, 1, 1],
[1, 1, 1, 1, 1, 1, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 4, 1, 1]])
counts = {}
I = np.zeros(A.shape[1], dtype=np.int64)
for j in range(A.shape[1]):
_, _, i = min([(v, counts.get(i, 0), i) for i, v in enumerate(A[:, j])])
counts[i] = counts.get(i, 0) + 1
I[j] = i
print(I)
Output
[0 1 2 3 4 0 5 1]
The idea is to create the following key: (value, count of index, index), and then use the normal comparison of tuples, so if the values are equal the one with less counts of the corresponding index will be selected, if both counts are equal get the one with lower index will be selected.

Generating all lists that satisfy certain constraints in Python

I would like to generate the following lists in Python:
[1, 1, 1, 2, 2]
[1, 1, 2, 1, 2]
... etc
[2, 1, 2, 1, 1]
[2, 2, 1, 1, 1]
There are always two "2"s and three "1"s in any list.
My intuition suggests that I will need to use the itertools module to do this. However, I am not sure where to begin, though I have read the documentation and looked at examples. Any suggestions?
You can notice that the number of such lists is equal to the number of ways to place two "2"s in a sequence of length 5. This suggests the following solution:
n = 5 # total length
n2 = 2 # number of "2"s
for idx in itertools.combinations( xrange(n), n2 ):
print [ 2 if i in idx else 1 for i in xrange(n) ]
It's easy to see that the answer using permutations is iterating over n! solutions, while my solution iterates over n!/( (n-n2)! * n2!). For example if the input list is [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2], the solution using permutations is ~90,000,000 times slower (10! * 4!)
You can use itertools.permutations and set (to eliminate duplicates):
>>> from itertools import permutations
>>> for combo in set(permutations([1, 1, 1, 2, 2])):
... print(list(combo))
...
[1, 2, 1, 1, 2]
[2, 1, 1, 1, 2]
[2, 1, 2, 1, 1]
[2, 1, 1, 2, 1]
[1, 1, 2, 1, 2]
[1, 1, 1, 2, 2]
[1, 2, 1, 2, 1]
[1, 1, 2, 2, 1]
[1, 2, 2, 1, 1]
[2, 2, 1, 1, 1]
>>>
If the combinations need to be in order, then you can use sorted:
>>> for combo in sorted(set(permutations([1, 1, 1, 2, 2]))):
... print(list(combo))
...
[1, 1, 1, 2, 2]
[1, 1, 2, 1, 2]
[1, 1, 2, 2, 1]
[1, 2, 1, 1, 2]
[1, 2, 1, 2, 1]
[1, 2, 2, 1, 1]
[2, 1, 1, 1, 2]
[2, 1, 1, 2, 1]
[2, 1, 2, 1, 1]
[2, 2, 1, 1, 1]
>>>

Categories

Resources