Problem: split a list of ints such that the sums of the sublists are bounded (by 10)
Here’s how I would solve it in python using a scan to do the conditional logic:
l = random.choices(range(5), k=30)
[2, 3, 3, 1, 4, 0, 3, 2, 0, 3, 3, 1, 2, 0, 2, 1, 2, 4, 4, 3, 1, 4, 2, 0, 3, 1, 4, 1, 0, 2]
scan_result = *itertools.accumulate(l, lambda acc, x: x if acc + x >= 10 else acc + x),
(2, 5, 8, 9, 4, 4, 7, 9, 9, 3, 6, 7, 9, 9, 2, 3, 5, 9, 4, 7, 8, 4, 6, 6, 9, 1, 5, 6, 6, 8)
adjacent_map = lambda fn, l: itertools.starmap(fn, zip(l, l[1:]))
mask = (0, *adjacent_map(lambda a, b: int(a > b), scan_result))
(0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0)
With the mask you can then cut you original list into the desired list of lists.
You could do it in one go in the scan
by returning the mask as well. But then you lambda becomes awkward lambda acc, x: (x, 1, x) if acc[0] + x >= 10 else (acc[0] + x, 0, x)
.
This is not very satisfactory. It has poor separation of concerns. acc[0]
is only needed for the logic of the scan and is not needed after. Only acc[1:]
is needed after. What I want is a scan algorithm that splits what you return: result[0]
becomes the next accumulator, result[1:]
the yielded output of the scan.
Has this problem been solved before? Is there any prior art?
It seems you have to write you own library to get half decent solutions. I think my problem is I program in c++ but don’t write my own iterators/ranges.