Using While Function in a Fibonacci Sequence in R - r

I've written down a fibonacci code but I cant quite get the While function. Lets say I've made the sequence go up to 34 calculations, but I only want the results that are 4,000,000 or less. Here is the code that I have (bottom one is just to get prime numbers).
#rm (list=ls())
len <- 34
fibvals <- numeric(len)
fibvals[1] <- 1
fibvals[2] <- 1
for (i in 3:len) {
fibvals[i] <- fibvals[i-1]+fibvals[i-2]
}
fib.mat <- as.matrix(fibvals)
fib.mat[lapply(fib.mat, "%%", 2) == 0]
sum (fib.mat)
···········
Ive tried using codes such as this which either it goes on an infinite loop or just get an error. Any help would be appreciated, thanks!
while (fibvals < 4000000) {
print(fibvals)
}

It does not loop over the values of fibvals the way you coded it (you pass a vector of TRUE/FALSE values to while). You cold for example use an auxiliary counter variable like this:
counter <- 1
while (fibvals[counter] < 4000000) {
print(fibvals[counter])
counter <- counter + 1
}
This gives the desired result as I understood it.

You can do the following (note this takes around ~45 seconds on my laptop):
# Fibonacci numbers using recursive relation
fib <- function(n) {
val <- n;
if (n > 1) val <- fib(n - 1) + fib(n - 2);
return(val);
}
# Print Fibonacci numbers while < 4,000,0000
n <- 0;
while (fib(n) < 4000000) {
print(fib(n));
n <- n + 1;
}
#[1] 0
#[1] 1
#[1] 1
#[1] 2
#[1] 3
#[1] 5
#[1] 8
#[1] 13
#[1] 21
#[1] 34
#[1] 55
#[1] 89
#[1] 144
#[1] 233
#[1] 377
#[1] 610
#[1] 987
#[1] 1597
#[1] 2584
#[1] 4181
#[1] 6765
#[1] 10946
#[1] 17711
#[1] 28657
#[1] 46368
#[1] 75025
#[1] 121393
#[1] 196418
#[1] 317811
#[1] 514229
#[1] 832040
#[1] 1346269
#[1] 2178309
#[1] 3524578

you can use the explicit form of the Fibonacci sequence
fibonacciR <- function(n){(((1+sqrt(5))/2)^(n)-(1-((1+sqrt(5))/2))^(n))/sqrt(5)}
#fibonacciR(0:30)
result<-n<-0
while(fibonacciR(n)<4000000){
result<-c(result,fibonacciR(n));
n<-n+1}
result[-1]
[1] 0 1 1 2 3 5 8 13 21 34 55 89 144
[14] 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025
[27] 121393 196418 317811 514229 832040 1346269 2178309 3524578
It's very fast, it takes less than a second on my PC

Related

R: Printing Every 5th Output of a Loop

I am working with the R programming language.
I have this loop:
for (i in 1:100)
{
num_i = as.integer(rnorm(1,100,100))
print(num_i)
}
[1] 44
[1] -3
[1] -55
[1] 127
[1] 149
[1] 83
[1] 151
[1] 52
[1] 120
[1] 102
[1] 132
[1] 352
[1] 96
[1] 208
[1] 268
[1] 156
[1] 51
[1] 23
[1] 27
I only want to print every 5th output of this loop (i.e. 5th output, 10th output, 15th output, etc.):
[1] 83
[1] 132
[1] 156
I had an idea - I could use the concept of "modulo" in such a way, such that only every 5th output is printed. For example:
for (i in 1:100)
{
num_i = as.integer(rnorm(1,100,100))
ifelse(i %% 5 == 0, print(num_i), "" )
}
Have I done this correctly?
Thanks!
There are non-loop ways to do this to get the same output since rnorm can generate more than 1 number.
However, this seems to be a simplified example of what you are doing so in this case, you can continue the for loop using if/else -
for (i in 1:100) {
num_i = as.integer(rnorm(1,100,100))
if(i %% 5 == 0) {
print(num_i)
}
}
This will print nothing when the condition i %% 5 is FALSE. If you want it to print "" you may include the else condition.
Or since we are not using num_i when the condition is not satisfied so in this case we can generate the number only when i %% 5 == 0
for (i in 1:100) {
if(i %% 5 == 0) {
num_i = as.integer(rnorm(1,100,100))
print(num_i)
}
}

How to convert decimal (base 10) numbers to ternary (base 3)

