Problem overview
This lesson has two functions. The helper clamp receives one number x and two limits, low and high, and returns x moved inside them: a number below low becomes low, a number above high becomes high, and any other number stays as it is. The function that is tested, clamp_all, receives a vector nums and the limits and returns a vector with every number clamped, in the same order. The task asks you to do the comparing in the helper by hand, without a built-in min, max or clamp.
For nums = [12, -3, 7, 25] with low = 0 and high = 20 the answer is [12, 0, 7, 20]. With negative limits, [-8, -1, 4] and limits -5 and 5 give [-5, -1, 4]. When both limits are 6, every number becomes 6. The limits are never in the wrong order: low is never greater than high.
Approach
Split the work. The helper knows how to handle one number; clamp_all knows how to visit every number. Once the helper is right, clamp_all is a plain loop that pushes the helper's answer for each number. Neither function has to think about the other's job, and each is easy to check on its own.
Step by step
- In
clamp, ifx < low, returnlow. - Then, if
x > high, returnhigh. - Return
x. Only a number between the limits gets here, so noelseis needed. - In
clamp_all, create an empty mutableVecnamedclamped. Rust works out its element type from what you push. - Loop over
&nums. Eachnumis a reference, so the loop doesn't take numbers out of the vector. - Push
Self::clamp(*num, low, high). The loop needs noif: the helper does all the comparing. - Return
clampedafter the loop.
The solution in Rust
impl Solution {
fn clamp(x: i32, low: i32, high: i32) -> i32 {
if x < low {
return low;
}
if x > high {
return high;
}
return x;
}
fn clamp_all(nums: Vec<i32>, low: i32, high: i32) -> Vec<i32> {
let mut clamped = Vec::new();
for num in &nums {
clamped.push(Self::clamp(*num, low, high));
}
return clamped;
}
}
Rust details
Self::clamp. Both functions live in animplblock, so one calls the other asSelf::clamp(...). A bareclamp(...)does not compile: the compiler reportscannot find function `clamp` in this scopeand suggestsSelf::clamp.*num. The loop gives references, but the helper takes ani32. Passingnumas it is fails withmismatched types, and the compiler suggests dereferencing it.- Early returns. Each
returnends the helper at once. After the firstifreturns, the second one only ever sees numbers that are not belowlow.
Why split the work
The helper is a tiny function with one job and a clear contract: one number and two limits in, one number out. That makes it easy to test alone. The three calls clamp(-3, 0, 20), clamp(25, 0, 20) and clamp(7, 0, 20) cover all three cases: below, above and inside. Once they behave, clamp_all can trust the helper and only has to repeat it.
If the rule ever changes, only the helper changes. The loop in clamp_all would stay exactly as it is. This is the habit the lesson is practising: when a task has a small piece that repeats, give the piece its own function with a name that says what it does.
The built-in you are not using
Rust numbers have their own clamp method, so 7i32.clamp(0, 20) gives 7. The task asks you to write the comparisons yourself so you see what such a method does. A built-in clamp also panics when the lower limit is greater than the upper one; the lesson guarantees that never happens, and the helper above has no such case to worry about.
The name clamp in your own impl block does not clash with the built-in: yours is called as Self::clamp(...), the built-in as a method on a number.
Trying it
clamp_all([12, -3, 7, 25], 0, 20) -> [12, 0, 7, 20]
clamp_all([-8, -1, 4], -5, 5) -> [-5, -1, 4]
clamp_all([3, 9, 6], 6, 6) -> [6, 6, 6]
clamp(-3, 0, 20), clamp(25, 0, 20), clamp(7, 0, 20) -> 0, 20, 7
Edge cases
Numbers that sit exactly on a limit stay where they are, and numbers far outside move to the nearest limit. For [0, 20, 1000, -1000] with limits 0 and 20 the result is [0, 20, 20, 0]: 0 and 20 are already inside, 1000 drops to 20 and -1000 rises to 0. A vector with one number works like any other, and wide limits leave it alone: [5] with limits -1000 and 1000 stays [5].
The vector is never empty in this lesson. If it were, the loop would simply not run and the function would return an empty vector.
Common mistakes
- Swapping the limits' roles. Returning
highfor a number belowlowflips the result. Read eachifaloud: "below the lower limit, return the lower limit". - Using
<=or>=. That is harmless for the result (a number equal tolowbecomeslowanyway), but it adds a case that is not needed. - Changing the order. Push in the loop's order and the result matches the input position by position.
- Doing the comparing in
clamp_all. The loop should only call the helper; that is the point of the split.
