Problem overview
The function min_value receives three i32 integers, a, b and c, and returns the smallest of them. The task forbids built-in helpers such as min, so the comparison has to be written by hand.
With a = 7, b = 4 and c = 9 the answer is 4. With a = 3, b = 8 and c = 3 the answer is 3: when the smallest value appears twice, you return it once, and it doesn't matter which copy you pick.
Approach: keep the smallest value seen so far
One way is to test each candidate: a is the answer if a <= b and a <= c, then b under the same kind of test, and otherwise c. That works, but every extra number would need a longer condition.
The version in this lesson scales better. It keeps one variable, min_val, that always holds the smallest value looked at so far:
- Start by assuming
ais the smallest, since it is the only number seen. - Look at
b. If it is smaller thanmin_val, it becomes the new smallest. - Look at
cthe same way. - After the last comparison,
min_valholds the smallest of all three.
With 4 numbers you would add one more if; with 1,000 numbers you would replace the if statements with a loop. The idea does not change.
Trace it on a = 7, b = 4, c = 9. min_val starts at 7. Since 4 < 7, it becomes 4. Since 9 < 4 is false, it stays 4. The function returns 4.
Step by step
- Declare
min_valwithlet mutand set it toa. Themutkeyword is required because later steps assign a new value to it. - Compare
bwithmin_val. The test is strictly "less than". An equal value would change nothing anyway, so the extra assignment is skipped. - Assign
btomin_valinside thatif. - Write a second, separate
ifforc. It must not be anelsebranch of the first one. Even whenbreplaceda,cstill has to be compared with the new minimum. - Return
min_val.
The solution in Rust
impl Solution {
fn min_value(a: i32, b: i32, c: i32) -> i32 {
let mut min_val = a;
if b < min_val {
min_val = b;
}
if c < min_val {
min_val = c;
}
return min_val;
}
}
The Rust details in these few lines:
- Variables are immutable by default. Without
mut, the linemin_val = b;fails to compile with "cannot assign twice to immutable variable". Rust even suggests addingmut. - No parentheses around conditions. Rust writes
if b < min_val {, and the braces are mandatory, even for a one-line body. - The condition must be a
bool. Rust doesn't treat numbers as true or false, soif min_valwould not compile. returnis optional at the end. The last expression of a function, written without a semicolon, is returned automatically. Writingmin_valalone as the final line is the usual Rust style, andreturn min_val;means the same thing here.- Parameters are copied. An
i32is a small value that is copied when passed, so changingmin_valnever affects the caller's variables.
Edge cases and common mistakes
- Negative numbers.
min_value(-5, -9, -1)returns-9. Startingmin_valatarather than at a fixed number is what makes every input work. A start value of0would wrongly return0for7, 4, 9. - Equal values.
min_value(3, 8, 3)returns3, andmin_value(5, 5, 5)returns5. - Using
else iffor the second check. Witha = 9,b = 4,c = 2, the firstifsetsmin_valto 4, and anelse ifwould then skipcand return 4 instead of 2. - Largest and smallest values.
min_value(i32::MAX, i32::MIN, 0)returnsi32::MIN. Comparisons can't overflow, unlike arithmetic.
Testing
min_value(7, 4, 9)gives4.min_value(3, 8, 3)gives3.min_value(1, 2, 3)gives1, the case whereanever gets replaced.min_value(9, 4, 2)gives2, the case where bothifstatements fire.min_value(-5, -9, -1)gives-9.