I was wondering if there is a way to convert decimal numbers to ternary, given that there is a function intToBits for converting to binary.
I actually need to convert a character string like
> S0 <- c("Hello Stac")
to base 3. I thought to first convert it to decimal with
> S01 <- utf8ToInt(S0)
> S01
## [1] 72 101 108 108 111 32 83 116 97 99
then convert the result to base 3. I want to obtain something like this:
> S1
## [1] 2200 10202 11000 11010 11022 1012 10002 11022 10121 10200
For practice, I guess you can try to write your own converter function like below
f <- function(x, base = 3) {
q <- c()
while (x) {
q <- c(x %% base, q)
x <- x %/% base
}
# as.numeric(paste0(q, collapse = ""))
sum(q * 10^(rev(seq_along(q) - 1)))
}
or with recursion
f <- function(x, base = 3) {
ifelse(x < base, x, f(x %/% base) * 10 + x %% base)
}
then you can run
> sapply(utf8ToInt(S0),f)
[1] 2200 10202 11000 11000 11010 1012 10002 11022 10121 10200
Nice programming exercise. I have vectorized #ThomasIsCoding's answer to avoid expensive loops over strings and characters within strings. The idea is to loop over digits instead, since Unicode code points do not exceed 21 digits in any base, whereas the total number of characters in a character vector can be orders of magnitude greater.
The function below takes as arguments a character vector x, a base b (from 2 to 10), and a logical flag double. It returns a list res such that res[[i]] is an nchar(x[i])-length vector giving the base-b representation of x[i]. The list elements are double vectors or character vectors depending on double.
utf8ToBase <- function(x, b = 10, double = TRUE) {
## Do some basic checks
stopifnot(is.character(x), !anyNA(x),
is.numeric(b), length(b) == 1L,
b %% 1 == 0, b >= 2, b <= 10)
## Require UTF-8 encoding
x <- enc2utf8(x)
## Operate on concatenation to avoid loop over strings
xx <- paste(x, collapse = "")
ixx <- utf8ToInt(xx)
## Handle trivial case early
if (length(ixx) == 0L) {
el <- if (double) base::double(0L) else character(0L)
res <- rep.int(list(el), length(x))
names(res) <- names(x)
return(res)
}
## Use common field width determined from greatest integer
width <- as.integer(floor(1 + log(max(ixx, 1), base = b)))
res <- rep.int(strrep("0", width), length(ixx))
## Loop over digits
pos <- 1L
pow <- b^(width - 1L)
while (pos <= width) {
quo <- ixx %/% pow
substr(res, pos, pos) <- as.character(quo)
ixx <- ixx - pow * quo
pos <- pos + 1L
pow <- pow %/% b
}
## Discard leading zeros
if (double) {
res <- as.double(res)
if (b == 2 && any(res > 0x1p+53)) {
warning("binary result not guaranteed due to loss of precision")
}
} else {
res <- sub("^0+", "", res)
}
## Return list
res <- split(res, rep.int(gl(length(x), 1L), nchar(x)))
names(res) <- names(x)
res
}
x <- c(foo = "Hello Stack Overflow!", bar = "Hello world!")
utf8ToBase(x, 2)
$foo
[1] 1001000 1100101 1101100 1101100 1101111 100000
[7] 1010011 1110100 1100001 1100011 1101011 100000
[13] 1001111 1110110 1100101 1110010 1100110 1101100
[19] 1101111 1110111 100001
$bar
[1] 1001000 1100101 1101100 1101100 1101111 100000
[7] 1110111 1101111 1110010 1101100 1100100 100001
utf8ToBase(x, 3)
$foo
[1] 2200 10202 11000 11000 11010 1012 10002 11022 10121 10200
[11] 10222 1012 2221 11101 10202 11020 10210 11000 11010 11102
[21] 1020
$bar
[1] 2200 10202 11000 11000 11010 1012 11102 11010 11020 11000
[11] 10201 1020
utf8ToBase(x, 10)
$foo
[1] 72 101 108 108 111 32 83 116 97 99 107 32 79 118 101
[16] 114 102 108 111 119 33
$bar
[1] 72 101 108 108 111 32 119 111 114 108 100 33
Some caveats:
For efficiency, the function concatenates the strings in x rather than looping over them. It throws an error if the concatenation would exceed 2^31-1 bytes, which is the maximum string size allowed by R.
x <- strrep(letters[1:2], 0x1p+30)
log2(sum(nchar(x))) # 31
utf8ToBase(x, 3)
Error in paste(x, collapse = "") : result would exceed 2^31-1 bytes
The largest Unicode code point is 0x10FFFF. The binary representation of this number exceeds 2^53 when interpreted as decimal, so it cannot be stored in a double vector without loss of precision:
x <- sub("^0+", "", paste(rev(as.integer(intToBits(0x10FFFF))), collapse = ""))
x
## [1] "100001111111111111111"
sprintf("%.0f", as.double(x))
## [1] "100001111111111114752"
As a defensive measure, the function warns if 2^53 is exceeded when b = 2 and double = TRUE.
utf8ToBase("\U10FFFF", b = 2, double = TRUE)
[[1]]
[1] 1.000011e+20
Warning message:
In utf8ToBase("\U{10ffff}", b = 2, double = TRUE) :
binary result not guaranteed due to loss of precision
utf8ToBase("\U10FFFF", b = 2, double = FALSE)
[[1]]
[1] "100001111111111111111"
You can use cwhmisc::int2B:
library(cwhmisc)
int2B(utf8ToInt(S0), 3)[[1]] |> as.numeric()
# [1] 2200 10202 11000 11000 11010 1012 10002 11022 10121 10200

