-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path31 - Coin sums.R
58 lines (49 loc) · 1.89 KB
/
31 - Coin sums.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
denom <- c(1L, 2L, 5L, 10, 20L, 50L, 100L, 200L)
target <- 200L
# Given a target and a vector of denominations, fix the
# number of coins, say n, of a particular denomination, say d,
# and find the number of ways in which the reduced target of
# `target - (n * d)` can be made from the vector of denominations
# excluding d. Summing the number of ways over n = 1 to floor(target / d)
# yields the desired answer.
# This solution does not use memoization which would of course be faster.
# See the problem solution in the pdf file for an explanation of this.
numWays <- function(denom, target) {
if (target == 0L) {
return(1L)
} else if (length(denom) == 1L) {
return(1L)
} else {
denomMax <- max(denom)
nMax <- floor(target / denomMax)
targets <- target - denomMax * (0:nMax)
out <- mapply(
FUN = numWays,
MoreArgs = list(denom = denom[-which(denom == denomMax)]),
target = targets
)
return(sum(out))
}
}
numWays(denom, target)
# c++ implementation of memoization. Included for comparison sake.
# See how much faster (~ 11,500 times faster)!
library(Rcpp)
cppFunction('int NWays(NumericVector coinSizes, int target){
NumericVector ways(target + 1);
ways[0] = 1;
for (int i = 0; i < coinSizes.size(); i++) {
for (int j = coinSizes[i]; j <= target; j++) {
ways[j] += ways[j - coinSizes[i]];
}
}
return(ways[target]);
}')
NWays(denom, target)
identical(numWays(denom, target), NWays(denom, target))
library(microbenchmark)
microbenchmark(numWays(denom, target), NWays(denom, target))
# Unit: microseconds
# expr min lq mean median uq max neval
# numWays(denom, target) 95453.583 98382.223 100403.9116 99197.014 100298.951 133979.307 100
# NWays(denom, target) 2.276 2.844 6.7333 8.676 9.956 24.748 100