Lighten a fibonacci while loop - r

This problem has given headache for me and I just can't figure it out. The problem is to write R function which will return every Fibonacci number equal to or less than n.
So far I've tried to make while loop.
vast <- function(n) {
if (n==1) return(1)
x <- c(1,1)
while (length(x)-1 < n) {
pos <- length(x)
new <- x[pos-1] + x[pos]
x <- c(x,new)
}
x<-x[x <= n]
return(x)
}
It works like charm except when I try to return the work. At that point the R program starts infinite calculation and the course package jams.
The solution can be also written so that one makes assumption that n is an Fibonacci number. Is there any way to lighten this loop e.g. with break or next statements or would it be easier to approach the problem from different angle?

The code provides correct output as is, but it's very slow for large numbers. For instance, on my machine, vast(100000) (with only 25 elements in the result) takes over 10 seconds to run, and slows down exponentially after that.
The reason it's slow is that your while condition is testing if the vector that has n-1 elements, rather than the bare requirements of a vector whose last / largest vector is <= n. For the case of vast(100000), you are creating a 100,000-element vector, when the answer ultimately only needs the first 25 elements.
This code works instantaneously past n = 10^5000, whereas the original function gums up in the 100k's on my machine. The only change is that it is now checking to see if the last number in the vector is larger than n, not checking if the vector has n elements.
vast2 <- function(n) {
if (n==1) return(1)
x <- c(1,1)
# while (length(x)-1 < n) { # OLD
while (max(x) < n) { # NEW
pos <- length(x)
new <- x[pos-1] + x[pos]
x <- c(x,new)
}
x<-x[x <= n]
return(x)
}

Related

Problem with checking logical within for loop

Inspired by the leetcode challenge for two sum, I wanted to solve it in R. But while trying to solve it by brute-force I run in to an issue with my for loop.
So the basic idea is that given a vector of integers, which two integers in the vector, sums up to a set target integer.
First I create 10000 integers:
set.seed(1234)
n_numbers <- 10000
nums <- sample(-10^4:10^4, n_numbers, replace = FALSE)
The I do a for loop within a for loop to check every single element against eachother.
# ensure that it is actually solvable
target <- nums[11] + nums[111]
test <- 0
for (i in 1:(length(nums)-1)) {
for (j in 1:(length(nums)-1)) {
j <- j + 1
test <- nums[i] + nums[j]
if (test == target) {
print(i)
print(j)
break
}
}
}
My problem is that it starts wildly printing numbers before ever getting to the right condition of test == target. And I cannot seem to figure out why.
I think there are several issues with your code:
First, you don't have to increase your j manually, you can do this within the for-statement. So if you really want to increase your j by 1 in every step you can just write:
for (j in 2:(length(nums)))
Second, you are breaking only the inner-loop of the for-loop. Look here Breaking out of nested loops in R for further information on that.
Third, there are several entries in nums that gave the "right" result target. Therefore, your if-condition works well and prints all combination of nums[i]+nums[j] that are equal to target.

Finding the value of infinite sums in r

I'm very new to r and programming so please stay with me :)
I am trying to use iterations to find the value of infinite iterations to the 4th decimal place. I.e. where the 4th decimal does not change. so 1.4223, where 3 does not change anymore so the result to 3 decimal place is 1.422.
The link above shows an example of a similar problem that I am faced with. My question is how do I create a for-loop that goes to infinity and find the value where the 4th decimal point stops changing?
I have tried using while loops but I am not sure how to stop it from just looping forever. I need some if statement like below:
result <- 0
i <- 1
d <- 1e-4
while(TRUE)
{
result <- result + (1/(i^2))
if(abs(result) < d)
{
break
}
i <- i + 1
}
result
Here's an example: to do the infinite loop, use while(TRUE) {}, and as you suggested use an if clause and break to stop when necessary.
## example equation shown
## fun <- function(x,n) {
## (x-1)^(2*n)/(n*(2*n-1))
## }
## do it for f(x)=1/x^2 instead
## doesn't have any x-dependence, but leave it in anyway
fun <- function(x,n) {
1/n^2
}
n <- 1
## x <- 0.6
tol <- 1e-4
ans <- 0
while (TRUE) {
next_term <- fun(x,n)
ans <- ans + next_term
if (abs(next_term)<tol) break
n <- n+1
}
When run this gives ans=1.635082, n=101.
R also has a rarely used repeat { } keyword, but while(TRUE) will probably be clearer to readers
there are more efficient ways to do this (i.e. calculating the numerator by multiplying it by (x-1)^2 each time)
it's generally a good idea to test for a maximum number of iterations as well so that you don't set up a truly infinite loop if your series doesn't converge or if you have a bug in your code
I haven't solved your exact problem (chose a smaller value of tol), but you should be able to adjust this to get an answer
as discussed in the answer to your previous question, this isn't guaranteed, but should generally be OK; you can check (I haven't) to be sure that the particular series you want to evaluate has well-behaved convergence

