Practicing loops - r

I'm trying to improve my function writing skills and I'm a little confused on the proper structure of functions. I've searched a ton of examples, but none are that clear to me. My aim is to run the #RUN over and over section in a for loop and build a function which allows me to control the number of times I can loop it.
Currently, I've got to this point:
set.seed(123)
#Start but setting the conditions and being the Win Lose counters
Count_Win_Hunt=0
Count_Win_Moose=0
#RUN over and over
Hunter=1
Moose=7
win=0
while(win != 1){ a = sample(1:6, 1) # dice roll
if( a<= 4) {Moose = Moose+a} else{Hunter = Hunter+a}
if( Hunter >= Moose ) { Count_Win_Hunt = Count_Win_Hunt +1 } else if( Moose >= 12) {Count_Win_Moose = Count_Win_Moose + 1}
if( Hunter >= Moose || Moose >= 12 ) {win = win+1} else {
#if not condition not meet roll again
a = sample(1:6, 1) # dice roll
if( a<= 4) {Moose = Moose+a} else{ Hunter = Hunter+a}}}
# calculated the average win rates
paste0( round(Count_Win_Hunt/(Count_Win_Hunt+Count_Win_Moose),4)*100,"%"," of the time the Hunter won")
paste0( round(Count_Win_Moose/(Count_Win_Hunt+Count_Win_Moose),4)*100,"%"," of the time the Moose won")