Twin primes less than 87 in R

I am trying to list the first 87 twin primes. I'm using the Eratosthenes approach. Here is what I've worked on so far
Eratosthenes <- function(n) {
# Return all prime numbers up to n (based on the sieve of Eratosthenes)
if (n >= 2) {
sieve <- seq(2, n) # initialize sieve
primes <- c() # initialize primes vector
for (i in seq(2, n)) {
if (any(sieve == i)) { # check if i is in the sieve
primes <- c(primes, i) # if so, add i to primes
sieve <- sieve[(sieve %% i) != 0] # remove multiples of i from sieve
}
}
return(primes)
} else {
stop("Input value of n should be at least 2.")
}
}
Era <- c(Eratosthenes(87))
i <- 2:86
for (i in Era){
if (Era[i]+2 == Era[i+1]){
print(c(Era[i], Era[i+1]))
}
}
First thing I dont understand is this error:
Error in if (Era[i] + 2 == Era[i + 1]) { :
missing value where TRUE/FALSE needed
Second thing is in the list there are missing twin primes so for example (29,31)
Within your for loop, i is not index any more but the element in Era. In this case, you can try using (i+2) %in% Era to judge if i+2 is the twin
for (i in Era){
if ((i+2) %in% Era){
print(c(i,i+2))
}
}
which gives
[1] 3 5
[1] 5 7
[1] 11 13
[1] 17 19
[1] 29 31
[1] 41 43
[1] 59 61
[1] 71 73
A simpler way might be using diff, e.g.,
i <- Era[c(diff(Era)==2,FALSE)]
print(cbind(i,j = i+2))
which gives
> print(cbind(i,j = i+2))
i j
[1,] 3 5
[2,] 5 7
[3,] 11 13
[4,] 17 19
[5,] 29 31
[6,] 41 43
[7,] 59 61
[8,] 71 73
Firstly, (23,29) is not twin prime.
Secondly, your answer may be found in here
Edit: I've tried your code, I found that length of Era is 23.
Maybe when running if (Era[i] + 2 == Era[i+1]), it reaches to 24 and causes the problem.
for (i in Era) will set i to 2, then 3, then 5 etc which is not what you intended. Use for (i in seq_len(length(Era) - 1)).
for (i in seq_len(length(Era) - 1)){
if (Era[i] + 2 == Era[i + 1]){
print(c(Era[i], Era[i + 1]))
}
}
#> [1] 3 5
#> [1] 5 7
#> [1] 11 13
#> [1] 17 19
#> [1] 29 31
#> [1] 41 43
#> [1] 59 61
#> [1] 71 73

Fibonacci sequence less than 1000 in R

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

How to remove from a list 'setequally' duplicated elements in R?

Suppose I have some list li in R whose elements are vectors. For instance,
li=list(a=c(2,3,5),b=c(77,119,81),c=c(9,11,13),d=c(5,2,3),e=c(80,45,16),f=c(16,17,19),g=c(13,9,11),h=c(22,13,58))
It can be seen that all objects in li are different as vectors. Therefore,
duplicated(li)
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Also, the command unique(li) will return the same list li. But note that the elements a and d as well as c and g are equal as sets. Namely,
setequal(li$a,li$d)
[1] TRUE
and
setequal(li$c,li$g)
[1] TRUE
Consequently, the element a is duplicated as set by the element d and the element c is duplicated as set by the element g. My question is: How to remove from a list such 'setequally' duplicated elements in R ?
What about:
li[apply(sapply(li, function(x) sapply(li, setequal, x)), 2, sum)==1]
$b
[1] 77 119 81
$e
[1] 80 45 16
$f
[1] 16 17 19
$h
[1] 22 13 58
?
We can get the unique sorted elements and then remove all the set equal elements with duplicated
li1 <- lapply(li, function(x) sort(unique(x)))
i1 <- !(duplicated(li1)|duplicated(li1, fromLast = TRUE))
li[i1]
#$b
#[1] 77 119 81
#$e
#[1] 80 45 16
#$f
#[1] 16 17 19
#$h
#[1] 22 13 58

Resources