Since we are doing homework now.
def unimod(seq):
"""
Return longest unimodal sequence in seq.
A sequence is unimodular when a0≤a1≤...≤ai≥ai+1≥...ad
"""
if len(seq) < 3: # No sequences < 3 are unimodular(?)
return []
ascending = None # We don't know if we are ascending or descending
_, start, end = longest = (0, 0, 0)
for p, n in zip(seq, seq[1:]):
if ascending is None:
# Have we found the first valley?
if n >= p:
ascending = True
start = end
elif ascending:
# Are we still ascending?
ascending = n >= p
elif n > p:
# Found start of next mountain. Was last mountain the longest?
ascending = True
longest = max(longest, (end-start+1, start, end+1))
# Back up to the start of the valley
start = end
while start > 0 and seq[start-1] == p:
start -= 1
end += 1
if ascending == False:
# Last sequence is unimodular. Is it longest?
longest = max(longest, (end-start+1, start, end+1))
_, start, end = longest
return seq[start:end]
# Test some sequences
assert(unimod([]) == [])
assert(unimod([1,2]) == [])
assert(unimod([2,1,2]) == [])
assert(unimod([5,4,3,2,1,2,3]) == [])
assert(unimod([1,2,1]) == [1,2,1])
assert(unimod([2,1,2,1,2]) == [1,2,1])
assert(unimod([5,4,3,2,1,2,1,2,3,4,5]) == [1,2,1])
assert(unimod([2,1,2,1,1,1,2,2,1]) == [1,1,1,2,2,1])
assert(unimod([1,2,3,2,1,2,3,3,2,1]) == [1,2,3,3,2,1])
This is a one trick pony. I prefer writing more generic tools and using them to solve multiple problems. With a small modification unimod becomes a unimodal sequence generator. I can still find the longest sequence using max(). And if I only want the length, len(max())
def unimod(seq):
"""
Generate unimodal sequences found in seq.
A sequence is unimodular when a0≤a1≤...≤ai≥ai+1≥...ad
"""
if len(seq) < 3: # No sequences < 3 are unimodular(?)
return []
ascending = None
start = end = 0
for p, n in zip(seq, seq[1:]):
if ascending is None:
# Have we found the first valley?
if n >= p:
ascending = True
start = end
elif ascending:
# Are we still ascending?
ascending = n >= p
elif n > p:
# Found start of next mountain. Was last mountain the longest?
ascending = True
yield(seq[start:end+1])
# Back up to the start of the valley
start = end
while start > 0 and seq[start-1] == p:
start -= 1
end += 1
if ascending == False:
# Last sequence is unimodular. Is it longest?
yield(seq[start, end+1])
sequences = list(unimod([3,2,1,2,1,2,3,2,1,2,3,4,3,2,1,2,1,2,3]))
longest = max(sequences, key=len)
print("Unimodal sequences =", sequences)
print("Longest sequence =", longest, 'Length =', len(longest))
Output:
Unimodal sequences = [[1, 2, 1], [1, 2, 3, 2, 1], [1, 2, 3, 4, 3, 2, 1], [1, 2, 1]]
Longest sequence = [1, 2, 3, 4, 3, 2, 1] Length = 7