I realize the language is at 0.9/0.10 and undergoing breaking changes still (like dropping do this week?), but am curious to know if I'm using sound idiomatics here. I've implemented two versions of the change-making algorithm, one naive and one that looks 'better' in my opinion.
This is for 0.9. Both snippets compile and yield identical results in a couple assert!'s
fn count_change_naive(cents: int, coins: &[int]) -> int {
if (cents == 0) {
1
} else if (cents < 0) {
0
} else {
if coins.iter().len() > 0 {
let new_amount: int = cents - coins[0];
let coins_tailed: &[int] = coins.tail();
count_change_naive(cents, coins_tailed) + count_change_naive(new_amount, coins)
} else {
0
}
}
}
That's pretty unwieldy IMO. I tried to implement the following:
fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
match cents {
n if cents == 0 => 1,
n if cents < 0 => 0,
n if coins.iter().len() > 0 => {
let new_amount: int = cents - coins[0];
let coins_tailed: &[int] = coins.tail();
count_change_idiomatic(cents, coins_tailed) + count_change_idiomatic(new_amount, coins)
},
_ => 0
}
}
I get unused variable warnings on account of the n in the match, but I'm uncertain how to avoid this without an ugly if-else pyramid. Can it be done? Am I missing anything significant in the second implementation?
EDIT: have cleaned up some to meet some of the suggestions, but left intact for comparision
To no get the warnings for the variable you have no use for, you just don't use it:
fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
match cents {
_ if cents == 0 => 1,
_ if cents < 0 => 0,
_ if coins.iter().len() > 0 => {
let new_amount: int = cents - coins[0];
let coins_tailed: &[int] = coins.tail();
count_change_idiomatic(cents, coins_tailed) + count_change_idiomatic(new_amount, coins)
},
_ => 0
}
}
You can use pattern matching on vectors to avoid the length-taking, indexing and tailing:
fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
match (cents, coins) {
(0, _) => 1,
_ if cents < 0 => 0,
(_, [first, .. coins_tailed]) => {
let new_amount = cents - first;
count_change_idiomatic(cents, coins_tailed) +
count_change_idiomatic(new_amount, coins)
}
_ => 0
}
}
The .. part of the pattern matches the rest of the vector (in this case, everything but the first element).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With