Создать вектор с увеличением последовательности в соответствии с уравнением, примененным к последнему сгенерированному числу - PullRequest
0 голосов
/ 29 декабря 2018

Я хочу получить вектор, начинающийся с 1 и заканчивающийся на 900, где каждое увеличение основано на взятии последнего сгенерированного числа и добавлении 1, а затем умножении его на 1,55;а затем округлите его до ближайшего числа.

То есть последовательность должна быть:

First number:  1 (i.e., start at 1)

Second number: 3 (i.e., (1+1)*1.55)

Third number:  6 (i.e., (3+1)*1.55)

Я пробовал:

 x0=1
 seq(x0, 600, (+1*1.55))

Ответы [ 3 ]

0 голосов
/ 29 декабря 2018

Уменьшить решение

Вот решение с использованием 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)
}
0 голосов
/ 29 декабря 2018

A рекурсивное решение:

FUN <- function(start, end){
  n <- length(start) ; last <- start[n]
  if(last >= end)
    return(start[-n])
  else
    FUN(c(start, round((last + 1) * 1.55)), end)
}

FUN(1, 900)
# [1]   1   3   6  11  19  31  50  79 124 194 302 470 730
0 голосов
/ 29 декабря 2018

Не очень умный подход с использованием while loop

stop = 900
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)
# [1]   1   3   6  11  19  31  50  79 124 194 302 470 730
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...