Twin primes less than 87 in R - 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

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)
}
}

Modifying for loop with if conditions to apply format in R

I am creating a variable called indexPoints that contains a subset of index values that passed certain conditions -
set.seed(1)
x = abs(rnorm(100,1))
y = abs(rnorm(100,1))
threshFC = 0.5
indexPoints=c()
seqVec = seq(1, length(x))
for (i in seq_along(seqVec)){
fract = x[i]/y[I]
fract[1] = NaN
if (!is.nan(fract)){
if(fract > (threshFC + 1) || fract < (1/(threshFC+1))){
indexPoints = c(indexPoints, i)
}
}
}
I am trying to recreate indexPoints using a more efficient method like apply methods (any except sapply). I started the process as shown below -
set.seed(1)
x = abs(rnorm(100,1))
y = abs(rnorm(100,1))
threshFC = 0.5
seqVec <- seq_along(x)
fract = x[seqVec]/y[seqVec]
fract[1] = NaN
vapply(fract, function(i){
if (!is.nan(fract)){ if(fract > (threshFC + 1) || fract < (1/(threshFC+1))){ i}}
}, character(1))
However, this attempt causes an ERROR:
Error in vapply(fract, function(i) { : values must be length 1,
but FUN(X[[1]]) result is length 0
How can I continue to modify the code to make it in an apply format. Note: sometimes, the fract variable contains NaN values, which I mimicked for the minimum examples above by using "fract[1] = NaN".
There are several problems with your code:
You tell vapply that you expect the internal code to return a character, yet the only thing you ever return is i which is numeric;
You only explicitly return something when all conditions are met, which means if the conditions are not all good, you do not return anything ... this is the same as return(NULL) which is also not character (try vapply(1:2, function(a) return(NULL), character(1)));
You explicitly set fract[1] = NaN and then test !is.nan(fract), so you will never get anything; and
(Likely a typo) You reference y[I] (capital "i") which is an error unless I is defined somewhere (which is no longer a syntax error but is now a logical error).
If I fix the code (remove NaN assignment) in your for loop, I get
indexPoints
# [1] 3 4 5 6 10 11 12 13 14 15 16 18 20 21 25 26 28 29 30 31 32 34 35 38 39
# [26] 40 42 43 44 45 47 48 49 50 52 53 54 55 56 57 58 59 60 61 64 66 68 70 71 72
# [51] 74 75 77 78 79 80 81 82 83 86 88 89 90 91 92 93 95 96 97 98 99
If we really want to do this one at a time (I recommend against it, read below), then there are a few methods:
Use Filter to only return the indices where the condition is true:
indexPoints2 <- Filter(function(i) {
fract <- x[i] / y[i]
!is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1)))
}, seq_along(seqVec))
identical(indexPoints, indexPoints2)
# [1] TRUE
Use vapply correctly, returning an integer either way:
indexPoints3 <- vapply(seq_along(seqVec), function(i) {
fract <- x[i] / y[i]
if (!is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1)))) i else NA_integer_
}, integer(1))
str(indexPoints3)
# int [1:100] NA NA 3 4 5 6 NA NA NA 10 ...
indexPoints3 <- indexPoints3[!is.na(indexPoints3)]
identical(indexPoints, indexPoints3)
# [1] TRUE
(Notice the explicit return of a specific type of NA, that is NA_integer_, so that vapply is happy.)
We can instead just return the logical if the index matches the conditions:
logicalPoints4 <- vapply(seq_along(seqVec), function(i) {
fract <- x[i] / y[i]
!is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1)))
}, logical(1))
head(logicalPoints4)
# [1] FALSE FALSE TRUE TRUE TRUE TRUE
identical(indexPoints, which(logicalPoints4))
# [1] TRUE
But really, there is absolutely no need to use vapply or any of the apply functions, since this can be easily (and much more efficiently) checked as a vector:
fract <- x/y # all at once
indexPoints5 <- which(!is.nan(fract) & (fract > (threshFC+1) | fract < (1/(threshFC+1))))
identical(indexPoints, indexPoints5)
# [1] TRUE
(If you don't use which, you'll see that it gives you a logical vector indicating if the conditions are met, similar to bullet 3 above with logicalPoints4.)

Return list of lists from foreach loop in R

