switch case: several equivalent cases expressions in r - r

In r-programming:
i want to use the same method to handle cases 1 and 10, ie, when the loop is in round 1 and then in 10 again. same for 2 and 11.
is there a way to have several case expressions being handled by the same method
for k == 1 and later also fo 10 it should use the first case and for k ==2 and later 11 it should use the second case. the above code doesn't work.
for(i in 1:x) {
switch(k,
"1", "10"= {
correct <- test[21,1]
current <- test[i-p,1]
if(all(correct == current)){
answers[i-p,k] <- c(1)
} else{
answers[i-p,k] <- c(0)
}
},
"2","11" ={
correct <- test[21,2]
current <- test[i,2]
if(all(correct == current)){
answers[i,k] <- c(1)
} else{
answers[i,k] <- c(0)
}
}
}
the same code for only one case expression works:
for(i in 1:x) {
switch(k,
"1" = {
correct <- test[21,1]
current <- test[i-p,1]
if(all(correct == current)){
answers[i-p,k] <- c(1)
} else{
answers[i-p,k] <- c(0)
}
},
"2" ={
correct <- test[21,2]
current <- test[i,2]
if(all(correct == current)){
answers[i,k] <- c(1)
} else{
answers[i,k] <- c(0)
}
}
}
in java we can use case 1 : case 2 to do that. how is it done in r?
i appreciate your help. alternatively i could also copy the code but don't want to if i can avoid it.

My personal choice would be to remap your k to the overlapping cases. Example:
k<-1:20
kmatch<-(k-1)%%9 +1
# [1] 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2
Then feed kmatch to your case expression

The syntax is along the lines of
f = function(x)
switch(x, "1"=, "10"="first", "11"="eleventh", "none")
Note the equal sign after each named expression, other than the default value.
> f("1")
[1] "first"
> f("10")
[1] "first"
> f("11")
[1] "eleventh"
> f("12")
[1] "none"
This is documented in the third paragraph of the 'Details' section of ?switch.

Related

R Floop behavior

Suppose I have the following R loop:
for(i in 1:5){
print(i)
i = i + 1
}
This produces the following result:
1
2
3
4
5
Which is weird since I did redefine the index inside the loop.
Why do we see this behavior?
I thought I would see something like the following:
1
3
4
5
6
Assignment to the looping variable i is discarded on the next loop iteration, so i = i + 1 has no effect. If you want to change the value of i within the loop, you can use a while loop.
However, your intended output of 1 3 4 5 6 doesn't make sense for a couple of reasons:
assignment of i, as already mentioned;
why does it not increment every other loop?; and
the domain of i, 1:5, is locked in at the first pass of the loop.
Having said that, try this:
i <- 1
lim <- 5
while (i <= lim) {
if (i == 2) {
lim <- lim + 1
} else {
print(i)
}
i <- i + 1
}
# [1] 1
# [1] 3
# [1] 4
# [1] 5
# [1] 6
(My only caution here is that if your increment of i is conditional on anything, there needs to be something else that prevents this from being an infinite loop. Perhaps this caution is unnecessary in your use-case, but it seems relevant to at least mention it.)
The i is the for each value and that cannot be modified with i = i + 1. We may use an if condition
for(i in 1:5){
if(i != 2)
print(i)
}
-output
[1] 1
[1] 3
[1] 4
[1] 5
Also, if the intention is to subset a vector, why not use vectorized option
v1 <- 1:5
v1[v1 != 2]

Find Previous Prime Number using 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)
}
}
}

Executing Basic Addition with for Loop (Trying to Understand how R Interprets for Loops)

