I want to iterate a loop only for some values so I am using this:
present <- c(3,5,7,8)
for(i in present)
{
print(i)
}
which gives me
[1] 3
[1] 5
[1] 7
[1] 8
however I need to jump to the next value within the loop, say I dont want 5 to be printed in above example.
I cannot use next since I want it in nested for like this
present <- c(3,5,7,8)
for(i in present)
{
k <- i
"Jump to next value of present"
while(k < "The next value for i should come here")
{
k <- k + 1
print(k)
}
}
The output would be 3 4 5 6 7 8 but the condition must check value of k if it exceeds next value of i.
Is there anyway to accomplish this?
I'll take help of C to explain further,
for(i=0; i < 10; i++)
{
for(k=i;k <= i+1;k++)
{
printf("%d", k);
}
}
The link contains output of above code
http://codepad.org/relkenY3
It is easy in C since next value is in sequence, but here next value is not known, hence the problem.
What you should do is loop through two vectors:
x <- head(present, -1)
# [1] 3 5 7
y <- tail(present, -1)
# [1] 5 7 8
and the function to do that is mapply (have a look at ?mapply). A close translation of your pseudo-code would be:
invisible(mapply(function(x, y) while(x < y) {x <- x + 1; print(x)}, x, y))
but maybe you'll find this more interesting:
mapply(seq, x + 1, y)
I suspect the answer is to use seq_along and use it as an index into "present", but as others have pointed out your code does not promise to deliver what you expect, even with that simple modification. The K <- K=1 assignment jumps ahead too far to deliver a value of 3 at any point and the termination condition is likewise not clear. It turns into an infinite loop in the form you construct. Work with this;
present <- c(3,5,7,8)
for(i in seq_along(present))
{
k <- i
while(k < length(present) )
{
k <- k + 1
print(present[k])
}
}
Related
I have a list with values and I need to select values from this list that are greater or equal to 3 and less than/equal to 4 but I don't know how to do so using the while and if loops. Anyone could give me a clue on how to solve this?
If I understood what you have in mind correctly, you can use the following solution. Imagine we have a vector of length 20 called vec:
We first create an empty vector out to store our result in it during in every iteration (if any)
Then we set the iterator i to its first value (here we set the initial value to 1)
While loops begin by testing a condition (i <= length(vec)), so after that they execute the body (our if clause and subsequent assigning of value that meets our requirements(>=3 & <=4) to out). It then adds one to the iterator and evaluates the condition again and so forth.
vec <- sample(1:10, size = 20, replace = TRUE)
out <- c()
i <- 1
while(i <= length(vec)) {
if(vec[i] <= 4 & vec[i] >= 3) {
out <- c(out, vec[i])
}
i <- i + 1
}
out
[1] 4 3
Actually you don't need any while/if statements, you can simply apply
x[x >= 3 & x <= 4]
If you have to use while and if to make it, below is one option
k <- 1
res <- c()
while(k < length(x)) {
if (x[k] >= 3 & x[k] <= 4) {
res <- append(res,x[k])
}
k <- k + 1
}
I am in an intro to R course and the professor has not been much help. One of the questions on the latest homework has me stumped. The question is below, along with my answers so far.
8. [15 points] Given the following code,
#
# x <- rnorm(10)
#
# Do the following.
#
# (1) create a count vector named "count" of four elements and set each to 0 using the rep function.
# (2) using a for loop to process each value in the vector x, count how many times each of the following values occur in the vector x using an if statement.
# a. "value is between -1 and 1 inclusive"
# b. "value is between -2 and 2 inclusive, but not between -1 and 1",
# c. "value is between -3 and 3 inclusive, but not between -2 and -2", or
# d. "value is greater than 3 or less than -3".
# (3) print each of the four counts in the count vector using a while loop.
#
# For example, if the vector x contains the following ten values,
#
# 1.1478911 1.6183994 -2.3790632 -0.2566993 0.8923735
# -0.7523441 -0.7559083 0.9836396 1.0994189 2.5519972
#
# Then, the output should be as below.
#
# count[1] is 5
# count[2] is 3
# count[3] is 2
# count[4] is 0
x <- rnorm(10)
My answers:
(1) count <- c(rep(0,4))
(2)
for (count in x) {
if (x > -1 & x < 1) {
print(count[1])
}
I know there is something wrong with my code for part one but we haven't gone over anything like this in class and I have struggled to find a video for something like this. Please point me in the right direction and let me know what mistakes I have made, thanks so much!
You part one is correct. Maybe you can remove the initial c() from it.
x <- rnorm(10)
#Part 1
count <- rep(0,4)
#Part 2
for(i in x) {
if(i >= -1 && i <= 1)
count[1] <- count[1] + 1
else if(i >= -2 && i <= 2)
count[2] <- count[2] + 1
else if(i >= -3 & i <= 3)
count[3] <- count[3] + 1
else count[4] <- count[4] + 1
}
#Part 3
i <- 0
while (i < length(count)) {
i <- i + 1
print(sprintf('count[%d] is: %d', i, count[i]))
}
Note that there are better/efficient ways to do this but I think for the purpose of this exercise this is what your professor wants.
Each of the 4 slots in count is supposed to keep track of whether a value in x satisfies one of the 4 conditions listed (a. through d.).
If we were to speak it out loud, it'd go something like:
Look at element 1 in x (you can do that with x[1]). It's 1.1478911. This satisfies condition b., so add a 1 to the "b. counter", which is the second slot in count, or count[2].
Now look at element 2 in x (that's x[2])...(and so on, up to the last element in x).
To solve this task, you could just write out 10 statements, looking at each of the 10 elements in x separately, and update count on a case-by-case basis, but that is long and is hard to modify.
A for-loop is kind of like making a template for the spoken-out-loud part above. So instead of saying, "Ok, now we're on Element 3, let's see what the deal is", you can instead say, "Ok, now we're on Element i...", where i is just a temporary variable, a placeholder that only exists for the life of the for-loop. The i placeholder automatically takes on the value of the element in the vector we're iterating over.
If it's for (i in 1:3) then i will be 1, then 2, then 3.
If it's for (letter in c("a", "b", "c")), then letter will be "a", then "b", then "c".
So you can see that when you write for (count in x), that doesn't follow the rules of the for-loop. It's true that we'll want to update count at some point in the loop, but you've got it in the spot where our temporary placeholder is supposed to go. You can call that placeholder whatever you want, but i is common when looping over numbers, by convention.
Here's an example: the following code will start i at 1, and repeat the code inside the loop statement with new integers, until i gets to 10:
for (i in 1:10) {
print(paste("i is", i, "and the i'th value of x is", x[i]))
}
That should be enough to get you over the part you're stuck on.
A couple of additional hints:
f you want to know how many things are in a vector, such as x, you can use length(x) (try it, you will see the output is 10). So instead of doing: for(i in 1:10), you can swap out 10 for length(x).
count[3] <- count[3] + 1 adds 1 to whatever the current total is in the third element of count.
Good luck! Someone may post the answer to the whole problem, but if you want to work through each piece, I hope this is a good jump start for you.
I've been set a question on the Fibonacci Sequence and although I've been successful in doing the sequence, I haven't been as lucky summing the even terms up (i.e. 2nd, 4th, 6th... etc.) My code is below as well as the part of the question I am stuck on. Any guidance would be brilliant!
Question:
Write a function which will take as an input x and y and will return either the sum of the first x even Fibonacci numbers or the sum of even Fibonacci numbers less than y.
That means the user will be able to specify either x or y but not both.
You have to return a warning if someone uses both numbers (decide
on the message to return)
Code:
y <- 10
fibvals <- numeric(y)
fibvals[1] <- 1
fibvals[2] <- 1
for (i in 3:y) {
fibvals[i] <- fibvals[i-1]+fibvals[i-2]
if (i %% 2)
v<-sum(fibvals[i])
}
v
To get you started since this sounds like an exercise.
I would split your loop up into steps rather than do the summing within the loop with an if statement. Since you already have the sequence code working, you can just return what is asked for by the user. The missing function would probably help you out here
f <- function(x, y) {
if (missing(y)) {
warning('you must give y')
y <- 10
}
fibvals <- numeric(y)
fibvals[1] <- 1
fibvals[2] <- 1
for (i in 3:y) {
fibvals[i] <- fibvals[i-1]+fibvals[i-2]
}
evens <- fibvals %% 2 == 0
odds <- fibvals %% 2 != 0
if (missing(x)) {
return(sum(fibvals[evens]))
} else return(fibvals)
}
f(y = 20)
# [1] 3382
f(10)
# [1] 1 1 2 3 5 8 13 21 34 55
# Warning message:
# In f(10) : you must give y
I am relatively new to R and am a little bit confused about for loops.
I tried to repeat several steps within a for loop after a specified condition is hit. I tried to put the loop one step back, but have recognized that the loop keeps counting up and ignores my command. Here is a simple example to illustrate what I meant:
a <- 1:10
b <- rep(NA, 15)
fun <- function(){
i <- 1
for(i in 1:10){
b[i] <- a[i]
i <- i - 1 # This is the line I am talking about.
}
return(b)
}
fun()
[1] 1 2 3 4 5 6 7 8 9 10 NA NA NA NA NA
I have expected that this code would run forever and assigns only 1's. Is there a way how I could move one step back within for loops or would I have to do a completely different approach?
Thanks a lot in advance!
The way a for loop works is that if you have for (i in 1:10), first i is set to 1, and the body of the loop is executed. Then we go back to the top and i is set to 2, and the body of the loop is executed again. Basically, this loop:
for (x in 1:3) {
print(x^2)
}
is equivalent to this code:
x = 1
print(x^2)
x = 2
print(x^2)
x = 3
print(x^2)
So your attempt to roll the loop back a step by changing i doesn't work because the for loop doesn't actually monitor what i is, it just runs the body of the loop once for each element of the original 1:10 sequence.
If you want to sometimes repeat a step, you should use a while loop and increment i manually:
a <- 1:10
b <- rep(NA, 15)
i <- 1
while (i <= 10) {
b[i] <- a[i]
# Flip a coin, don't move on if it comes up tails
# Replace this test with the relevant condition you
# want to check for
if (sample(c(0, 1), 1) == 1) {
i <- i + 1
} else {
print(paste("Repeating with i =", i))
}
}
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))