Which loop to use, R language?

We have to create function(K) that returns vector which has all items smaller than or equal to K from fibonacci sequence. We can assume K is fibonacci item. For example if K is 3 the function would return vector (1,1,2,3).
In general, a for loop is used when you know how many iterations you need to do, and a while loop is used when you want to keep going until a condition is met.
For this case, it sounds like you get an input K and you want to keep going until you find a Fibonacci term > K, so use a while loop.
ans <- function(n) {
x <- c(1,1)
while (length(x) <= n) {
position <- length(x)
new <- x[position] + x[position-1]
x <- c(x,new)
}
return(x[x<=n])
}
`
Tried many different loops, and this is closest I get. It works with every other number but ans(3) gives 1,1,2 even though it should give 1,1,2,3. Couldn't see what is wrong with this.

get last repeat loop's result as vector in R

i want to create a vector of numbers (following weibulldistribution (shape=c,scale=b), the length is uncertain at the beginning of creating this vector (length depending on g)! using a function (c,b,g) with a repeat loop brings the result on screen, but not into the vector. So I need the last loop's result in a vector, but don't know how
t<-NULL
z<-NULL
p<-NULL
neededvector<-function(c,b,g) {
p<-repeat{
t<-rweibull(1,c,b)
append(z,t)
z<-print(append(z,t))
if(sum(((z*0.01)^2*pi)/4)>g)
break
}
}
Normally it's a bad idea to grow an object in a loop, since that's slow in R. If we knew your resulting vector were less than 1000, we could use cumsum to know when we should stop it:
neededvector <- function(c,b,g) {
z <- rweibull(1000, c, b)
z[((cumsum(z) * 0.01) ^ 2 * pi) <= g]
}
This solution won't work for you if the resulting vector should have been longer than 1000. But you can make it work, and be a lot faster than 1-at-a-time, by doing it in chunks.
neededvector <- function(c,b,g) {
z <- c()
while (TRUE) {
# generate values 1000 at a time
z <- c(z, rweibull(1000, c, b))
threshold <- ((cumsum(z) * 0.01) ^ 2 * pi) <= g
# check if this would include all elements of z.
# if not, return it.
if (sum(threshold) < length(z)) {
return(z[threshold])
}
}
}
Generally, rather than 1000, set that value to some length greater than you generally expect the Weibull to be. (If your vector ends up being length 100,000, this method will have poor performance unless you set it to create it in chunks closer to that length).

Logical comparison of two vectors with binary (0/1) result

For an assignment I had to create a random vector theta, a vector p containing for each element of theta the associated probability, and another random vector u. No problems thus far, but I'm stuck with the next instruction which I report below:
Generate a vector r1 that has a 1 in position i if pi ≥ ui and 0 if pi < ui. The
vector r1 is a Rasch item given the latent variable theta.
theta=rnorm(1000,0,1)
p=(exp(theta-1))/(1+exp(theta-1))
u=runif(1000,0,1)
I tried the following code, but it doesn't work.
r1<-for(i in 1:1000){
if(p[i]<u[i]){
return("0")
} else {
return("1")}
}
You can use the ifelse function:
r1 <- ifelse(p >= u, 1, 0)
Or you can simply convert the logical comparison into a numeric vector, which turns TRUE into 1 and FALSE into 0:
r1 <- as.numeric(p >= u)
#DavidRobinson gave a nice working solution, but let's look at why your attempt didn't work:
r1<-for(i in 1:1000){
if(p[i]<u[i]){
return("0")
} else {
return("1")}
}
We've got a few problems, biggest of which is that you're confusing for loops with general functions, both by assigning and using return(). return() is used when you are writing your own function, with function() <- .... Inside a for loop it isn't needed. A for loop just runs the code inside it a certain number of times, it can't return something like a function.
You do need a way to store your results. This is best done by pre-allocating a results vector, and then filling it inside the for loop.
r1 <- rep(NA, length(p)) # create a vector as long as p
for (i in 1:1000) {
if (p[i] < u[i]) { # compare the ith element of p and u
r1[i] <- 0 # put the answer in the ith element of r1
} else {
r1[i] <- 1
}
}
We could simplify this a bit. Rather than bothering with the if and the else, you could start r1 as all 0's, and then only change it to a 1 if p[i] >= u[i]. Just to be safe I think it's better to make the for statement something like for (i in 1:length(p)), or best yet for (i in seq_along(p)), but the beauty of R is how few for loops are necessary, and #DavidRobinson's vectorized suggestions are far cleaner.

Resources