My yathzee function stucks in the if statement - r

I just started to learn R and I am asked to write a function for a simplified Yahtzee game. The objective of the game is to score points by rolling five dice to make certain combinations.
There are 6 different categories:
If all five dice the same, the player gets 50 points (Yahtzee).
Five sequential dices (i.e, all unique dices) yields 40 points (Straight)
Three of one number and two of another yields 25 points.
If four dices are the same, it gives a score of the sum of all dices.
If three dices are the same, it gives a score of the sum of all dices.
Any remaining condition gives a score of the sum of all dices.
Here is how I have tried (Although I think that the last three categories can be condensed into the same logical test):
yahtzee <- function(){
dices <- sample(1:6,5,TRUE)
t <- table(dices)
t.x <- unname(t)
if(length(unique(dices) == 1)){
print("Yahtzee")
score <- 50
}
else if(dices == c(1,2,3,4,5) | dices == c(2,3,4,5,6)){
print("Straight")
score <- 40
}
else if(t.x[1] == 3 & t.x[2] == 2 | t.x[1] == 2 & t.x[2] == 3){
print("Full House")
score <- 25
}
else if(t.x[1] == 4 & t.x[2] == 1 | t.x[1] == 1 & t.x[2] == 4){
print("Four Of A Kind")
score <- sum(dices)
}
else if(t.x[1] == 3 & t.x[2] == 1 & t.x[3] == 1 | t.x[1] == 1 & t.x[2] == 3 & t.x[3] == 1 | t.x[1] == 1 & t.x[2] == 1 & t.x[3] == 3){
print("Three Of A Kind")
score <- sum(dices)
}
else{
print("Chance")
score <- sum(dices)
}
print(dices)
print(score)
}
When I run the function, I always earn 50 points and 'Yahtzee' occurs no matter what the dice combination is. My code does not go over the remaining else if statements or somehow stucks in the first line. How can I fix it?

You basically just had a couple parens mismatched. I don't think you need t.x and can just leverage properties of t combined with the any function. Here's how I'd rewrite your function:
yahtzee <- function(){
dices <- sample(1:6,5,TRUE)
t <- table(dices)
if(length(unique(dices)) == 1){
print("Yahtzee")
score <- 50
}
else if(length(unique(dices)) == 5){
print("Straight")
score <- 40
}
else if(any(t == 3) * any(t == 2)){
print("Full House")
score <- 25
}
else if(any(t == 4)){
print("Four Of A Kind")
score <- sum(dices)
}
else if(any(t == 3)){
print("Three Of A Kind")
score <- sum(dices)
}
else{
print("Chance")
score <- sum(dices)
}
print(dices)
print(score)
}
yahtzee()

yahtzee <- function () {
dices <- sample(1:6, 5, TRUE)
if( length(unique(dices)) == 1 ) {
print("Yahtzee")
score <- 50
} else if ( length(unique(dices)) == 5 ) {
print("Straight")
score <- 40
} else if ( length(unique(dices)) == 2 && length(which(dices ==
unique(dices)[1])) == 2 ||
length(which(dices == unique(dices)[2])) == 2 ) {
print("Full House")
score <- 25
} else if ( length(unique(dices)) == 2 && length(which(dices ==
unique(dices)[1])) == 1 ||
length(which(dices == unique(dices)[2])) == 1 ) {
print("Four Of A Kind")
score <- sum(dices)
} else if ( length(unique(dices)) == 3 && length(which(dices ==
unique(dices)[1])) == 3 ||
length(which(dices == unique(dices)[2])) == 3 ||
length(which(dices == unique(dices)[3])) == 3 ) {
print("Three Of A Kind")
score <- sum(dices)
} else {
print("Chance")
score <- sum(dices)
}
print(dices)
print(score)
}

Related

Creating a random play function in R

