In a coin-change
type of problem, I'm trying to refactor the recursive function into iterative. Given a set of coin_types
, the function coinr
finds the minimum number of coins to pay a given amount, sum
, recursively.
# Any coin_type could be used more than once or it may not be used at all
sub coinr ($sum, @coin_types) { # As this is for learning basic programming
my $result = $sum; # No memoization (dynamic programming) is used
if $sum == @coin_types.any { return 1 }
else { for @coin_types.grep(* <= $sum) -> $coin_type {
my $current = 1 + coinr($sum - $coin_type, @coin_types);
$result = $current if $current < $result; } }
$result;
}
say &coinr(@*ARGS[0], split(' ', @*ARGS[1]));
# calling with
# 8 "1 4 5" gives 2 (4+4)
# 14 "1 3 5" gives 4 (1+3+5+5), etc.
This function was originally written in Python and I converted it to Raku. Here is my take on the iterative version, which is very incomplete:
# Iterative
sub coini ($sum, @coin_types) {
my $result = 1;
for @coin_types -> $coin_type {
for 1 ... $sum -> $i {
if $sum-$coin_type == @coin_types.any { $result += 1 } #?
else { # ???
}
}
}
}
Can somebody help me on this?
Initialize the accumulator before the while-loop. Use the negation of the base-case condition as the loop's condition. Use the recursive function's body (except the recursive call) as the body of the while-loop. After the loop, apply the base-case update of the accumulator and return its value.
The Coin Change Problem is considered by many to be essential to understanding the paradigm of programming known as Dynamic Programming. The two often are always paired together because the coin change problem encompass the concepts of dynamic programming.
Many professional developers probably already know how to replace recursive functions to avoid stack-overflow problems in advance by replacing with iterative function or using stack (heap stack) and while-loop (recursive simulation function).
Picture this, you are given an array of coins with varying denominations and an integer sum representing the total amount of money. You must return the fewest coins required to make up that sum; if that sum cannot be constructed, return -1.
There are a number of different ways to implement this iteratively (There's More Than One Way To Do It, as we like to say!) Here's one approach:
sub coini($sum is copy, @coin-types) {
gather while $sum > 0 { take $sum -= @coin-types.grep(* ≤ $sum).max } .elems
}
This decreases the (now mutable) $sum
by the largest coin possible, and keeps track of the current $sum
in a list. Then, since we only want the number of coins, it returns the length of that list.
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