Besides my general problems with your question (please be more specific as to your actual problem) your for-loops have a wrong syntax. They should be like this:
for (val in sequence)
{
statement
}
So applied to your function they should look like this:
for (val in c(1:4))
{
probability + (hunter,goose+val,num+1)
}
for (val in c(5:6))
{
probability + (hunter,goose+val,num+1)
print probability
}
However the are not only syntactically wrong, also their content seems to be wrong.
E.g. in your second for-loop, the goose steps forward even though it should be the hunter. Also these are not two for-loops but should be an if-statement like this:
if (val <= 4) {
probability + (hunter,goose+val,num+1)
}
else {
probability + (hunter+val,goose,num+1)
}
Finally the whole structure of your function seems strange (and has misleadingly named variables). Shouldn`t it be something like this:
dice_roll <- function(hunter,goose, win){
# While to check for winning condition
while(win != 1){
dice_roll = sample(1:6, 1) # simulate dice roll
# If statement depending on dice roll, increasing value of hunter or goose by dice roll
# Change win condition
If(hunter >= goose){
win <- 1
}
}
dice_roll(1,7,0)

Related

confunsion in create if in R

I have a question how to make a IF
for (i in 1:12){
for (j in 1:12) {
if (i != j) {
var = x + b
}
else{ }
}}
"else" I need that when they are equal to continue with j + 1 example: if i = 4 and j = 4 then continue with j = 5 and continue counting until the end of j and continue the process of when i! = j
I think you don't understand what is going on in your code or you don't understand what for loops do. One "trick" you can do is to actually print what happens in your for loops so that you will have one idea of what is going on. You could also do this with a piece of paper.
As they already pointed you out, you don't need the else because the for already takes care of this.
for (i in 1:12){
print("-------------------------------")
valueI <- paste0("my i value is ",i)
print(valueI)
for (j in 1:12) {
valueJ <- paste0("my j value is ",j)
print(valueJ)
if (i != j) {
#var = x + b
diff <- paste0(i, " is different than ", j)
print(diff)
}
else{
}
}
}
This code is the same as yours and will generate a log that explains you what happens step from step, you could also use a debugger but seeing your struggles, better use this for now. What are you trying to calculate? I feel like you want to calculate the power of something...

Dealing with recursion depth limitation in R

The algorithm is from https://www.math.upenn.edu/~wilf/eastwest.pdf page 16 RandomKSubsets
RandomKSubsets = function(n, k){
if (n<0 | k<0 | k<n){
return()
}
else {
if (n==0 && k==0){
return(c())
}
else {
rno = runif(1)
if (rno < n/k){
east = RandomKSubsets(n-1,k-1)
return (c(east, k))
}
else{
west = RandomKSubsets(n,k-1)
return(west)
}
}
}
}
Running the program with k=4000 and n=1200 I run into recursion depth limit. I tried options(expressions=500000) but it's not enough for the algorithm. How can I run this code for my variables?
This is close to tail recursion: the only recursive calls are in the return statements. This blog: http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html describes how to change such functions into loops. I followed the mostly mechanical process described there, and came up with this version:
RandomKSubsetsLoop = function(n, k) {
acc <- NULL
while (TRUE) {
if (n<0 | k<0 | k<n){
return(acc)
}
else {
if (n==0 && k==0){
return(acc)
}
else {
rno = runif(1)
if (rno < n/k){
acc <- c(k, acc)
k <- k - 1
n <- n - 1
next
}
else{
k <- k - 1
next
}
}
}
break
}
}
I haven't tested it extensively, but it produces the same result as the original in this test:
set.seed(1)
RandomKSubsets(5, 10)
# [1] 1 3 6 9 10
set.seed(1)
RandomKSubsetsLoop(5, 10)
# [1] 1 3 6 9 10
You'll probably want to do more extensive testing, and read the blog to make sure I've done things as it describes.
By the way, there are other algorithms to do this sampling, e.g. the one described in
AUTHOR="McLeod, A.I. and Bellhouse, D.R. ",
YEAR = 1983,
TITLE="A convenient algorithm for drawing a simple random sample",
JOURNAL="Applied Statistics",
VOLUME="32",
PAGES="182-184"
That one is based on a loop by design, and has the advantage that you don't need to know the population size (k in your notation) in advance: you just keep updating your sample until there are no more items to process.

Trying to create a dice game in R but function not running

I have a code to make a game where a person rolls the die 4 times and if a roll lands on 6, they win. However, I'm running the code but it doesn't produce an output.
game<-function (n=4){
count=0
ceiling(6*runif(1))
for(i in 1:n){
if(ceiling(6*runif(1))==6){
count=1
}
else(
count=0
)
if(count=1){
print("Win")}
else{
print("Lose")
}
}
}
You can in fact do it much simpler using ifelse to vectorise the if statement. Also, you can avoid intermediate variables (e.g. count):
game<-function (n=4){
ifelse(6 %in% sample(6, n, replace = TRUE), "Win", "Lose")
}
I would suggest using any to see if any roll equals to 6, then use return to report the value.
game <- function(n = 4){
if (any(ceiling(6 * runif(n)) == 6L)){
return("Win")
} else {
return("Lose")
}
}

Error message in Bubble sort code in R language

I did some programming work on R language to do the bubble sort. Sometimes it works perfectly without any error message, but sometimes, it shows "Error in if (x[i] > x[i + 1]) { : argument is of length zero". Can any one help me check whats wrong with it? I have attached my code below
example <- function(x) {
n <- length(x)
repeat {
hasChanged <- FALSE
n <- n - 1
for(i in 1:n) {
if ( x[i] > x[i+1] ) {
temp <- x[i]
x[i] <- x[i+1]
x[i+1] <- temp
hasChanged <- TRUE
cat("The current Vector is", x ,"\n")
}
}
if ( !hasChanged ) break;
}
}
x <-sample(1:10,5)
cat("The original Vector is", x ,"\n")
example(x)
The error occurs because you are iteratively decreasing n. Depending on the original vector's order (or lack thereof), n can reach the value of 1 after the last change. In that case, a further reduction of n in the next iteration step addresses the value x[0], which is undefined.
With a minimal correction your code will work properly, without giving error messages. Try to replace the line
if ( !hasChanged ) break;
with
if ( !hasChanged | n==1 ) break
Basically you have two termination criteria: Either nothing has been changed in the previous iteration or n is equal to one. In both cases, a further iteration won't change the vector since it is already ordered.
By the way, in R programming you don't need a semicolon at the end of a command. It is tolerated/ignored by the interpreter, but it clutters the code and is not considered good programming style.
Hope this helps.

How to get equivalent to R ifelse functionality, using logical operators

Please can anyone advise how I can turn the following statement into one that will do the same thing but NOT using ifelse please?
<-ifelse(y>=50, 0.2*x+0.8*y, ifelse(y<50 & x>70, y+10, ifelse(y<50 & x<70, y)))
x=80
y=60
So I the final code should give an answer of 64 - selecting the first condition. I will then test it to ensure the other 3 conditions give the correct result for varying values of x and y
Thanks a lot.
This should work:
finalmark <- (x * 0.2 + y * 0.8) * (y >= 50) + (y + 10 * (x > 70)) * (y < 50)
Something like this?
if(y>=50){
0.2*x+0.8*y
}else{
if(y<50 & x>70){
y+10
}else{
if(y<50 & x<70){
y
}else{
"OMG I did not expect this scenario"
}
}
}
try: y=45; x=70 to see why I have the last condition.
If y is a number then, once you've tested for y > = 50 then y must be less than 50 so don't keep testing for that. Similarly, once you've found x > 70 then you don't need the last ifelse. You don't have a return for x = 70. My guess is that you want to test for a <= or >= situation there.
ifelse(y>=50, 0.2*x+0.8*y, ifelse(x>70, y+10, y))
in scalar that's
if(y >= 50){
0.2*x+0.8*y
}else if(x > 70){
y+10
}else y
Given you seem to be having a hard time in general writing the logic I suggest you post a more complete question. It's possible (probable) that you're doing something here that you really don't want to do.
There are several approaches you can take. Below are a few examples of building a function 'f', so that 'f(x,y)' meets your criteria listed in the question using logic other than 'ifelse' statements.
Note: I'm also adding in one amendment to the original post, since 'x=70' would break the logic. I'm adding 'x>=70' to the second criterion.
Option 1: Use a standard 'if / else if / else' logic block. Personally, I like this option, because it's easily readable.
f <- function(x, y){
if (y>= 50){
return(0.2*x+0.8*y)
} else if (y < 50 & x >= 70){
return(y+10)
} else {
return(y)
}
}
Option 2: Combine your two logical tests (there are really only two) into a string, and use a switch. Note that the final and unnamed option is treated as an 'else'.
f <- function(x, y){
return(
switch(paste(x >= 70, y >= 50, sep=""),
TRUEFALSE = y + 10,
FALSEFALSE = y,
0.2*x+0.8*y
)
)
}
Option 3: Order your 'if' statements to reduce logical comparisons. This is the sort of thing to do if you have a large data set or very limited memory. This is slightly harder to troubleshoot, since you have to read the whole block to fully understand it. Option 1 is better if you don't have memory or cycle limitations.
f <- function(x, y){
if (y >= 50){
return(0.2*x+0.8*y)
} else {
if (x >=70){
return(y+10)
} else {
return(y)
}
}
}
There are other options, but these are the simplest that come readily to mind.

Resources