Find Previous Prime Number using R - r

I am trying to find Previous Prime number of given value. The mentioned code works fine if I pass prime Number straight away as input lp(7) returns 7. But if I pass lp(6) none are displaying. I am expecting 5 to return.
How do I find the previous prime Number for given one.
Suggestions / Corrections are much appreciated
lp <- function(x){
temp <- x:2
while (x == 2L || all(x %% 2L:max(2,floor(sqrt(x))) != 0))
{
return(x)
}
}

If you run this function a lot of times, probably most efficient is to generate a list of primes once, and search where your value lies in that sequence
library(primes)
primes = generate_primes(2, 1e6)
find_lower_prime = function(x) {
primes[findInterval(x, primes)]
}
find_lower_prime(6)
# [1] 5

You can use the following
lp <- function(x){
previousNumbers <- 2:x
previousPrimes <- sapply(previousNumbers, function(num) {
divisorsToCheck <- 2:max(2,floor(sqrt(num)))
if(num == 2 | all(num %% divisorsToCheck != 0)) {
return(num)
} else {
return(NA)
}
})
previousPrimes[!is.na(previousPrimes)]
}
to get all previous primes.
lp(18) # 2 3 5 7 11 13 17
lp(5) #2 3 5

You can try the code lie below
lp <- function(x) {
p <- x - 1
repeat {
if (p %in% c(2, 3) | all(p %% ceiling(sqrt(2:p)) != 0)) {
return(p)
}
p <- p - 1
}
}
and you will see
> lp(5)
[1] 3
> lp(6)
[1] 5
> lp(7)
[1] 5
> lp(8)
[1] 7
> lp(11)
[1] 7

Hi All this worked for me ..
lp <- function(x){
for(i in x:2)
{
while (i == 2L || all(i %% 2L:max(2,floor(sqrt(i))) != 0))
{
return(i)
}
}
}

Related

