I'm trying to print the Fibonacci Sequence less than 1000 using while loop in R.
So far,
fib <- c(1,1)
counter <-3
while (fib[counter-1]<1000){
fib[counter]<- fib[counter-2]+fib[counter-1]
counter = counter+1
}
fib
I have this code. Only the first two numbers are given: 1,1. This is printing:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
How do I fix my code to print only less than 1000?
Instead of checking the value of the last element wrt 1000, for the expected output you should be checking the sum of the last two elements as so.
fib <- c(1,1)
counter <-3
while (fib[counter-2]+fib[counter - 1]<1000){
fib[counter]<- fib[counter-2]+fib[counter-1]
counter = counter+1
}
fib
The issue with your approach is when the condition (fib[counter-1]<1000) in while loop is FALSE you have already added the number in fib which is greater than 1000.
You could return fib[-length(fib)] to remove the last number or check the number before inserting the number in fib.
fib <- c(1,1)
counter <-3
while (TRUE){
temp <- fib[counter-2] + fib[counter-1]
if(temp < 1000)
fib[counter] <- temp
else
break
counter = counter+1
}
fib
#[1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
You could change the while condition to sum the last 2 answers instead of just the last one:
fib <- c(1,1)
counter <-3
while (sum(fib[counter - 1:2]) < 1000){
fib[counter]<- fib[counter-2]+fib[counter-1]
counter = counter+1
}
fib
#> [1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
Or just get rid of counter completely:
fib <- c(1,1)
while (sum(fib[length(fib) - 0:1]) < 1000) fib <- c(fib, sum(fib[length(fib) - 0:1]))
fib
#> [1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
Related
I have a vector made of 10 random integers like this:
a <- c(400,1,1,1,1,1,1,1,1,13)
and I have a random integer:
n <- 100
My goal is to divide n so that the components of a have the smallest differences between them. The desired output in this case is c(400,14,14,14,14,13,13,13,13,13) (13+13+13+13+12+12+12+12 = 100)
My approach was to use a recursive function:
dis <- function(n,a){
a[which.min(a)] <- a[which.min(a)] + 1
n <- n -1
if(!n){
return(a)
}
dis(n,a)
}
dis(100, c(400,1,1,1,1,1,1,1,1,13))
But I found problems when n is larger, e.g. when n is 1000 I get this message
Error: C stack usage 7969684 is too close to the m
I'm not sure if there is something to avoid recursion, maybe an arithmetic solution, or another approach.
Why not do it as a while loop rather than using deeply nested recursion?
dis <- function(n,a) {
while(n > 0)
{
a[which.min(a)] <- a[which.min(a)] + 1
n <- n - 1
}
a
}
dis(100, c(400,1,1,1,1,1,1,1,1,13))
#> [1] 400 14 14 14 14 13 13 13 13 13
dis(10000, c(400,1,1,1,1,1,1,1,1,13))
#> [1] 1043 1042 1042 1042 1042 1042 1042 1042 1042 1042
You need some minor modification over your recursive function, e.g.,
dis <- function(n, a) {
if (!n) {
return(a)
} else {
a[which.min(a)] <- a[which.min(a)] + 1
dis(n-1, a)
}
}
Example
> dis(100,a)
[1] 400 14 14 14 14 13 13 13 13 13
> dis(1000,a)
[1] 400 114 114 114 114 113 113 113 113 113
I have a Df like this:
x y z
<dbl> <dbl> <dbl>
1 408001.9 343 0
2 407919.2 343 0
3 407839.6 343 0
4 407761.2 343 0
5 407681.7 343 0
6 407599.0 343 0
7 407511.0 343 0
8 407420.5 343 0
9 407331.0 343 0
10 407242.0 343 0
11 407152.7 343 0
12 407062.5 343 0
13 406970.7 343 0
14 406876.6 342 0
15 406777.1 342 0
16 406671.0 342 0
17 406560.9 342 0
18 406449.4 342 0
19 406339.0 342 0
20 406232.5 342 0
... ... ... ...
with x decreasing.
And a vector like
vec=(a1, a2, a3, a4, a5, a6, ...)
with a1< a2< a3< a4...
Now I want to divide df$x by vec[1], what will give the same result (rounded) as for df$y.
But now, when the value in df$z drops by one to 342, I want to divide the value in df$x by vec[2] from then on, to get the new df$z values.
From here the result will be different from df$y, as for df$y the number to divide with is allways vec[1]and will not change
Every time the value I get for df$z drops by one, the next values for df$z shal be calculated with the corresponding vec[i] where i is the number of drops+1 so far
In the end I want a vector df$z, where the values are df$x / vec[i], where vec [i] depends on, what the last number of df$z is.
reproducible example:
test <- data.frame(x = sort((seq(500, 600, 2)), decreasing = T)
)
vec <- seq(10, 10.9, 0.03)
for(i in 1:31){
test[i+1] <- round(test$x/vec[i])
}
This will give you a df with one col for every value of vec, that test$x got divided by.
Now, in the end, my vector shall contain the values of col2 until the value in col2 drops from 60 to 59. Afterwards I want the values from col3 until the value in col3 drops below 59 to 58. Then I want the values from col4 and so on.
How can I achive this with any data(like mine above, which is not linear ditributed as this example.)
I tried some for and while loops, but none worked. I didn't even get close to what I want.
I think my problem is that I dont know how to make the condition depenent on a value(the value of df$z at point i), that I want to calculate in the same operation. I want to calculate the value of df$z[i] with the value of vec[t], that has been used so far. But if the value of df$z drops by one at a certain observation[i], the value of vec[t+1] shall be used for the division from then on.
Thanks for your help.
I hope I've understood what you are asking. This might be it...
test <- data.frame(x = sort((seq(500, 600, 2)), decreasing = T)
vec <- seq(10, 10.9, 0.03)
#this function determines the index of `vec` to use
xcol<-function(v){
x<-rep(NA,length(v))
x[1] <- 1
for(i in 2:length(v)){
x[i] <- x[i-1]
if(round(v[i]/vec[x[i]])<round(v[i-1]/vec[x[i]])){
x[i] <- x[i]+1
}
}
return(x)
}
test$xcol <- xcol(test$x)
test$z <- round(test$x/vec[test$xcol])
test
x xcol z
1 600 1 60
2 598 1 60
3 596 1 60
4 594 2 59
5 592 2 59
6 590 2 59
7 588 2 59
8 586 3 58
9 584 3 58
10 582 3 58
11 580 3 58
12 578 4 57
...
This question already has answers here:
R: How to use ifelse statement for a vector of characters
(2 answers)
Closed 6 years ago.
My friend gave me a brain teaser that I wanted to try on R.
Imagine 100 coins in a row, with heads facing up for all coins. Now every 2nd coin is flipped (thus becoming tails). Then every 3rd coin is flipped. How many coins are now showing heads?
To create the vector, I started with:
flips <- rep('h', 100)
levels(flips) <- c("h", "t")
Not sure how to proceed from here. Any help would be appreciated.
Try this:
coins <- rep(1, 100) # 1 = Head, 0 = Tail
n = 3 # run till the time when you flip every 3rd coin
invisible(sapply(2:n function(i) {indices <- seq(i, 100, i); coins[indices] <<- (coins[indices] + 1) %% 2}) )
which(coins == 1)
# [1] 1 5 6 7 11 12 13 17 18 19 23 24 25 29 30 31 35 36 37 41 42 43 47 48 49 53 54 55 59 60 61 65 66 67 71 72 73 77 78 79 83 84 85 89 90 91 95 96 97
sum(coins==1)
#[1] 49
If you run till n = 100, only the coins at the positions which are perfect squares will be showing heads.
coins <- rep(1, 100) # 1 = Head, 0 = Tail
n <- 100
invisible(sapply(2:n, function(i) {indices <- seq(i, 100, i); coins[indices] <<- (coins[indices] + 1) %% 2}) )
which(coins == 1)
# [1] 1 4 9 16 25 36 49 64 81 100
sum(coins==1)
# [1] 10
I want to calculate number of items waiting or queued over. Let's say, I have fixed capacity of 102 item/hour and different incoming items for 9 hours.
as data table:
dt<-data.table(hour = c(1,2,3,4,5,6,7,8,9),
incoming = c(78,102,115,117,105,99,91,80,71),
capacity = rep(102,9))
I want to calculate queued items in each period.
In 1 and 2 capacity is enough and queue is 0.
In 3, 13 items are queued
In 4, 15+13 backlogged items are queued.
In 6, there were 31 backlogged items and 3 items are deducted so 28 were queued.
I have tried several options but could not figure out how to calculate.
Result should be:
Explicit looping in R won't get you far, and I don't see a vectorized solution for this, but this is trivial to solve using Rcpp:
library(Rcpp)
cppFunction("NumericVector queue(NumericVector x) {
NumericVector res(x.size());
res[0] = std::max<double>(0, x[0]);
for (int i = 1, size = x.size(); i < size; ++i) {
res[i] = std::max<double>(0, res[i-1] + x[i]);
}
return res;
}")
dt[, queued := queue(incoming - capacity)][]
# hour incoming capacity queued
#1: 1 78 102 0
#2: 2 102 102 0
#3: 3 115 102 13
#4: 4 117 102 28
#5: 5 105 102 31
#6: 6 99 102 28
#7: 7 91 102 17
#8: 8 80 102 0
#9: 9 71 102 0
I'd create a separate function to get queued number like #sebastian-c did, but with #R.S. 's logic. Like this
get_queue <- function(x){
n <- length(x)
y <- c(max(0, x[[1]]), rep(0, n - 1))
for(i in 2:n){
y[i] <- max(0, y[i - 1] + x[i])
}
y
}
And then
dt[,incoming_capacity := incoming - capacity]
dt[,queued := get_queue(incoming_capacity)]
Another alternative:
require(data.table)
dt<-data.table(hour = c(1,2,3,4,5,6,7,8,9),
incoming = c(78,102,115,117,105,99,91,80,71),
capacity = rep(102,9))
dt$incoming_capactity<- dt$incoming-dt$capacity
dt$carriedover<- 0
dt$carriedover[1]<- max(0,dt$incoming_capactity[1]) #added
for( i in 2:length(dt$carriedover)) {
dt$carriedover[i]<- max(0,dt$incoming_capactity[i] + dt$carriedover[i-1])
}
dt
I have a vector and I need to sum every n numbers and return the results. This is the way I plan on doing it currently. Any better way to do this?
v = 1:100
n = 10
sidx = seq.int(from=1, to=length(v), by=n)
eidx = c((sidx-1)[2:length(sidx)], length(v))
thesum = sapply(1:length(sidx), function(i) sum(v[sidx[i]:eidx[i]]))
This gives:
thesum
[1] 55 155 255 355 455 555 655 755 855 955
unname(tapply(v, (seq_along(v)-1) %/% n, sum))
# [1] 55 155 255 355 455 555 655 755 855 955
UPDATE:
If you want to sum every n consecutive numbers use colSums
If you want to sum every nth number use rowSums
as per Josh's comment, this will only work if n divides length(v) nicely.
rowSums(matrix(v, nrow=n))
[1] 460 470 480 490 500 510 520 530 540 550
colSums(matrix(v, nrow=n))
[1] 55 155 255 355 455 555 655 755 855 955
Update
The olde version don't work. Here a ne awnser that use rep to create the grouping factor. No need to use cut:
n <- 5
vv <- sample(1:1000,100)
seqs <- seq_along(vv)
tapply(vv,rep(seqs,each=n)[seqs],FUN=sum)
You can use tapply
tapply(1:100,cut(1:100,10),FUN=sum)
or to get a list
by(1:100,cut(1:100,10),FUN=sum)
EDIT
In case you have 1:92, you can replace your cut by this :
cut(1:92,seq(1,92,10),include.lowest=T)
One way is to convert your vector to a matric then take the column sums:
colSums(matrix(v, nrow=n))
[1] 55 155 255 355 455 555 655 755 855 955
Just be careful: this implicitly assumes that your input vector can in fact be reshaped to a matrix. If it can't, R will recycle elements of your vector to complete the matrix.
v <- 1:100
n <- 10
cutpoints <- seq( 1 , length( v ) , by = n )
categories <- findInterval( 1:length( v ) , cutpoints )
tapply( v , categories , sum )
I will add one more way of doing it without any function from apply family
v <- 1:100
n <- 10
diff(c(0, cumsum(v)[slice.index(v, 1)%%n == 0]))
## [1] 55 155 255 355 455 555 655 755 855 955
Here are some of the main variants offered so far
f0 <- function(v, n) {
sidx = seq.int(from=1, to=length(v), by=n)
eidx = c((sidx-1)[2:length(sidx)], length(v))
sapply(1:length(sidx), function(i) sum(v[sidx[i]:eidx[i]]))
}
f1 <- function(v, n, na.rm=TRUE) { # 'tapply'
unname(tapply(v, (seq_along(v)-1) %/% n, sum, na.rm=na.rm))
}
f2 <- function(v, n, na.rm=TRUE) { # 'matrix'
nv <- length(v)
if (nv %% n)
v[ceiling(nv / n) * n] <- NA
colSums(matrix(v, n), na.rm=na.rm)
}
f3 <- function(v, n) { # 'cumsum'
nv = length(v)
i <- c(seq_len(nv %/% n) * n, if (nv %% n) nv else NULL)
diff(c(0L, cumsum(v)[i]))
}
Basic test cases might be
v = list(1:4, 1:5, c(NA, 2:4), integer())
n = 2
f0 fails with the final test, but this could probably be fixed
> f0(integer(), n)
Error in sidx[i]:eidx[i] : NA/NaN argument
The cumsum approach f3 is subject to rounding error, and the presence of an NA early in v 'poisons' later results
> f3(c(NA, 2:4), n)
[1] NA NA
In terms of performance, the original solution is not bad
> library(rbenchmark)
> cols <- c("test", "elapsed", "relative")
> v <- 1:100; n <- 10
> benchmark(f0(v, n), f1(v, n), f2(v, n), f3(v, n),
+ columns=cols)
test elapsed relative
1 f0(v, n) 0.012 3.00
2 f1(v, n) 0.065 16.25
3 f2(v, n) 0.004 1.00
4 f3(v, n) 0.004 1.00
but the matrix solution f2 seems to be both fast and flexible (e.g., adjusting the handling of that trailing chunk of fewer than n elements)
> v <- runif(1e6); n <- 10
> benchmark(f0(v, n), f2(v, n), f3(v, n), columns=cols, replications=10)
test elapsed relative
1 f0(v, n) 5.804 34.141
2 f2(v, n) 0.170 1.000
3 f3(v, n) 0.251 1.476
One way is to use rollapply from zoo:
rollapply(v, width=n, FUN=sum, by=n)
# [1] 55 155 255 355 455 555 655 755 855 955
And in case length(v) is not a multiple of n:
v <- 1:92
rollapply(v, width=n, FUN=sum, by=n, partial=T, align="left")
# [1] 55 155 255 355 455 555 655 755 855 183
A little late to the party, but I don't see a rowsum() answer yet. rowsum() is proven more efficient than tapply() and I think it would also be very efficient relative to a few of the other responses as well.
rowsum(v, rep(seq_len(length(v)/n), each=n))[,1]
# 1 2 3 4 5 6 7 8 9 10
# 55 155 255 355 455 555 655 755 855 955
Using #Josh O'Brien's grouping technique would likely improve efficiency even more.
rowsum(v, (seq_along(v)-1) %/% n)[,1]
# 0 1 2 3 4 5 6 7 8 9
# 55 155 255 355 455 555 655 755 855 955
Simply wrap in unname() to drop the group names.