4

I need to automate the process of getting the next number(s) in the given sequence.

Can we make a function which takes two inputs

  1. a vector of numbers(3,7,13,21 e.g.)
  2. how many next numbers

    seqNext <- function(sequ, next) {
    ..
    }
    
    seqNext( c(3,7,13,21), 3) 
    # 31 43 57
    seqNext( c(37,26,17,10), 1)
    # 5 
    
Navin Manaswi
  • 964
  • 7
  • 19

2 Answers2

7

By the power of maths!

x1 <- c(3,7,13,21)
dat <- data.frame(x=seq_along(x1), y=x1)

predict(lm(y ~ poly(x, 2), data=dat), newdata=list(x=5:15))
#  1   2   3   4   5   6   7   8   9  10  11 
# 31  43  57  73  91 111 133 157 183 211 241 

When dealing with successive differences that change their sign, the pattern of output values ends up switching from decreasing to increasing:

x2 <- c(37,26,17,10)

dat <- data.frame(x=seq_along(x2), y=x2)
predict(lm(y ~ poly(x,2), data=dat), newdata=list(x=1:10))

# 1      2      3      4      5      6      7      8      9     10 
#37     26     17     10      5      2      1      2      5     10
   -(11)   -(9)   -(7)    -(5)   -(3)   -(1)  -(-1)  -(-3) -(-5)
        -2     -2      -2     -2     -2    -2     -2     -2 

As a function:

seqNext <- function(x,n) {
  L <- length(x)
  dat <- data.frame(x=seq_along(x), y=x)
  unname(
    predict(lm(y ~ poly(x, 2), data=dat), newdata=list(x=seq(L+1,L+n)))
  )
}

seqNext(x1,5)
#[1] 31 43 57 73 91
seqNext(x2,5)
#[1] 5 2 1 2 5

This is also easily extensible to circumstances where the pattern might be n orders deep, e.g.:

x3 <- c(100, 75, 45, 5, -50)
diff(x3)
#[1] -25 -30 -40 -55
diff(diff(x3))
#[1]  -5 -10 -15
diff(diff(diff(x3)))
#[1] -5 -5

seqNext <- function(x,n,degree=2) {
  L <- length(x)
  dat <- data.frame(x=seq_along(x), y=x)
  unname(
    predict(lm(y ~ poly(x, degree), data=dat), newdata=list(x=seq(L+1,L+n)))
  )
}

seqNext(x3,n=5,deg=3)
#[1] -125 -225 -355 -520 -725
thelatemail
  • 91,185
  • 12
  • 128
  • 188
  • 1
    To be more precise, in our answers patterns can be different from Richard's not when sequences cross zero but when successive differences change their sign, i.e. when they are decreasing in absolute terms in `x`. – Julius Vainora Nov 27 '15 at 00:34
  • @RichardScriven - nothing too controversial. The decreasing pattern will continue until the slope reverses `seqNext(c(10,2,-4), 5)` as per the 2nd-order polynomial curve (which is U shaped), e.g.: `x <- seq(-4,4,0.5); plot(x,poly(x,2)[,2],type="l")` – thelatemail Nov 27 '15 at 01:45
  • I would say that the extension to `n` orders should be obvious. It's what makes this a great answer. – Matthew Lundberg Nov 27 '15 at 03:44
  • @MatthewLundberg - thanks. For a dullard like me, nothing is obvious when it comes to these sorts of calculations! The edit is mainly so I can come back and reference this post myself! – thelatemail Nov 27 '15 at 03:49
2
seqNext <- function(x, n) {
  k <- length(x);  d <- diff(x[(k - 2):k])
  x[k] + 1:n * d[2] + cumsum(1:n) * diff(d[1:2])
}

seqNext(c(3,7,13,21),3) 
# [1] 31 43 57
seqNext(c(37,26,17,10),1)
# [1] 5
seqNext(c(137,126,117,110),10)
# [1] 105 102 101 102 105 110 117 126 137 150
seqNext(c(105,110,113,114),5)
# [1] 113 110 105  98  89
Julius Vainora
  • 47,421
  • 9
  • 90
  • 102