I have a function which returns a list of two objects (a list l and a number n). I want to loop over this function in a foreach loop.
create_lists <- function(){
l = sample(100, 5)
n = sample(100, 1)
return(list(l=l, n=n))}
Because create_lists has a list as ouput, this post told me to use a combine function which looks like this:
combine_custom <- function(list1, list2){
ls = c(list1$l, list2$l)
ns = c(list1$n, list2$n)
return(list(l = ls, n = ns))
}
So now my foreach loop looks like this:
m = foreach(i=1:5, .combine = combine_custom)%do%{
create_lists()}
My desired output would be:
m$l
[[1]]
[1] 100 25 86 21 28
[[2]]
[1] 78 37 79 41 61
[[3]]
[1] 73 22 78 94 13
[[4]]
[1] 15 28 76 78 52
[[5]]
[1] 32 93 92 2 1
m$n
[1] 52 56 3 79 82
But what I get is something like this:
$l
[1] 84 28 75 59 68 84 28 75 59 68
$n
[1] 31 91 18 98 39
So I have two problems:
1) Why is everything but two of the l lists dropped?
2) How can I make m$l to be a list of lists?
EDIT:
I tried another approach I got from here which does not use c:
combine_custom <- function(list1, list2){
ls = list1$l[[length(list1$l)+1]] = list(list2$l)
ns = c(list1$n, list2$n)
return(list(l = ls, n = ns))
}
But this gave the same result as described above, to be exact:
$l
$l[[1]]
[1] 65 84 48 81 82
$n
[1] 88 79 92 36 71
I have found another way which avoids the problem mentioned above, namely that combine has to create a new list first and later only append lists.
Also, the real function I am using actually returns a list of lists, so the following proved useful:
combine_custom <- function(list1, list2) {
if (plotrix::listDepth(list1$l) > plotrix::listDepth(list2$l)) {
ls <- c(list1$l, list(list2$l))
} else {
ls <- c(list(list1$l), list(list2$l))
}
ns <- c(list1$n, list2$n)
return(list(l = ls, n = ns))
}
This is not perfect if the function can return lists of varying nesting depths, but it works in my case.
The combine part is giving a lot of trouble, because on the first iteration, it needs to make a list out of two lists , but on the second iteration, it needs to append one list as an element to a list of lists.
Another approach (may or may not work depending on the size of your actual data/problem) is to use the purrr package for working with lists:
> m <- foreach(i=1:3)%do%{create_lists()}
> m
[[1]]
[[1]]$l
[1] 21 33 12 50 36
[[1]]$n
[1] 74
[[2]]
[[2]]$l
[1] 12 80 39 78 6
[[2]]$n
[1] 74
[[3]]
[[3]]$l
[1] 9 61 75 63 94
[[3]]$n
[1] 2
> purrr::transpose(m)
$l
$l[[1]]
[1] 21 33 12 50 36
$l[[2]]
[1] 12 80 39 78 6
$l[[3]]
[1] 9 61 75 63 94
$n
$n[[1]]
[1] 74
$n[[2]]
[1] 74
$n[[3]]
[1] 2
Hope that helps!
Thank you #Maria H., you solved my problem! The 'plotrix' package didn't work for me, but I used 'collapse' and it worked fine:
combine_custom1 <- function(a, b) {
if (collapse::ldepth(a) > collapse::ldepth(b)) {
ls <- c(a, list(b))
} else {
ls <- c(list(a), list(b))
}
return(ls)
}

Display order of objects in vector in R

Let's say I create a simple vector:
x <- seq(1, 50, by = 5)
Then I might want to display its contents to see which item is the 7th:
print(x)
[1] 1 6 11 16 21 26 31 36 41 46
Is there a simple way to display the contents such that each item is numbered?
[1] 1, [2] 6, [3] 11, etc.
One simple option is to column-bind a counter next to the original vector:
cbind(1:length(x), x)
An elegant way might be to use ?names.
x <- seq(1, 50, by = 5)
names(x) <- seq_along(x)
x
1 2 3 4 5 6 7 8 9 10
1 6 11 16 21 26 31 36 41 46
I assume you're asking how to modify print to include the index of every element of a vector x.
Here is a possibility
x <- seq(1, 50, by = 5)
cat(sapply(seq_along(x), function(i) (sprintf("[%i] %i", i, x[i]))), "\n")
#[1] 1 [2] 6 [3] 11 [4] 16 [5] 21 [6] 26 [7] 31 [8] 36 [9] 41 [10] 46
Or you could define a custom my.print function that nicely wraps lines every nmaxth entry for long vectors
my.print <- function(x, nmax = 6) {
os <- 0
while (length(x) > 0) {
cat(sapply(seq_along(x[1:min(length(x), 6)]), function(i)
sprintf("[%i] %i", i + os, x[i])), "\n")
x <- x[-(1:min(length(x), nmax))]
os <- os + nmax
}}
my.print(x)
#[1] 1 [2] 6 [3] 11 [4] 16 [5] 21 [6] 26
#[7] 31 [8] 36 [9] 41 [10] 46

Storing the output from a loop as a list in R

I am running a small loop to randomly assign a list of numbers (1 to 30) to a subset of 4 groups. I would like to store the outputs of the loop (for 4 subsets) as a single line in one variable and use the results elsewhere. I am also getting some warnings, though the output is correctly displayed on the screen.
list = as.vector(c(6, 9, 3, 12)
start <- 1
end <- 6
i <- 1
while(i<=list){
print(sample(start:end, replace=T))
start <- start+list[i]
end <- end + list[i+1]
i <- i+1
}
[1] 3 5 6 1 5 6
[1] 9 13 12 7 11 12 14 11 14
[1] 16 17 17
[1] 28 22 26 21 28 26 22 28 26 30 21 19
Error in start:end : NA/NaN argument
In addition: Warning messages:
1: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
2: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
3: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
4: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
5: In while (i <= list) { :
the condition has length > 1 and only the first element will be used
I am unable to find the reasons for this error. Please help. Thanks.
Works fine using for loop than while loop, no need of sub-setting i variable when we use seq function
list = c(6, 9, 3, 12)
start <- 1
end <- 6
for(i in seq(list)){
if(i <= list[i]){
start <- start+list[i]
end <- end + (list[i]+1)
print(sample(start:end, replace=T))
}
}
[1] 10 8 11 7 11 10 12
[1] 23 17 18 21 22 18 20 21
[1] 25 21 27 23 26 26 23 25 22
[1] 33 32 37 37 35 40 32 37 34 38

Resources