Back to Scan

Iterators · Scan · Practice Question

Generate Even Numbers Up to N

Sign in to track your progress

Question

Write a function f that takes a number and returns all even numbers from 2 up to and including that number.

q)f 20
2 4 6 8 10 12 14 16 18 20

Solution

f:{-1_(2+)\[x>=;2]}

Alternative Solution

f:{a where not mod[a:1+til x;2]}

Explanation

Scan-while form — the primary solution uses the While form of Scan:

function\[condition;seed]

It starts at 2 and repeatedly applies (2+) — a projection of + with its left argument fixed to 2 — for as long as the condition x>= (a projection of >= with left argument x) is true of the latest value. Scan collects every value along the way.

Trace for f 9:

2      9>=2  true  → apply (2+) → 4
4      9>=4  true  → apply (2+) → 6
6      9>=6  true  → apply (2+) → 8
8      9>=8  true  → apply (2+) → 10
10     9>=10 false → stop
scan result: 2 4 6 8 10

The While form stops when the condition fails, but the value that failed it (10) has already been produced and is part of the result. That last value is always one step too far, so -1_ drops it, giving 2 4 6 8. Without the -1_, the function would return 2 4 6 8 10 for f 9, and ,2 for f 1.

Filter form — the alternative builds the full integer list 1+til x (i.e., 1 2 3 … x), assigns it to a, then keeps elements where mod[a;2] is zero (not 1). mod[a;2] returns 0 for evens and 1 for odds, so not mod[a;2] is a boolean mask selecting even positions.

a                    : 1 2 3 4 5 6 7 8 9 10
mod[a;2]             : 1 0 1 0 1 0 1 0 1 0
not mod[a;2]         : 0101010101b
a where not mod[a;2] : 2 4 6 8 10

The scan-while approach generates only the values it needs; the filter approach builds the full list 1 2 … x first, trading a little memory for clarity. (A third option avoids both iteration and filtering: {2*1+til x div 2}.)