2

I am trying to find the longest sequence of the minimum number in a list. For an example, for this list, resp_rates = [1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1], the minimum number is 1, and the lengths of sequences of 1's are, 2, 4, 3, 7 respectively. So, the length of the longest sequence is 7, but, my code prints 4.

Code:

resp_rates = [1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]
rr_min_current = np.amin(resp_rates)
print(rr_min_current)
count = 0
first = 1
min_rr_sequence = []
print(resp_rates)
for resp_rate in resp_rates:
    if resp_rate == rr_min_current and first == 1:
        count=count+1 
        first = 0
    elif resp_rate == rr_min_current and first == 0:
        count=count+1
    elif resp_rate != rr_min_current and first == 0:    
        min_rr_sequence.append(count)
        first = 1
        count = 0
#longest_min_rr_sequence.append(np.amax(min_rr_sequence))
print(min_rr_sequence)
longest_min_rr_sequence = np.amax(min_rr_sequence)
print(longest_min_rr_sequence)

Output:

1
[1, 1, 2, 89, 56, 4, 1, 1, 1, 1, 10, 5, 67, 1, 1, 1, 76, 5, 7, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1]
[2, 4, 3]
4
1
  • 1
    Your problem is that the longest sequence is at the very end, so the last elif in which you append the count of the sequence won't be reached. Commented Nov 18, 2018 at 12:37

4 Answers 4

2

A short solution using groupby:

from itertools import groupby

resp_rates = [1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]

out = -min((value, -len(list(group))) for value, group in groupby(resp_rates))[1]
print(out)
# 7

Some explanations: (value, -len(list(group))) for value, group in groupby(resp_rates)) generates tuples: (1, -2), (2, -1), (89, -1), ... (1, -4) ...

Taking the min will return the tuple with the smallest value, and if many have this same smallest value, the one with the greatest length (hence the use of -length to be able to do that with min).

We just have to keep the length from our smallest tuple and change its sign.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Your solution worked. Could you please find the flaw in my code?
1

Here you go (EDITED):

resp_rates = [1,1,1,1,1,1,1,1,1,1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]

lowest = resp_rates[0]
count = 0
max_count = 0

for i in resp_rates:
    if i < lowest:
        lowest = i
        count = 1
        max_count = count
    elif i == lowest:
        count = count + 1
        if count > max_count:
            max_count = count
    else:
        count = 0


print(max_count)

3 Comments

The longest sequence is at the end, so you need to do a count check after iterating on all values
The case of resp_rates = [1,1,1,1,1,1,1,1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1] shows, that the code of the accepted answer is flawn (gives 7 instead of 9)
Yes indeed it was. Corrected.
1

Do this:

In [72]: resp_rates = [1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]

In [73]: import itertools,operator
In [83]: r = max((list(y) for (x,y) in itertools.groupby((enumerate(resp_rates)),operator.itemgetter(1)) if x == min(resp_rates)), key=len)

In [84]: len(r)
Out[84]: 7

Comments

1

Adding a line min_rr_sequence.append(count) as done in code below corrects the flaw in the provided code:

import numpy as np
resp_rates = [1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]
rr_min_current = np.amin(resp_rates)
print(rr_min_current)
count = 0
first = 1
min_rr_sequence = []
print(resp_rates)
for resp_rate in resp_rates:
    if resp_rate == rr_min_current and first == 1:
        count=count+1 
        first = 0
    elif resp_rate == rr_min_current and first == 0:
        count=count+1
    elif resp_rate != rr_min_current and first == 0:    
        min_rr_sequence.append(count)
        first = 1
        count = 0
min_rr_sequence.append(count)

The problem was that the provided code didn't run .append(count) in case the longest counted sequence occurs at the very end of the resp_rates list.

As pointed out by Thierry Lathuille in his comment to the question the flaw in the code is that "the last elif in which you append the count of the sequence won't be reached."

