Get counters within cycles - python

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

Related

Check if python list elemnts respect a pattern

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.

How can I select a specific number in a list with duplicates without removing the previous same values?

I have the following list in python3:
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
I want to have something like this as an output:
b = [1, 2, 3, 1, 2, 4, 3]
How can I do that? I have tried a = set(a) and other methods for getting rid of duplicates. But they remove all duplicates.
If you are willing to use a module, you can use itertools.groupby:
from itertools import groupby
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
output = [k for k, _ in groupby(a)]
print(output) # [1, 2, 3, 1, 2, 4, 3]
This would work:
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
b = [a[0]]
for k in a:
if k!=b[-1]:
b.append(k)
print(b)
If you comfortable with C, you may like this style:
a = [1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3]
b=len(a)
i=0
last_one=None
while i<b:
if a[i]==last_one:
del a[i]
b-=1
continue
else:
last_one=a[i]
i+=1
print(a)

Permutations of a list in Python - converting JS solution

I'm converting a working JavaScript solution for for calculating the permutations of an array over to Python, and I wanted to know why the translation doesn't work exactly the same way. Specifically, it appears as though the memo list I'm using to keep track of values is continually appended and never cleared, but I'm unsure as to what differences in Python's underpinnings cause this effect. Here's my code in Python:
def perms(input):
result = []
def permute(arr, m):
if len(arr) == 0:
print('this is m appending!: ', m)
print('=============================')
result.append(m)
else:
for i in range(len(arr)):
curr = arr.copy()
next = curr.pop(i)
m.append(next)
print('curr: ', curr)
print('next: ', next)
print('m: ', m)
permute(curr, m)
print('running')
permute(input, [])
return result
answer = perms([1,2,3])
print(answer)
and here is the output:
running
curr: [2, 3]next: 1m: [1]
curr: [3]
next: 2
m: [1, 2]
curr: []
next: 3
m: [1, 2, 3]
this is m appending!: [1, 2, 3]
=============================
curr: [2]
next: 3
m: [1, 2, 3, 3]
curr: []
next: 2m: [1, 2, 3, 3, 2]this is m appending!: [1, 2, 3, 3, 2]
=============================
curr: [1, 3]
next: 2
m: [1, 2, 3, 3, 2, 2]
curr: [3]
next: 1
m: [1, 2, 3, 3, 2, 2, 1]
curr: []
next: 3
m: [1, 2, 3, 3, 2, 2, 1, 3]
this is m appending!: [1, 2, 3, 3, 2, 2, 1, 3]
=============================
curr: [1]
next: 3
m: [1, 2, 3, 3, 2, 2, 1, 3, 3]
curr: []
next: 1
m: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1]
this is m appending!: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1]
=============================
curr: [1, 2]
next: 3
m: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3]
curr: [2]
next: 1
m: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1]
curr: []
next: 2m: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2]this is m appending!: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2]
=============================
curr: [1]
next: 2
m: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2]
curr: []
next: 1
m: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1]
this is m appending!: [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1]
=============================
[[1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1], [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1], [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1], [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1], [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1], [1, 2, 3, 3, 2, 2, 1, 3, 3, 1, 3, 1, 2, 2, 1]]
As you can see, the first result ([1,2,3]) is processed as intended (as you can see where I print 'this is m appending' to the results list).However, m fails to "back out" appended items when the recursion steps backwards to execute. I'm assuming this is because Python manages the stack differently, but I'm unsure. If it's helpful, I can also post the JavaScript code and results.
If someone could explain to me why exactly this code is failing, that would be great!
Olvin's comment was correct that the issue was caused by nonlocal scoping, and Ajay's comment was a good fix for the problem - basically backing out the changes to the list manually after recursion. Here's the now-functioning code:
def perms(input):
result = []
def permute(arr, m = []):
if len(arr) == 0:
result.append(m.copy())
else:
for i in range(len(arr)):
curr = arr.copy()
nextItem = curr.pop(i)
m.append(nextItem)
permute(curr, m)
m.pop()
print('running')
permute(input)
return result
answer = perms([1,2,3])
print(answer)

Combinations with limited repeats in Python

I know how to get ALL combinations of a list in Python with itertools, but what if I want to limit the amount of repeats?
So, if I have [1, 2, 3, 4, 5]
But I want to limit combinations to only 3 repeats of each item (with a fixed length of the final list, say 10):
[1, 1, 1, 2, 3, 3, 5, 5, 5, 4]
[1, 2, 3, 3, 3, 4, 5, 5, 4, 4]
[4, 4, 1, 1, 1, 5, 2, 2, 2, 3]
and so on. How do I do this?
This would work:
import random
L = [1, 2, 3, 4, 5]
L3 = L * 3
random.shuffle(L3)
L3[:10]
I don't know if there is a more elegant way but that seems to work:
from itertools import combinations_with_replacement
a = [1, 2, 3, 4, 5] # can contain letters as well
all_combinations = combinations_with_replacement(a, 10)
filtered_results = []
for current in all_combinations:
throw_away = False
for item in current:
if current.count(item) > 3:
throw_away = True
break
if not throw_away:
filtered_results.append( current )
for j in filtered_results:
print(j)
You could do it the following way: Use [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5] and use itertools.combination(the list from above, 10). That would mean that each element occurs at most three times in a resulting list.
Example with smaller list:
Edited to ensure every combination occurs exactly once, the combinations occur in random order and, finally, every combination has a random order.
Also incorporated the idea of Mike Müller to just multiply the list by 3.
import itertools
import random
combinations = set()
for c in itertools.combinations(sorted([1, 2, 3] * 3), 5):
combinations.add(c)
shuffledCombinations = list(combinations)
random.shuffle(shuffledCombinations)
for combination in shuffledCombinations:
copiedCombination = list(combination)
random.shuffle(copiedCombination)
print copiedCombination
which will give:
[2, 1, 3, 2, 2]
[2, 2, 1, 1, 2]
[3, 3, 3, 1, 2]
[2, 2, 3, 2, 3]
[1, 2, 3, 1, 2]
[1, 1, 1, 2, 3]
[2, 1, 1, 1, 2]
[3, 3, 1, 1, 1]
[1, 3, 3, 3, 1]
[3, 2, 3, 2, 3]
[3, 2, 1, 2, 3]
[1, 1, 2, 3, 3]

How to count in a row results from text file

i would like to know how to count in a row results from text file. I wroted this code:
from itertools import groupby
def count_runs_of(seq, val):
return sum(key == val for key, group in groupby(seq))
Example:
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 3)
1
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
2
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3, 9, 2, 4, 3, 3, 3], 3)
3
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 2)
2
I want to know how long serie it is. For example, when i have "1" in first result, i want to also print "3" (because there was 3 x 3 in a row). Could You help me? Thank You
def count_runs_of(seq, val):
return [len(list(group)) for key, group in groupby(seq) if key == val]
Example
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
[3, 2]
You were pretty close, you get get the length of a group by looping on it using sum() and generator expression. This will return length of all such runs in the list:
>>> def count_runs_of(seq, val):
return [sum(1 for _ in g) for k, g in groupby(seq) if k == val]
...
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4], 3)
[3]
>>> count_runs_of([1, 2, 3, 3, 3, 1, 2, 2, 4, 3, 3], 3)
[3, 2]

Categories

Resources