Two symbols we reuse everywhere below (defined once, so nothing is unearned):
⌈x⌉ means round up — the smallest whole number that is not below x. Example: ⌈3.1⌉=4, ⌈3.0⌉=3. We round up because even a tiny leftover distance to stop still fits one more term before we cross the wall.
[start,stop) is a half-open interval: the square bracket [ means include the left end, the round bracket ) means exclude the right end. That single round bracket is the whole personality of range().
WHAT: Single-argument form → start = 0, step = 1, stop = 6.
Terms:ak=0+k⋅1=k. Keep while ak<6: k=0,1,2,3,4,5.
Output:[0, 1, 2, 3, 4, 5].
Count:n=⌈(6−0)/1⌉=6. This is the golden identity len(range(n)) == n.
Recall Solution
WHAT: Two-argument form → step = 1, start = 3, stop = 8.
Terms:ak=3+k. Include while 3+k<8, i.e. k<5, so k=0..4.
Output:[3, 4, 5, 6, 7]. Note the wall at 8 is never landed on.
Count:⌈(8−3)/1⌉=5.
Recall Solution
type(r) is <class 'range'> — not a list. A range is a lazy immutable sequence: it stores only start, stop, step and computes any element on demand.
But it supports indexing like a sequence: r[2] = a_2 = 0 + 2\cdot 1 = 2. So r[2] is 2.
Terms:ak=2+4k: 2,6,10,14,18. Next is a5=22<20, so stop.
Output:[2, 6, 10, 14, 18].
Count:n=⌈(20−2)/4⌉=⌈18/4⌉=⌈4.5⌉=5 ✓.
Recall Solution
WHY negative step: to descend — each hop goes left on the number line (the mirror image of the mint-dot figure above).
WHY the test flips to ak>stop: when we walk leftward, "we haven't crossed the stop wall yet" means "we are still strictly abovestop." So the moment a term drops to or below stop, we halt. This is the descending case proved in the box above — same ceiling formula, flipped inequality.
Terms:ak=20−3k: 20,17,14,11,8,5. Next is a6=2>4, so stop.
Output:[20, 17, 14, 11, 8, 5].
Count:n=⌈(4−20)/(−3)⌉=⌈(−16)/(−3)⌉=⌈5.33⌉=6 ✓.
Interval view: this is the half-open interval [20,4)read downward — 20 is included, 4 is the excluded left-wall we descend toward but never land on.
Recall Solution
Because stop is excluded, to make 100 appear we must aim one past it: range(1, 101).
Check: last term a99=1+99=100<101 ✓; a100=101<101 ✗. Count =⌈(101−1)/1⌉=100.
Recall Solution
range(1, 6) yields 1, 2, 3, 4, 5. Sum =1+2+3+4+5=15. It prints 15.
(This is an arithmetic sum; see also for loops for the iteration mechanics.)
Count first (the point of the formula):n=⌈(50−7)/5⌉=⌈43/5⌉=⌈8.6⌉=9.
First:a0=7.
Last:an−1=a8=7+8⋅5=47. Indeed 47<50 and 52<50 ✓.
So the range is 7, 12, 17, 22, 27, 32, 37, 42, 47 — nine numbers.
Recall Solution
(a) ⌈(5−5)/1⌉=⌈0⌉=0 → empty[].
(b) ⌈(2−9)/1⌉=⌈−7⌉=−7, then max(0,−7)=0 → empty (going up but start already above stop).
(c) ⌈(9−2)/(−1)⌉=⌈−7⌉=−7→max(0,−7)=0 → empty (going down but start below stop; the descending test ak>9 fails immediately since a0=2>9).
(d) ⌈(2−9)/(−1)⌉=⌈7⌉=7 → 7 elements: 9, 8, 7, 6, 5, 4, 3. Not empty.
The pattern: a range is non-empty exactly when the sign of step matches the direction from start to stop — which is precisely when the ceiling fraction is positive and the max(0, …) guard does nothing.
Recall Solution
len(r):⌈(40−4)/6⌉=⌈36/6⌉=⌈6⌉=6.
r[3]: use the term rule directly — a3=4+3⋅6=22.
Ranges support O(1) indexing precisely because they never store the numbers; they recompute ak each time. This mirrors Indexing and slicing.
start = first term = 3.
step = gap between consecutive terms = 8−3=5.
stop = must exclude the term after the last: the last term is 23, and the next would-be term is 23+5=28. So we need stop big enough to keep 23 but small enough to reject 28. The valid window is 23<stop≤28 (any stop here yields the identical list).
What "shortest" means here: since every valid stop gives the same output, "shortest" refers to the range(...) call whose stop literal is the smallest number of characters / smallest value. Among {24,25,26,27,28} the minimal valid stop is 24 — the smallest integer strictly above the last term 23. Choosing 24 also makes the intent clearest ("stop just past 23"), whereas 28 accidentally equals the next term and invites the reader to wonder if it should have appeared.
Call:range(3, 24, 5). Check count ⌈(24−3)/5⌉=⌈21/5⌉=⌈4.2⌉=5 ✓.
Recall Solution
(a)range(5, 0, -1) → terms 5,4,3,2,1 (stop 0 excluded). ✓
(b)list(reversed(range(1, 6))) → range(1,6) is 1,2,3,4,5, reversed → 5,4,3,2,1. ✓
Both produce [5, 4, 3, 2, 1]. The negative-step form is usually clearer; reversed() is handy when the forward range already exists.
Recall Solution
Outer count:range(0, 6, 2) → 0, 2, 4 → ⌈6/2⌉=3 iterations.
Inner count:range(1, 4) → 1, 2, 3 → 3 iterations, and it restarts fully for each outer value.
Total:3×3=9 prints.
Multiples of 7 in [0,1000) are 0, 7, 14, …. Model as range(0, 1000, 7).
Count:n=⌈(1000−0)/7⌉=⌈142.857…⌉=143.
Check the last term:a142=0+142⋅7=994<1000 ✓; a143=1001<1000 ✗. So the largest multiple below 1000 is 994, and there are 143 multiples.
Recall Solution
(a)ValueError: range() arg 3 must not be zero. A zero step would never advance ak, so it could never reach stop — Python refuses rather than loop forever.
(b)TypeError. range accepts integers only; 0.5 is a float. For float steps use numpy.arange or linspace.
(c) Negative start is perfectly legal (only step = 0 and floats are banned). ak=−3+k, include while <3: [-3, -2, -1, 0, 1, 2]. Count ⌈(3−(−3))/1⌉=6.
Recall Solution
Same term rule: both have step = 1, so ak=a+k for both — identical terms in identical order.
Same count: both give n=max(0,⌈(b−a)/1⌉)=max(0,b−a).
If a<b: n=b−a>0, sequence a, a+1, …, b-1.
If a≥b: b−a≤0, so n=0, sequence is empty [] — the max(0, …) handles the degenerate case for both.
Since term rule and count coincide in every case, the two calls are identical. (The one-argument default is just this with a = 0.)