Worth to notice fact is, that the by Thierry Lathuille provided solution using itertools.groupby(), min() and len() is almost 10 times faster as other of the provided (status: Nov. 18, 2018, 17:30 MEZ) approaches to this task.

Check it out for yourself on your system. Here the code:

import time
# resp_rates = [1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]
# resp_rates = [1,1,1,1,1,1,1,1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]
# resp_rates = [1,1,1,1,1,1,1,1,1,1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]
# resp_rates = [1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1]
# resp_rates = [5,1,1,2,89,56,4,1,1,1,1,10,5,67,1,1,1,76,5,7,6,6,6,1,1,1,1,1,1,1]
# resp_rates = [1,3,1,1,1,2,1,1,4,1,1,1,1]
resp_rates = [7,7,7,7,7,7,7,8,8,8,8,8,8,8,8]

# -----------------------------------------------------------------------------
print("# Original code with one line added to make it print correct result:")
import numpy as np

largeList = 20000000*[5]
resp_rates = resp_rates + largeList 

timeNOW = time.time()
rr_min_current = np.amin(resp_rates)
# print(rr_min_current)
count = 0
first = 1
min_rr_sequence = []
# print(resp_rates)
for resp_rate in resp_rates:
    if resp_rate == rr_min_current and first == 1:
        count=count+1 
        first = 0
    elif resp_rate == rr_min_current and first == 0:
        count=count+1
    elif resp_rate != rr_min_current and first == 0:    
        min_rr_sequence.append(count)
        first = 1
        count = 0
min_rr_sequence.append(count)

#longest_min_rr_sequence.append(np.amax(min_rr_sequence))
# print(min_rr_sequence)
longest_min_rr_sequence = np.amax(min_rr_sequence)
print("Result of timing", time.time() - timeNOW )
print(longest_min_rr_sequence)

# -----------------------------------------------------------------------------
print("# Provided solution using itertools.groupby(), min() and len(): ")
timeNOW = time.time()
from itertools import groupby
out = -min((value, -len(list(group))) for value, group in groupby(resp_rates))[1]
print("Result of timing", time.time() - timeNOW )
print(out)
# 7

# -----------------------------------------------------------------------------
print("# Provided solution using itertools.groupby() and operator.itemgetter(): ")
timeNOW = time.time()
import itertools, operator
r = max((list(y) for (x,y) in itertools.groupby((enumerate(resp_rates)),operator.itemgetter(1)) if x == min(resp_rates)), key=len)
print("Result of timing", time.time() - timeNOW )
print(len(r))


print("# Accepted answer: ")
timeNOW = time.time()
lowest = resp_rates[0]
count = 0
max_count = 0
for i in resp_rates:
    if i < lowest:
        lowest = i
        count = 1
    elif i == lowest:
        count = count + 1
    else:
        if count != 0:
            max_count = count
        count = 0

if count != 0:
    max_count = count

print("Result of timing", time.time() - timeNOW )
print(max_count)

print("# Accepted answer (EDITED): ")
timeNOW = time.time()

lowest = resp_rates[0]
count = 0
max_count = 0

for i in resp_rates:
    if i < lowest:
        lowest = i
        count = 1
        max_count = count
    elif i == lowest:
        count = count + 1
        if count > max_count:
            max_count = count
    else:
        count = 0
print("Result of timing", time.time() - timeNOW )
print(max_count)

Here the printout on my system:

python3.6 -u "longestSequence-ofMinimalNumber_Cg.py"
# Original code with one line added to make it print correct result:
Result of timing 10.655358791351318
20000000
# Provided solution using itertools.groupby(), min() and len(): 
Result of timing 0.3956716060638428
20000000
# Provided solution using itertools.groupby() and operator.itemgetter(): 
Result of timing 4.829622983932495
20000000
# Accepted answer: 
Result of timing 3.7705492973327637
20000000
# Accepted answer (EDITED): 
Result of timing 5.475024223327637
20000000

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.