I want to create a gambling game that does the following:
It is a lottery, which asks for 5 numbers comprised between 01 and 43 and an additional number comprised between 01 and 16; the idea is that I give my 6 numbers and it tells me if I won or not.
To do so, use this code
Lotery = function(a,b,c,d,e,f){
NumeroAleatorio <- matrix(1:6, ncol = 6)
NumeroAleatorio[1] <- sample (1:43, 1, replace= FALSE)
for (i in 2:6) {
if(i!=6){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
if(i == 2){
while(NumeroAleatorio[i] == NumeroAleatorio[1] ){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}else{
if(i == 3 ){
while(NumeroAleatorio[i] == NumeroAleatorio[1] || NumeroAleatorio[i] == NumeroAleatorio[2]){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}else{
if(i == 4 ){
while(NumeroAleatorio[i] == NumeroAleatorio[1] || NumeroAleatorio[i] == NumeroAleatorio[2] || NumeroAleatorio[i] == NumeroAleatorio[3]){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}else{
if(i == 5 ){
while(NumeroAleatorio[i] == NumeroAleatorio[1] || NumeroAleatorio[i] == NumeroAleatorio[2] || NumeroAleatorio[i] == NumeroAleatorio[3] || NumeroAleatorio[i] == NumeroAleatorio[4] ){
NumeroAleatorio[i] <- sample (1:43, 1, replace= FALSE)
}
}
}
}
}
}else{
NumeroAleatorio[6] <- sample (1:16, 1, replace= FALSE)
}
}
ContA<-0
ContB<-0
ContC<-0
ContD<-0
ContE<-0
ContF<-0
for(p in 1:6){
if(NumeroAleatorio[p] == a){
ContA<-ContA+1
}
if(NumeroAleatorio[p] == b){
ContB<-ContB+1
}
if(NumeroAleatorio[p] == c){
ContC<-ContC+1
}
if(NumeroAleatorio[p] == d){
ContD<-ContD+1
}
if(NumeroAleatorio[p] == e){
ContE<-ContE+1
}
if(NumeroAleatorio[p] == f){
ContF<-ContF+1
}
}
if(ContA==0 || ContB==0 || ContC==0 || ContD==0 || ContE==0 || ContF==0){
return(data.frame("Resultado", NumeroAleatorio, "Numero escogido", a, b, c, d, e, f, "No Ganaste"))
}else{
return(data.frame("Resultado", NumeroAleatorio, "Numero escogido", a, b, c, d, e, f, "Ganaste"))
}
}
Lotery(20,15,3,45,9,8)
It seems to work, but I want to know if I can make things simpler because I think the code is too long.
I may not be following your code, but it looks like you randomly select 6 numbers and compare them to the numbers submitted. None of the first 5 should match, but the 6th can match one of the first 5. If that is correct then this will generate the random 6 numbers:
NumeroAleatorio <- c(sample.int(43, 5, replace=FALSE), sample.int(16, 1))
To compare this to the submitted values, just use
NumeroAleatorio == comp
All FALSE indicates no matches. Any TRUE values indicate a match at that position.

If loop - Argument is of length zero - error

I do have the following code for a loop, which basically only updates the column "decay rate" based on whether or not the column "RPK_cap" is higher than a certain threshold which is exogenously given(in scenario 1 it is 1200, in Scenario 2 it is 1300 etc). If that is the case than I want to decrease the decay rate by multiplying it my 0.9. This is done for all countries (column: iso) and years(column: year) which are in the data.table. When I am using scenario 1 data the column "RPK_cap" will be filled with scenario 1 data and if I choose scenario 2 the column "RPK_cap" will be filled with scenario 2 data respectively.
And my problem is the following:
This loop works ONLY for scenario 1.
If I am using scenario 2 I get the error message:
"Error in if (price_el_int_aviation_RPK$RPK_Cap[price_el_int_aviation_RPK$iso == :
argument is of length zero"
I really tried a lot and I just donĀ“t know what the problem is here. Does anyone know what the problem is?
This is the data.table
data.table_example
if (scenario == "1") {
for (j in unique(price_el_int_aviation_RPK$iso)) {
for (i in unique(price_el_int_aviation_RPK$year[price_el_int_aviation_RPK$iso == j])) {
if (price_el_int_aviation_RPK$RPK_cap[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year == i] > 1200) {
price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] <- price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] * 0.90
}
}
}
} else if (scenario == "2"){
for (j in unique(price_el_int_aviation_RPK$iso)) {
for (i in unique(price_el_int_aviation_RPK$year[price_el_int_aviation_RPK$iso == j])) {
if (price_el_int_aviation_RPK$RPK_Cap[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year == i] > 1300) {
price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] <- price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] * 0.95
}
}
}
} else if (scenario == "3"){
for (j in unique(price_el_int_aviation_RPK$iso)) {
for (i in unique(price_el_int_aviation_RPK$year[price_el_int_aviation_RPK$iso == j])) {
if (price_el_int_aviation_RPK$RPK_Cap[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year == i] > 1400) {
price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] <- price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] * 0.95
}
}
}
} else if (scenario == "4"){
for (j in unique(price_el_int_aviation_RPK$iso)) {
for (i in unique(price_el_int_aviation_RPK$year[price_el_int_aviation_RPK$iso == j])) {
if (price_el_int_aviation_RPK$RPK_Cap[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year == i] > 1500) {
price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] <- price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] * 0.95
}
}
}
} else if (scenario == "5"){
for (j in unique(price_el_int_aviation_RPK$iso)) {
for (i in unique(price_el_int_aviation_RPK$year[price_el_int_aviation_RPK$iso == j])) {
if (price_el_int_aviation_RPK$RPK_Cap[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year == i] > 1600) {
price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] <- price_el_int_aviation_RPK$decay_rate[price_el_int_aviation_RPK$iso == j & price_el_int_aviation_RPK$year >= i] * 0.99
}
}
}
}else{}
It's hard to answer in specifics because we cannot see your data.
But the error you see
"Error in if (price_el_int_aviation_RPK$RPK_Cap[price_el_int_aviation_RPK$iso == : argument is of length zero"
is because price_el_int_aviation_RPK$iso is of length zero - it's a vector without anything in it!
Here's a minimal example of the problem
# Create a vector of length zero
a <- c()
# Prove it's length is zero
length(a)
# [1] 0
# This is a minimal example of what's going wrong with scenario 2 in your script
if(a == 2) { print("it works") }
Error in if (a == 2) if (a == 2) { : argument is of length zero

Trying to insert new column which is combination of two different columns i.e race and ethnicity

For demographic analysis of state I want to compare race and ethnicity and want to find out how many people are hispanic, non-hispanic and others
hsg.ppl2$XYZ <- for(i in 1:100)
if (hsg.ppl2$HISP[i] == 1 & hsg.ppl2$RAC1P[i] == 1) { "NHWht" } else if (hsg.ppl2$HISP[i] == 1 & hsg.ppl2$RAC1P[i] == 2) { "NHBlack" } else
if (hsg.ppl2$HISP[i] == 1 & (hsg.ppl2$RAC1P[i] == 6 | hsg.ppl2$RAC1P[i] == 7)) {"NHAsian" } else
if (hsg.ppl2$HISP[i] == 1 & (hsg.ppl2$RAC1P[i] == 3 | hsg.ppl2$RAC1P[i] == 4 |hsg.ppl2$RAC1P[i] == 5 | hsg.ppl2$RAC1P[i] == 8 | hsg.ppl2$RAC1P[i] == 9)) {"NHOther" } else
if (hsg.ppl2$HISP[i] >= 1) {"HISP"}
else {NA}
I am getting XYZ actual column as null
XYZ <- NULL
for(i in 1:100) {
if (hsg.ppl2$HISP[i] == 1 & hsg.ppl2$RAC1P[i] == 1) { XYZ[i] <- "NHWht" } else if (hsg.ppl2$HISP[i] == 1 & hsg.ppl2$RAC1P[i] == 2) { XYZ[i] <- "NHBlack" } else
if (hsg.ppl2$HISP[i] == 1 & (hsg.ppl2$RAC1P[i] == 6 | hsg.ppl2$RAC1P[i] == 7)) {XYZ[i] <- "NHAsian" } else
if (hsg.ppl2$HISP[i] == 1 & (hsg.ppl2$RAC1P[i] == 3 | hsg.ppl2$RAC1P[i] == 4 |hsg.ppl2$RAC1P[i] == 5 | hsg.ppl2$RAC1P[i] == 8 | hsg.ppl2$RAC1P[i] == 9)) {XYZ[i] <- "NHOther" } else
if (hsg.ppl2$HISP[i] >= 1) {XYZ[i] <- "HISP"}
else {XYZ[i] <- NA}
}
hsg.ppl2$XYZ <- XYZ

Loop returns error: 'argument is of length zero'

i <- 2
j <- 0
for (i in 2:1000) {
if(return.prime(i)){j = j + 1}
i = i + 1
}
I want to check how many prime numbers there are in 1 to 1000 using my own function return.prime which returns TRUE when the number input is a prime and FALSE when the number input is not prime. The return.prime function is the function below and it is correct.
return.prime <- function(d){
if(d ==1 ){print(FALSE)}
if (d == 2){
print(TRUE)
}
if(d !=2 && d!=1){
if(any(d %% (2:(d-1)) == rep(0,d-2))==TRUE){
print(FALSE)}
else
print(TRUE)
}
}
The problem is when I run my program it says:
[1] TRUE
Error in if (return.prime(i)) { : argument is of length zero
I do not know what causes the length zero.
R doesn't work that way. You're just having the function print the word "TRUE" or "FALSE". Instead, you need to ?return TRUE or FALSE. Consider:
return.prime <- function(d){
if(d==1){ return(FALSE) }
if(d==2){ return(TRUE) }
if(d !=2 && d!=1){
if(any(d %% (2:(d-1)) == rep(0,d-2))==TRUE){
return(FALSE)
} else{
return(TRUE)
}
}
}
i <- 2
j <- 0
for (i in 2:1000) {
if(return.prime(i)){j = j + 1}
i = i + 1
}
j # [1] 168

Calculate the days between dates by hand

I suspect R has a built-in method to do this, but I'm new to programming and was trying to figure out how to calculate the days between dates by hand as practice. Here is my code:
isLeapYear <- function(year) {
if (year %% 400 == 0) {
return (TRUE)
}
if (year %% 100 == 0) {
return (FALSE)
}
if (year %% 4 == 0) {
return (TRUE)
}
else{ return (FALSE)}
}
daysInMonth <- function(year,month){
if (month == 1 | month == 3| month == 5 | month == 7 | month == 8 | month == 10 | month == 12) {
return (31)
}
else if (month == 2){
if (isLeapYear(year)){
return (29)
}
else {return (28)}
}
else {return (30)}
}
nextDay <- function(year, month, day){
if (day < daysInMonth(year,month)){
return (list(year, month, day + 1))
}
else{
if (month == 12){
return (list(year + 1, 1, 1))
}
else{return (list(year, month + 1, 1))}
}
}
dateIsBefore <- function(year1, month1, day1, year2, month2, day2){
if (year1 < year2){
return(TRUE)
}
if (year1 == year2){
if (month1 < month2){
return(TRUE)
}
if (month1 == month2){
return (day1 < day2)
}
}
return (FALSE)
}
daysBetweenDates <- function(year1, month1, day1, year2, month2, day2){
days <- 0
while (dateIsBefore(year1, month1, day1, year2, month2, day2)){
result = nextDay(year1,month1,day1)
year1 = result[1]
month1 = result[2]
day1 = result[3]
days = days+1
}
return (days)
}
I wrote a code to determine the number of day between two dates using python. I'm now trying to convert it to R for another assignment I'm doing. When I run each indiviual function, they seem to work fine. When I call daysBetweenDates(2012,1,1,2012,2,28) I get the following error:
Error in day + 1 : non-numeric argument to binary operator
> as.Date("2012/02/28") - as.Date("2012/01/01")
# Time difference of 58 days
> as.Date("2012/01/01") - as.Date("2012/02/28")
# Time difference of -58 days
Improvement suggested by Dirk in comments on just to get the number as a difference using as.integer(), here it is
> as.integer(as.Date("2012/02/28") - as.Date("2012/01/01"))
# [1] 58
> as.integer(as.Date("2012/01/01") - as.Date("2012/02/28"))
# [1] -58
The reason your code isn't working is because of the way you are assigning the three elements of result to year1, month1, and day1 in the while loop in your daysBetweenDates function. If you change it like this it should work:
daysBetweenDates <- function(year1, month1, day1, year2, month2, day2){
days <- 0
while (dateIsBefore(year1, month1, day1, year2, month2, day2)){
result = nextDay(year1,month1,day1)
year1 = result[[1]]
month1 = result[[2]]
day1 = result[[3]]
days = days + 1
}
return (days)
}
If you do return <- list(2012, 1, 1) and then return[1] and compare that with return[[1]] you should see the difference. This is common mistake when using lists. You might want to take a look at this for an excellent discussion of subsetting: http://adv-r.had.co.nz/Subsetting.html.

Resources