> .
, any(g) and not any(g), , , / ( , , and ...).
def cumulative_sums(values):
s = 0
for v in values:
s += v
yield s
def count_in_bounds(iterable, start=1, stop=2):
counter = cumulative_sums(bool(x) for x in iterable)
return (start in counter) and (stop not in counter)
bool, , any() all(), - .
Taking an arbitrary [start, stop) is a great bonus, but it is not as general as we would like. It is tempting to pass on stop=Noneto follow, for example. any()which works, but always consumes all input; awkward correct emulation:
def any(iterable):
return not count_in_bounds(iterable, 0, 1)
def all(iterable):
return count_in_bounds((not x for x in iterable), 0, 1)
Taking a variable number of bounds and specifying what should return True / False will get out of control.
Perhaps a simple saturating counter is the best primitive:
def count_true(iterable, stop_at=float('inf')):
c = 0
for x in iterable:
c += bool(x)
if c >= stop_at:
break
return c
def any(iterable):
return count_true(iterable, 1) >= 1
def exactly_one(iterable):
return count_true(iterable, 2) == 1
def weird(iterable):
return count_true(iterable, 10) in {2, 3, 5, 7}
all()still requires denying inputs or a suitable helper count_false().