Error in if (a[i][j] > 4) { : missing value where TRUE/FALSE needed

Find the number of entries in each row which are greater than 4.
set.seed(75)
aMat <- matrix( sample(10, size=60, replace=T), nr=6)
rowmax=function(a)
{
x=nrow(a)
y=ncol(a)
i=1
j=1
z=0
while (i<=x) {
for(j in 1:y) {
if(!is.na(a[i][j])){
if(a[i][j]>4){
z=z+1
}
}
j=j+1
}
print(z)
i=i+1
}
}
rowmax(aMat)
It is showing the error. I don't want to apply in built function
You could do this easier counting the x that are greater than 4 using length.
rowmax2 <- function(x) apply(x, 1, function(x) {x <- na.omit(x);length(x[x > 4])})
rowmax2(aMat)
# [1] 8 7 8 7 4 3
If you wanted to do this absolutely without any shortcut you could use two for loops. 1 for each row and another for each value in the row.
rowmax = function(a) {
y=nrow(a)
result <- numeric(y)
for(j in seq_len(y)) {
count = 0
for(val in a[j, ]) {
if(!is.na(val) && val > 4)
count = count + 1
}
result[j] <- count
}
return(result)
}
rowmax(aMat)
#[1] 8 7 8 7 4 3
If you wanted to do this using in-built functions in base R you could use rowSums.
rowSums(aMat > 4, na.rm = TRUE)
#[1] 8 7 8 7 4 3
There are several errors in you code:
You should put z <- 0 inside while loop
You should use a[i,j] for the matrix indexing, rather than a[i][j]
Below is a version after fixing the problems
rowmax <- function(a) {
x <- nrow(a)
y <- ncol(a)
i <- 1
j <- 1
while (i <= x) {
z <- 0
for (j in 1:y) {
if (!is.na(a[i, j])) {
if (a[i, j] > 4) {
z <- z + 1
}
}
j <- j + 1
}
print(z)
i <- i + 1
}
}
and then we get
> rowmax(aMat)
[1] 8
[1] 7
[1] 8
[1] 7
[1] 4
[1] 3
A concise approach to make it is using rowSums, e.g.,
rowSums(aMat, na.rm = TRUE)

I am trying to create a Collatz sequence with while loop in R. What am i doing wrong in this while loop here?

I am trying to create a Collatz sequence with while loop in R.
vector <- NULL
n <- 10
while (n != 1) {
if (n %% 2 == 0) {
n <- n / 2
} else {
n <- (n * 3) + 1
}
vector <- c(vector, cbind(n))
print(vector)
}
After running the code, I got:
[1] 5
[1] 5 16
[1] 5 16 8
[1] 5 16 8 4
[1] 5 16 8 4 2
[1] 5 16 8 4 2 1
How do I do it such that it only shows the last row? What went wrong in my code?
Thanks for any help on this.
You have several ways to deal with print(vector)
add if condition before print(vector), i.e.,
vector <- NULL
n <- 10
while (n != 1) {
if (n %% 2 == 0) {
n <- n / 2
} else {
n <- (n * 3) + 1
}
vector <- c(vector, cbind(n))
if (n==1) print(vector)
}
move it outside while loop, i.e.,
vector <- NULL
n <- 10
while (n != 1) {
if (n %% 2 == 0) {
n <- n / 2
} else {
n <- (n * 3) + 1
}
vector <- c(vector, cbind(n))
}
print(vector)

Error argument is of length zero occurs when creating my own sorting function

*> csort <- function(c){
i<-1
for (i in 1:length(c)-1) {
j <- i+1
for (j in 2:length(c)) {
if(c[i] >= c[j])c[c(i,j)] <- c[c(j,i)]
j = j + 1
}
i = i + 1
}
}
> csort(a)
Error in if (c[i] >= c[j]) c[c(i, j)] <- c[c(j, i)] :
argument is of length zero*
This is what RStudio do when I run it. I do not know what cause the zero here.
csort <- function(c){
p <- 1
povit <- c[1]
c <- c[-1]
left <- c()
right <- c()
left <- c[which(c <= povit)]
right <- c[which(c > povit)]
if(length(left) > 1){
left <- csort(left)
}
if(length(right) > 1){
right <- csort(right)
}
return(c(left ,povit,right))
}
I viewed more about sorting online and this is a pivot sort way.
your mistake is in this line
for (i in 1:length(c)-1)
and should be
for (i in 1:(length(c)-1))
since $:$ operator precedes $-$.
an example is
1:(5-1)
#[1] 1 2 3 4
1:5-1
#[1] 0 1 2 3 4
so error happen in index with Zero value.
csort <- function(d){
for (i in 1:(length(d)-1)) {
for (j in (i+1):length(d)) {
if(d[i] >= d[j])d[c(i,j)] <- d[c(j,i)]
}
}
return(d)
}
d<-c(5:1,-1:3,-9,-3,10,9,-20,1,20,-6,5)
any((csort(d)==sort(d))==F)
#[1] FALSE
you can improve this function.

TwoSum function in R

I was trying to create a function that will pick up the 2 numbers in a list which have the sum of a target number.
Can someone let me know why my code isn't working?
Thank you!
TwoSum <- function(num, target) {
for (i in 1:length(num) - 1) {
for (j in i+1:length(num)) {
if (num[i] + num[j] == target) {
print("the numbers are:")
print(paste0(num[i], num[j]))
a <- a - 1
}
}
}
if (a == 1) {
print("No pairs")
}
}
a <- 1
num <- c(1,2,3,4,5)
target <- 7
TwoSum(num,target)
You should not use a loop for this. Use combn instead:
combs <- combn(num, 2)
combs[,colSums(combs) == target]
# [,1] [,2]
#[1,] 2 3
#[2,] 5 4
Introduce braces in the second and third line.
TwoSum <- function(num, target) {
for (i in 1:(length(num) - 1)) {
for (j in (i+1):length(num)) {
if (num[i] + num[j] == target) {
print("the numbers are:")
print(paste0(num[i], num[j]))
a <- a - 1
}
}

create scoring function and apply to each row in R

I'd like to apply a function to each row in R that "scores" each value of a row, x. It seems like i'd use the 'apply' function in R to do this, but not sure how to do it. I'd like to input a dataframe with a column of values of integers and have a vector output with the score. The code I have now is as follows:
ScoreFn <- function(x){
score <- 0
if(x<1) {
score <- 0
} else if(x==1) {
score <- 5
} else if(x==2) {
score <- 10
} else if(x==3) {
score <- 20
} else if(x >= 4 && x <= 10) {
score <- 30
} else if(x >= 11 && x <= 20) {
score <- 40
} else if(x >= 21) {
score <- 50
}
return(score)
}
apply(df$x, 1, ScoreFn())
Also, I am getting this message. Not sure the best way to do this function.
1: In if (x < 1) { :
the condition has length > 1 and only the first element will be used
2: In if (x == 1) { :
the condition has length > 1 and only the first element will be used
3: In if (x == 2) { :
the condition has length > 1 and only the first element will be used
4: In if (x == 3) { :
the condition has length > 1 and only the first element will be used
...
You can make a vectorised function, using cut, so you don't have to use apply at all:
scorefun <- function(x){
as.numeric(as.character(cut(x, breaks = c(0, 1, 2, 3, 4, 11, 21, Inf),
labels = c(0,5,10,20,30,40, 50), right = FALSE)))
}
df <- data.frame(x = 0:10)
scorefun(df$x)
[1] 0 5 10 20 30 30 30 30 30 30 30
This also has the bonus that cut does the heavy lifting of typing the if/elses, as well as being about 10x faster than the non-vectorised version.
It works by cutting the given vector (in this case df$x) into factors by slices, given by breaks. We then label them with your scores, and then get out the numbers again by using as.character and as.numeric.
If your input is just a column of data.frame, you don't need to use apply. You can use sapply instead.
ScoreFn <- function(x){
score <- 0
if(x<1) {
score <- 0
} else if(x==1) {
score <- 5
} else if(x==2) {
score <- 10
} else if(x==3) {
score <- 20
} else if(x >= 4 && x <= 10) {
score <- 30
} else if(x >= 11 && x <= 20) {
score <- 40
} else if(x >= 21) {
score <- 50
}
return(score)
}
# Return a list of scores
sapply(df$x, ScoreFn)

Resources