Prime number generator using for loop in R - r

Trying to create a for loop in which you input a number and the function tells you whether or not the number is prime or not. I used two examples being n1 <- 100 and n2 <- 101.
Here is my code below:
n1 <- 100
n2 <-101
answer = TRUE
for(i in n1){
if (n1 %% (i-1) == 0){
prime1=FALSE
}else {
prime1=TRUE
}
}
prime1
answer = TRUE
for (i in n2){
if (n2 %% (i-1) == 0){
prime2=FALSE
}else {
prime2=TRUE
}
}
prime2
The problem is that the function will generate the same output for both depending on one difference in the code.
In the first "if" statement, both functions will generate output TRUE if I put in the line (i-1). However, if I instead change the line of code to "n1 %% i == 0" as opposed to "n1 %% (i-1) == 0", both functions generate the output FALSE.
Any pointers? Thanks!

Here's a simple prime checker using a for loop.
With n1 <- 100 :
for(i in seq(2, ceiling(sqrt(n1)))) {
if(n1 %% i == 0){
print(FALSE)
break
}
if(i == ceiling(sqrt(n1)))
print(TRUE)
}
#> [1] FALSE
With n2 <- 101
for(i in seq(2, ceiling(sqrt(n2)))) {
if(n2 %% i == 0){
print(FALSE)
break
}
if(i == ceiling(sqrt(n2)))
print(TRUE)
}
#> [1] TRUE

Related

How can you check whether a sequence is an 'almost increasing sequence' in R?

A sequence (e.g. c(1,2,3,4)) is almost increasing when we can remove exactly one element from the sequence and get a strictly increasing sequence (i.e. a0 < a1 < ... < an). I'm trying to find a way to check whether a sequence is almost increasing. If it is, I want to return TRUE; if it isn't I want to output FALSE. I've got this far:
solution <- function(sequence) {
sequence1 <- unlist(sequence)
if (length(sequence1) == 1) {
next
}
count <- 0
for (i in (length(sequence1) - 1)) {
if (sequence1[i + 1] > sequence1[i]) {
next
} else if (((sequence1[i + 2] > sequence1[i]) & count == 0) & i !=
length(sequence1)-1) {
sequence1 <- sequence1[- (i + 1)]
count <- count + 1
} else if ((sequence1[i + 1] > sequence1[i - 1]) & count == 0 & i != 1) {
sequence1 <- sequence1[-i]
count <- count + 1
} else {
return(FALSE)
}
}
return(TRUE)
}
I've used unlist() because codesignal, for some reason, doesn't accept you to refer to the function argument within the function. This works for some sequences: solution(c(4,1,5)) correctly returns TRUE. It doesn't work for others: solution(c(1, 1, 1, 2, 3)) incorrectly returns TRUE. solution(c(2,1,2,1)) correctly returns FALSE and yet solution(c(1,2,1,2)) incorrectly returns TRUE. I've lost my grip on what's going on. I wonder if anyone can spot anything?
Clarification: the basic idea of my code is to iterate through the sequence and for each element check whether its right neighbour is a bigger number. If it isn't, then we have two options: get rid of i or get rid of i+1, so I check those in turn. Since we can only make one change, i've added the condition that if count is 1, then we skip to finish. Also, if the index is 1 then we can't check i-1, and if the index is length(sequence)-1, then we can't check i+2, so i've added those conditions in to make sure my code skips to the other option if appropriate.
Here is a solution which works for me. The idea is that diff(x) has negative elements for every downwards step in x. For example, min(diff(x)) is positive, if x is strictly increasing. If diff(x)[i] <= 0 for exactly one index i, we have to check whether either removing x[i] or removing x[i+1] makes the sequence strictly increasing. The following function passed all tests I tried:
check_almost <- function(x) {
if (length(x) < 2) {
return(TRUE)
}
d <- diff(x)
i <- which(d <= 0)
if (length(i) == 0) {
return(TRUE) # strictly increasing
} else if (length(i) > 1) {
return(FALSE)
}
return(i == 1 || # we can remove x[1]
i == length(d) || # we can remove x[length(x)]
d[i-1]+d[i] > 0 || # we can remove x[i]
d[i] + d[i+1] > 0) # we can remove x[i+1]
}

How to use the output of an r function in another function?

