R: Creating a function usingthe control structure 'for' - r

I would like to create a function that, having a vector (v) and a number (n), analyze if any of the numbers of 'v' is divisible by 'n', if it is, the function would have the outcome 'TRUE'. How could I use the control structure 'for' for it?
So far I've solved this problem using the 'while' operator:
function.while <- function(v, n){
while (n %% v == 0)
return (TRUE)
}
But I can't fully understand the logic of 'for'.
Thanks.

You can use for loop like below :
function.for <- function(v, n){
result <- logical(length(v))
for(i in seq_along(v)) {
result[i] <- v[i] %% n == 0
}
return(result)
}
function.for(1:10, 2)
#[1] FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
However, this is vectorised operation and you don't need for loop.
function.vectorized <- function(v, n){
v %% n == 0
}
function.vectorized(1:10, 2)
If you want to check if any value is present.
function.vectorized <- function(v, n){
any(v %% n == 0)
}

Related

What is the purpose of b <-c() in this code?

I have written a code to find a positive integer that has more divisors than any smaller positive integer has. My code is right but I noticed that I wrote a step only because I had solved other questions similarly but I don't really understand the intuition of why we write this particular line:
b <- c()
Also, why is there a "b" in c(b, sum..) as in the below line:
b <- c(b, sum(p %% c(1:p) == 0))
Here is the full code:
code <- function(n) {
if (n < 1 | n %% 1 != 0)
print("Only positive integers allowed")
else if (n <= 2)
return(TRUE)
else {
a <- sum(n %% c(1:n) == 0)
b <- c()
for (p in 1:(n-1)) {
b <- c(b, sum(p %% c(1:p) == 0))
}
return(max(b) < a)
}
}
code(8)
code(6)
code(-7)
As already explained in comments the purpose of b<-c() is to initialise an empty vector and fill it in the loop. Also the reason why you are using b <- c(b,sum(p%%c(1:p)== 0)) is to append new values to already existing values of b.
For example,
b <- c()
b
#NULL
b <- c(b, 1)
b
#[1] 1
b <- c(b, 2)
b
#[1] 1 2
Usually, it is not a good practice to grow an object in a loop, it is highly inefficient to do that. If the size of output is fixed you can initialise a vector with fixed size and then fill it in the loop.
code <- function(n){
if (n<1 | n%%1!=0)
print("Only positive integers allowed")
else if (n <= 2)
return(TRUE)
else{
a <- sum(n%%c(1:n) == 0)
b <- integer(n-1) #Creates a vector with 0's of length n-1
for (p in 1:(n-1)) {
b[p] <- sum(p%%c(1:p)== 0)
}
return(max(b) < a)
}
}
Or in this case you can save only the max value of b since all other values are not important.
code <- function(n){
if (n<1 | n%%1!=0)
print("Only positive integers allowed")
else if (n <= 2)
return(TRUE)
else{
a <- sum(n%%c(1:n) == 0)
max_b <- 0
for (p in 1:(n-1)) {
val <- sum(p%%c(1:p)== 0)
if(val > max_b) max_b <- val
}
return(max_b < a)
}
}

Question about passing sapply index to function

I am sure this is a simple problem. But I am new to programming so I am struggling. I think what I am trying to accomplish should be pretty clear from the code. Essentially, I want to generate a vector of random numbers of length i, check if there is less than i unique numbers. And I want to do this a bunch of times as a sort of simulation. When I do it i by i manually using the following code:
experiment<- function() {
ab <- rdunif(i, 1, 365)
ab <- data.frame(ab)
count <- uniqueN(ab)
if (count < i)
return(1)
else
return(0)
}
vector <- replicate(10, experiment(), simplify=FALSE)
sum <- sum(as.data.frame((vector)))
probability <- sum/(10)
It works fine. But I need to run this simulation 40 times and I would rather not do it by hand. However, I can't seem to get sapply to work for me and I cannot figure out what I am doing wrong:
i<-10:50
experiment<- function(i) {
ab <- rdunif(i, 1, 365)
ab <- data.frame(ab)
count <- uniqueN(ab)
if (count < i)
return(1)
else
return(0)
}
complete <- function(i) {
vector <- replicate(10, experiment(i), simplify=FALSE)
sum <- sum(as.data.frame((vector)))
probability <- sum/(10)
return(probability)
}
sapply(i, complete(i), simplify=FALSE)
This is the error I am currently experiencing:
Error in match.fun(FUN) :
'complete(i)' is not a function, character or symbol
In addition: Warning messages:
1: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
2: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
3: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
4: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
5: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
6: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
7: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
8: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
9: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
10: In if (count < i) return(1) else return(0) :
the condition has length > 1 and only the first element will be used
I figured it out:
experiment<- function(i) {
ab <- rdunif(i, 1, 365)
count <- length(unique(ab))
if (count < i) return(1)
else return(0)
}
i <- 10:50
replication <- function(i) {
replicate(100, experiment(i))
}
data<- sapply(i, replication)
colMeans(data)

