Уменьшить решение
Вот решение с использованием Reduce
# framework
x0 <- 1
bound <- 900
r <- 1.55
estimate <- round(log(bound, r))
# iterations and filtering
vec <- Reduce(f = function(y,x) round((1+y)*r), x = 1:estimate,
init = x0, accumulate = TRUE)
vec <- vec[vec <= bound]
# result
[1] 1 3 6 11 19 31 50 79 124 194 302 470 730
Примечания
- Как упоминалось в комментариях,чтобы иметь целые числа, нужно использовать
round;floor;ceil;etc.
, я выбрал round
.Но «истинные» значения не являются целыми числами. - Я вычисляю
estimate
, который я использую в Reduce
, чтобы иметь приблизительное представление о размере результата - это, безусловно, можно сделать умнее.
Решение Rcpp
Вот решение с использованием пакета Rcpp
(поэтому функция записана в c++
и «преобразована» в R
функция).Здесь функция использует цикл while
, так что решение @ RonakShah, написанное в c++
.
C ++ файле
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector nateCpp(int init, int bound) {
int current = init;
int outLength = 1;
NumericVector out(outLength);
out[0] = current;
while ((int) round((1+current)*1.55) <= bound) {
current = (int) round((1+current)*1.55);
out.insert(out.length(), current);
}
return out;
}
R файла
# sourcing the file to have the function
Rcpp::sourceCpp('MyCppFile.cpp')
nateCpp(1,900)
[1] 1 3 6 11 19 31 50 79 124 194 302 470 730
Сравнительный анализ
Вот контрольные цифры:
Unit: microseconds
expr min lq mean median uq max neval cld
ronak(1, 10^5) 34.644 38.656 56.628269 40.844 52.878 25973.41 1e+05 c
nate(1, 10^5) 36.103 40.844 57.294825 43.032 53.243 26714.79 1e+05 c
darren(1, 10^5) 29.903 33.550 46.599951 35.374 41.209 12248.98 1e+05 b
nateCpp(1, 10^5) 2.553 4.012 6.578349 4.741 5.471 10963.14 1e+05 a
Неудивительно, что решение, включающее c++
, безусловно, является самым быстрым.Для решений только R
рекурсия
- @ DarrenTsai является самой быстрой (рекурсии следует использовать с осторожностью, хотя могут возникнуть проблемы, такие как слишком много вложенных выражений - в этом случае все должно быть хорошо, так какчисла быстро растут), затем следуют
- @ Ронакшаха и моя функция.
Функции
ronak <- function(x0,stop) {
new_num = 1
num = 1
while(new_num < stop) {
new_num = round((new_num + 1) * 1.55)
num = c(num, new_num)
}
head(num,-1)
}
nate <- function(x0, bound) {
r <- 1.55
estimate <- round(log(bound, r))
vec <- Reduce(f = function(y,x) round((1+y)*r), x = 1:estimate, init = x0, accumulate = TRUE)
vec <- vec[vec <= bound]
vec
}
darren <- function(start, end){
n <- length(start) ; last <- start[n]
if(last >= end)
return(start[-n])
else
darren(c(start, round((last + 1) * 1.55)), end)
}