I have a vector named jvec that consists of #'s 1 - 9 and simply want to use a for loop to add 1 to every number in the vector if that number is bigger than 3 and print the result once. I've tried this a number of ways and all have failed.
jvec <- c(1:9)
for (x in jvec) {
if (x > 3) {
x + 1
}
}
print(jvec)
(won't work)
This won't work either:
jvec <- c(1:9)
for (x in jvec[c(x)]) {
if (jvec[c(x)] > 3) {
jvec[c(x)+1]
print(jvec)
}
}
Could someone please explain why neither of these options do the trick as well as how to do it correctly? Thanks!
You could iterate over the index of jvec and update jvec only if the value is greater than 3.
jvec <- 1:9
for (x in seq_along(jvec)) {
if (jvec[x] > 3) {
jvec[x] <- jvec[x] + 1
}
}
print(jvec)
#[1] 1 2 3 5 6 7 8 9 10
However, you can also do this without for loop :
jvec <- 1:9
jvec + as.integer(jvec > 3)
#[1] 1 2 3 5 6 7 8 9 10
It is the same like in other programming languages - you have to actually assign your calculation results to a variable (to save it).
E.g. this would work (but there are also quicker ways in R):
jvec <- c(1:9)
for (i in 1:length(jvec)) {
if (jvec[i] > 3) {
jvec[i] <- jvec[i] + 1
}
}
print(jvec)

finding sth with loops by indexing in R

Create a for loop that checks whether a numeric vector has at least two zeros in
a row. If so, it prints the position (index) of the first zero.
Here is a version by using rle + inverse.rle
findConZeros <- function(x) {
u <- rle(unlist(strsplit(as.character(x),""))==0)
u$values <- with(u,lengths>=2&values)
which(inverse.rle(u))
}
such that
> findConZeros(1200011)
[1] 3 4 5
> findConZeros(40400)
[1] 4 5
Below is a for loop version
findConZeros_forloop <- function(x) {
s <- unlist(strsplit(as.character(x),""))
res <- c()
for (i in seq_along(s)) {
if (all(s[i:(i+1)]=="0") & i < length(s)) res <- c(res,i,i+1)
}
unique(res)
}
which gives
> findConZeros_forloop(1200011)
[1] 3 4 5
> findConZeros_forloop(40400)
[1] 4 5

Quicksort in R: How do I print the intermediate steps?

I admit my knowledge of algorithms isn't very good. I wrote a quicksort function in R using basic recursion. My question is, how do I modify this algorithm to also display the intermediate vectors between each iteration. I know there is a clever way to do it with tracking where your pivot is but I'm struggling to figure it out myself.
qs <- function(vec) {
if(length(vec) > 1) {
pivot <- vec[1]
low <- qs(vec[vec < pivot])
mid <- vec[vec == pivot]
high <- qs(vec[vec > pivot])
c(low, mid, high)
}
else vec
}
PS: I am not sure, but your implementation might be very inefficient depending on how R implements subscripting with a logical array.
You cannot do it without spending too much memory in it in the current state (i.e. using recursion).
If you want to keep recursion:
This is depth first approach. Initialize an array of arrays. The first index is the depth and the corresponding array would give you the state at that depth. Keep track of depth (i.e. pass depth as a parameter) and append the subarray to the corresponding depth.
Code:
printableList = Array of empty arrays
qs <- function(vec, depth) {
printableList[depth] = printableList[depth] + vec
if(length(vec) > 1) {
pivot <- vec[1]
low <- qs(vec[vec < pivot], depth+1)
mid <- vec[vec == pivot]
high <- qs(vec[vec > pivot], depth+1)
c(low, mid, high)
}
else vec
}
Alternatively:
You can also implement the whole thing as a breadth first approach. You will have to implement the whole thing with a queue. Here, since you process the sub-problems layer-by-layer you just have to print them.
As #dickoa noted, use print. However, if you're using the GUI, printed output is by default buffered until the function returns. You can force the printout to occur immediately with flush.console.
qs <- function(vec) {
# print input vector
print(vec); flush.console()
if(length(vec) > 1) {
pivot <- vec[1]
low <- qs(vec[vec < pivot])
mid <- vec[vec == pivot]
high <- qs(vec[vec > pivot])
c(low, mid, high)
}
else vec
}
Sample run:
> z <- sample(10)
> qs(z)
[1] 2 6 1 4 8 5 9 7 3 10
[1] 1
[1] 6 4 8 5 9 7 3 10
[1] 4 5 3
[1] 3
[1] 5
[1] 8 9 7 10
[1] 7
[1] 9 10
integer(0)
[1] 10
[1] 1 2 3 4 5 6 7 8 9 10
You can do it by passing the whole vector at each function call, together with "start" and "end" parameters to describe which slice of the vector you're currently sorting. Here's my first attempt at doing this. Maybe you can write a more elegant version?
qs<-function(vec,start=1,finish=length(vec)) {
if (finish>start) {
pivot<-vec[start]
N<-length(vec)
window<-((1:N)>=start) & ((1:N)<=finish)
low_part<-vec[(vec<pivot) & window]
mid_part<-vec[(vec==pivot) & window]
high_part<-vec[(vec>pivot) & window]
if (start>1) cat(vec[1:(start-1)],"| ")
cat(low_part,">>>",mid_part,"<<<",high_part)
if (finish<N) cat(" |",vec[(finish+1):N])
cat("\n")
vec[window]<-c(low_part,mid_part,high_part)
if (length(low_part)>0) {
low_top<-start+length(low_part)-1
vec[start:low_top]<-qs(vec,start,low_top)[start:low_top]
}
if (length(high_part)>0) {
high_bottom<-finish-length(high_part)+1
vec[high_bottom:finish]<-qs(vec,high_bottom,finish)[high_bottom:finish]
}
}
return(vec)
}
qs(sample(1:30,replace=TRUE))

Resources