I want to create an script that calculates probabilities for a rol game.
I´m new to programming and I´m stuck with the return values and nested functions. What I want is to use the values returned by the first function in the next one.
I have two functions dice(k, n) and fight(a, b). (for the example, the functions are partly written):
dice <- function (k, n) {
if (k > 3 && n > 2){
a <- 3
b <- 2
attack <- sample(1:6, a)
deff <- sample(1:6, b)
}
return(c(attack, deff))
}
So I want to use the vector attack, and deff in the next function:
fight <- function(a, b){
if (a == 3 && b == 2){
if(sort(attack,T)[1] > sort(deff,T)[1]){
n <- n - 1}
if (sort(attack,T)[1] <= sort(deff,T)[1]) {
k <- k - 1}
if (sort(attack,T)[2] > sort(deff,T)[2]) {
n <- n - 1}
if (sort(attack,T)[2]<= sort(deff,T)[2]){
k <- k - 1}
}
return(c(k, n)
}
But this gives me the next error:
Error in sort(attack, T) : object 'attack' not found
Any ideas? Thanks!

Create sequence in R

Hi I was wondering if someone knows how to realize this sequence in R?
Consider a sequence with following requirement.
a1=1
an=an-1+3 (If n is a even number)
an=2×an-1-5 (If n is a odd number)
e.g. 1,4,3,6,7,10,15,...
a30=?
Try the following.
It will return the entire sequence, not just the last element.
seq_chih_peng <- function(n){
a <- integer(n)
a[1] <- 1
for(i in seq_along(a)[-1]){
if(i %% 2 == 0){
a[i] <- a[i - 1] + 3
}else{
a[i] <- 2*a[i - 1] - 5
}
}
a
}
seq_chih_peng(30)
Note that I do not include code to check for input errors such as passing n = 0 or a negative number.
If you want to do it recursively, you just have the write the equations in your function as follows:
sequence <- function(n) {
if (n == 1) return(1)
else if (n > 1) {
if (n %% 2 == 1) {
return(2 * sequence(n - 1) - 5)
}else{
return(sequence(n - 1) + 3)
}
}else{
stop("n must be stricly positive")
}
}
sequence(30)
# returns 32770

R - Print values using for, while, and repeat loop

I am having trouble again with my code. Here is the question and what I have right now:
# 2. Draw a random sample of size n=20 from a uniform distribution in 0 and 1 using
# runif(20). Sequentially, print values using the following rules:
# i. Print a value if it is less than 0.3 or more than 0.8, but skip it
# (don’t print the value) if it is in (0.1, 0.2],
# ii. Skip the entire process if you find a value in [0.4,0.5].
# Write three separate R codes using (a) for loop, (b) while loop
# and (c) repeat loop.
# (a) for loop
n = runif(20)
for (val in n){
if (val > 0.1 & val <= 0.2){
next
} else if (val < 0.3 | val > 0.8){
print(val)
} else if (val >= 0.4 & val <= 0.5){
print(val)
break
}
}
# (b) while loop
n = 1
m = runif(20)
while(n < 20){
if (m > 0.1 & m <= 0.2){
next
} else if (m < 0.3 | m > 0.8){
print(m)
} else if (m >= 0.4 & m <= 0.5){
print(m)
break
}
n = n + 1
}
# (c) repeat loop
n = 1
m = runif(20)
repeat{
if (m > 0.1 & m <= 0.2){
next
} else if (m < 0.3 | m > 0.8){
print(val)
} else if (m >= 0.4 & m <= 0.5){
print(m)
break
}
}
Part (a) for loop is working perfectly.
My only issue is (b) while loop and (c) repeat loop. He didn't do a good job in class or notes going over a while loop and repeat loop. Please help.
The object m that you created has a length of 20, so when you go to test it with something like if (m > 0.1 & m <= 0.2), R only tests the first item in your object. To solve this, you'll need to index m with n, your loop counter. In other words, don't use m in your tests, but use m[n] instead. In all it should look like this:
n <- 1
m <- runif(20)
while(n < 20){
if (m[n] > 0.1 & m[n] <= 0.2){
next
} else if (m[n] < 0.3 | m[n] > 0.8){
print(m[n])
} else if (m[n] >= 0.4 & m[n] <= 0.5){
print(m[n])
break
}
n <- n + 1
}
You should be able to use a similar approach for part c. (Also note that in part c you have print(val) at one point.)
Hope that helps!
Apparently the exercise if for you to sort it out, but OK, I'll post a solution.
# (b) while loop
n = 1
m = runif(20)
while(n <= 20){
if (m[n] > 0.1 & m[n] <= 0.2){
n = n + 1
next
} else if (m[n] < 0.3 | m[n] > 0.8){
print(m[n])
} else if (m[n] >= 0.4 & m[n] <= 0.5){
print(m[n])
break
}
n = n + 1
}
# (c) repeat loop
n = 0
m = runif(20)
repeat{
if(n < 20)
n <- n + 1
else
break
if (m[n] > 0.1 & m[n] <= 0.2){
next
} else if (m[n] < 0.3 | m[n] > 0.8){
print(m[n])
} else if (m[n] >= 0.4 & m[n] <= 0.5){
print(m[n])
break
}
}
As a final note, whenever pseudo-random number generators are used you should set the initial value in order for the results to be reproducible. This is done like this:
set.seed(6019) # or any other value, 6019 is the seed
This is put before the first call to runif.

Modulus warning in R- Lehmann Primality Test

I spent a little time hacking an R implementation of the lehmann primality test. The function design I borrowed from http://davidkendal.net/articles/2011/12/lehmann-primality-test
Here is my code:
primeTest <- function(n, iter){
a <- sample(1:(n-1), 1)
lehmannTest <- function(y, tries){
x <- ((y^((n-1)/2)) %% n)
if (tries == 0) {
return(TRUE)
}else{
if ((x == 1) | (x == (-1 %% n))){
lehmannTest(sample(1:(n-1), 1), (tries-1))
}else{
return(FALSE)
}
}
}
lehmannTest(a, iter)
}
primeTest(4, 50) # false
primeTest(3, 50) # true
primeTest(10, 50)# false
primeTest(97, 50) # gives false # SHOULD BE TRUE !!!! WTF
prime_test<-c(2,3,5,7,11,13,17 ,19,23,29,31,37)
for (i in 1:length(prime_test)) {
print(primeTest(prime_test[i], 50))
}
For small primes it works but as soon as i get around ~30, i get a bad looking message and the function stops working correctly:
2: In lehmannTest(a, iter) : probable complete loss of accuracy in modulus
After some investigating i believe it has to do with floating point conversions. Very large numbers are rounded so that the mod function gives a bad response.
Now the questions.
Is this a floating point problem? or in my implementation?
Is there a purely R solution or is R just bad at this?
Thanks
Solution:
After the great feedback and a hour reading about modular exponentiation algorithms i have a solution. first it is to make my own modular exponentiation function. The basic idea is that modular multiplication allows you calculate intermediate results. you can calculate the mod after each iteration, thus never getting a giant nasty number that swamps the 16-bit R int.
modexp<-function(a, b, n){
r = 1
for (i in 1:b){
r = (r*a) %% n
}
return(r)
}
primeTest <- function(n, iter){
a <- sample(1:(n-1), 1)
lehmannTest <- function(y, tries){
x <- modexp(y, (n-1)/2, n)
if (tries == 0) {
return(TRUE)
}else{
if ((x == 1) | (x == (-1 %% n))){
lehmannTest(sample(1:(n-1), 1), (tries-1))
}else{
return(FALSE)
}
}
}
if( n < 2 ){
return(FALSE)
}else if (n ==2) {
return(TRUE)
} else{
lehmannTest(a, iter)
}
}
primeTest(4, 50) # false
primeTest(3, 50) # true
primeTest(10, 50)# false
primeTest(97, 50) # NOW IS TRUE !!!!
prime_test<-c(5,7,11,13,17 ,19,23,29,31,37,1009)
for (i in 1:length(prime_test)) {
print(primeTest(prime_test[i], 50))
}
#ALL TRUE
Of course there is a problem with representing integers. In R integers will be represented correctly up to 2^53 - 1 which is about 9e15. And the term y^((n-1)/2) will exceed that even for small numbers easily. You will have to compute (y^((n-1)/2)) %% n by continually squaring y and taking the modulus. That corresponds to the binary representation of (n-1)/2.
Even the 'real' number theory programs do it like that -- see Wikipedia's entry on "modular exponentiation". That said it should be mentioned that programs like R (or Matlab and other systems for numerical computing) may not be a proper environment for implementing number theory algorithms, probably not even as playing fields with small integers.
Edit: The original package was incorrect
You could utilize the function modpower() in package 'pracma' like this:
primeTest <- function(n, iter){
a <- sample(1:(n-1), 1)
lehmannTest <- function(y, tries){
x <- modpower(y, (n-1)/2, n) # ((y^((n-1)/2)) %% n)
if (tries == 0) {
return(TRUE)
}else{
if ((x == 1) | (x == (-1 %% n))){
lehmannTest(sample(1:(n-1), 1), (tries-1))
}else{
return(FALSE)
}
}
}
lehmannTest(a, iter)
}
The following test is successful as 1009 is the only prime in this set:
prime_test <- seq(1001, 1011, by = 2)
for (i in 1:length(prime_test)) {
print(primeTest(prime_test[i], 50))
}
# FALSE FALSE FALSE FALSE TRUE FALSE
If you are just using base R, I would pick #2b... "R is bad at this". In R integers (which you do not appear to be using) are restricted to 16-bit accuracy. Above that limit you will get rounding errors. You should probably be looking at: package:gmp or package:Brobdingnag. Package:gmp has large-integer and large-rational classes.

Resources