Build RangeIterator(start, end, step=1), an iterator over integers that behaves like Python's range but is written by hand (don't call range or itertools inside it).
- It produces
start,start + step,start + 2*step, … and stops before reachingend(endis exclusive). - A positive
stepcounts upwards and stops once a value would be>= end; a negativestepcounts downwards and stops once a value would be<= end. - If the direction of
stepcan never reachend(for examplestart=5, end=1, step=2), the iterator is simply empty. step == 0raisesValueErrorin the constructor.
Methods:
has_next() -> bool: is there another value?next() -> int: return the next value and advance. RaiseStopIterationwhen exhausted.remaining() -> int: how many values are still to come, in O(1).- It must also work in a
forloop: implement__iter__(returningself) and__next__.
it = RangeIterator(2, 11, 3)
it.remaining() # 3
it.next() # 2
list(it) # [5, 8]
it.has_next() # False
list(RangeIterator(10, 0, -4)) # [10, 6, 2]
list(RangeIterator(-3, -3)) # []
list(RangeIterator(5, 1, 2)) # []
Values can be as large as 10**18, and a range may hold that many values: the iterator must be lazy (constant memory, O(1) per call).
Show hint
Keep only the next value to produce. With step > 0 the next value exists while cur < end; with step < 0, while cur > end. The count left is a ceiling division: max(0, (end - cur + step - (1 if step > 0 else -1)) // step).