How does this R function for the Sieve of Eratosthenes work?

I just started learning R, and was looking at a block of code that found prime numbers with the Sieve of Eratosthenes, up to some number n:
sieve <- function(n) {
if (n < 2) return(NULL)
a <- rep(T, n)
a[1] <- F
for(i in seq(n)) {
if (a[i]) {
j <- i * i
if (j > n) return(which(a))
a[seq(j, n, by=i)] <- F
}
}
}
The code works, but I don't understand how. I'm particularly confused by what a[seq(j, n, by=i)] is doing. I wrote comments on the code to show what I believe it does so far:
n=10
sieve <- function(n) {
if (n < 2) return(NULL) #ignore inputs that don't return anything
a <- rep(T, n) #TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
a[1] <- F ##to ignore 1? #FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
for(i in seq(n)) {
if (a[i]) { #i.e., for all values but 1
j <- i * i #4 9 16 25...
if (j > n) return(which(a))
a[seq(j, n, by=i)] <- F
}
}
}

Replicating is.element

I need to replicate the is.element function in R. I have two vectors and need to compare the values in each where if one matches the other the output is True and False for all others.
Code I've tried that does not quite work:
x <- c(3, 0, -2, 0)
y <- c(-1, 0, 1)
n <- length(x)
answer <- is.logical(x)
for (i in 1:n) {
if (x[i] == y[i]) {
answer[i] <- TRUE
} else {
answer[i] <- FALSE
}
}
answer
Intended answer:
[1] FALSE TRUE FALSE TRUE
An option would be outer to do the comparison of each element of 'x' with 'y' to return a logical matrix, which can be reduced to a logical vector
by getting the sum of TRUE elements in each row (rowSums) and check if it is greater than 0
rowSums(outer(x, y, `==`)) > 0
#[1] FALSE TRUE FALSE TRUE
Or create the logical matrix with sapply and do a `colSums
colSums(sapply(x, `==`, y)) > 0
actually, I just figured it out. Thanks again.
x <- c(3, 0, -2, 0)
y <- c(-1, 0, 1)
n <- length(x)
m <- length(y)
answer <- is.logical(x)
for (i in 1:n) {
for (j in 1:m) {
if (x[i] == y[j]) {
answer[i] <- TRUE
break
} else {
answer[i] <- FALSE
}
}
}
answer

R: converting a while loop to recursion

I'm trying to convert a while loop to a recursion.
I know the while loop is more efficient, but I'm trying to understand how to convert a for/while loop to recursion, and recursion to a for/while/if loop.
my function as I'm using a while loop:
harmon_sum <- function(x){
n <- 1
sum <- 0
while (sum < x)
{
sum <- sum + (1/n)
n <- (n +1)
}
return(n)
}
This function takes some numeric value, suppose x=2, and returns the number of objects for the harmonic sum that you need to sum up in order to create a greater number then x. (for x=2, you'd need to sum up the first 5 objects of the harmonic sum)
[![harmonic sum][1]][1]
**example**: `harmon_sum <- function(x){
n <- 1
sum <- 0
while (sum < x)
{
sum <- sum + (1/n)
print(sum)
n <- (n +1)
print(n)
}
return(n)
}
> harmon_sum(x =2)
[1] 1
[1] 2
[1] 1.5
[1] 3
[1] 1.833333
[1] 4
[1] 2.083333
[1] 5
[1] 5`
my version for the recursive function:
harmon_sum2 <- function(x, n =1){
if( x<= 0){
return(n-1)
}
else {
x <- (x- (1/(n)))
harmon_sum2(x, n+1)
}
}
which returns me the wrong answer.
I'd rather find a solution with just one variable (x), instead of using two variables (x, n), but I couldn't figure a way to do that.
It seems to me that if you change return(n-1) to return(n) you do get the right results.
harmon_sum2 <- function(x, n=1){
if( x <= 0){
return(n)
}
else {
x <- (x- (1/(n)))
harmon_sum2(x, n+1)
}
}
harmon_sum(2)
[1] 5
harmon_sum2(2)
[1] 5
harmon_sum(4)
[1] 32
harmon_sum2(4)
[1] 32
Your function needs to know n. If you don't want to pass it, you need to store it somewhere where all functions on the call stack can access it. For your specific case you can use sys.nframe instead:
harmon_sum2 <- function(x){
if( x<= 0){
return(sys.nframe())
}
else {
x <- (x- (1/(sys.nframe())))
harmon_sum2(x)
}
}
harmon_sum(8)
#[1] 1675
harmon_sum2(8)
#[1] 1675
However, this doesn't work if you call your function from within another function:
print(harmon_sum2(8))
#[1] 4551
Another alternative is the approach I demonstrate in this answer.

Resources