5 ms·
I couldn't resist. import operator as op import itertools as it def mono_split(cmp, lst): start = len(list(it.takewhile(lambda t: cmp(
by mrtranscendence 5y ago
I couldn't resist.
import operator as op
import itertools as it
def mono_split(cmp, lst):
start = len(list(it.takewhile(lambda t: cmp(t[0], t[1]), zip(lst, lst[1:]))))
return lst[:start + 1], lst[start + 1:]
def get_mono_splits(lst):
while len(lst) >= 2:
if lst[0] == lst[1]:
yield [lst[0]]
lst = lst[1:]
else:
cmp = op.lt if lst[0] < lst[1] else op.gt
run, lst = mono_split(cmp, lst)
yield run
if len(lst) == 1:
yield lst
This assumes you're operating on lists and that monotonicity is strict. It's reasonably short, reasonably clear, and uses standard Python modules. Arguably the definition of start in mono_split could be confusing but I don't think it's too bad.
- mrtranscendence 5y agoOops, it doesn't reverse decreasing runs. Make that: import operator as op import itertools as it def mono_split(cmp, lst): start = len(list(it.takewhile(lambda t: cmp(t[0], t[1]), zip(lst, lst[1:])))) return lst[:start + 1], lst[start + 1:] def get_mono_splits(lst): while len(lst) >= 2: if lst[0] == lst[1]: yield [lst[0]] lst = lst[1:] else: cmp = op.lt if lst[0] < lst[1] else op.gt run, lst = mono_split(cmp, lst) if cmp == op.gt: run = list(reversed(run)) yield run if len(lst) == 1: yield lst