Closed jasminacosta closed 1 month ago
open_goat_door <- function( game, a.pick )
{
game <- c("goat","car","goat")
a.pick <- 1
a.pick <- 2
doors <- c(1, 2, 3)
if ( game[ a.pick ] == "goat" )
{
opened.door <- doors[-c (this.game =="goat", my.initial.pick)]
}
if ( game[ a.pick ] == "car" )
{
opened.door <- doors[-c (this.game =="car", my.initial.pick)]
}
return(opened.door)
}
# test it
this.game <- create_game()
this.game
my.initial.pick <- select_door()
my.initial.pick
open_goat_door( this.game, my.initial.pick )
Just made some slight adjustments, but I am not sure if I am going in the right dircetion @lecy
TESTING:
1. > my.initial.pick
[1] 1
>
> open_goat_door( this.game, my.initial.pick )
[1] 2 3
2. > my.initial.pick
[1] 3
>
> open_goat_door( this.game, my.initial.pick )
[1] 2
3. > my.initial.pick
[1] 2
>
> open_goat_door( this.game, my.initial.pick )
[1] 3
Hi Jasmina! Welcome back.
You are on the right path. Recall that functions are input, output machines. You send it information through arguments, it processes the information and sends back a specific output (the return value).
Make sure you are sending information through arguments, not hard-coding it as static values inside the functions:
open_goat_door <- function( game, a.pick )
{
doors <- c(1, 2, 3) # belongs here
game <- c("goat","car","goat") # should be passed as argument
a.pick <- 1 # should be passed as argument
a.pick <- 2 # overwrites last line - redundant
I would suggest creating some cases to test your code in different scenarios:
# can only be door 3
this.game <- c( "goat", "car", "goat" )
my.initial.pick <- 1
open_goat_door( this.game, my.initial.pick )
# can only be door 1
this.game <- c( "goat", "car", "goat" )
my.initial.pick <- 3
open_goat_door( this.game, my.initial.pick )
# can be 1 or 3
this.game <- c( "goat", "car", "goat" )
my.initial.pick <- 2
open_goat_door( this.game, my.initial.pick )
open_goat_door( this.game, my.initial.pick )
open_goat_door( this.game, my.initial.pick )
Also check your logic here. If your first pick is a car, then eliminating both the car and your pick will be redundant.
More importantly, if your first pick is a goat then there is only one option you can return. If your first pick is the car, however, then you have two goat doors to select from. Since you can't return two doors from the function you will need to randomly pick one of the two goat doors in this case.
if ( game[ a.pick ] == "car" )
{
opened.door <- doors[-c (this.game =="car", my.initial.pick)]
}
@lecy
I am not quite understanding.
I tried this but it is a little inconsistent.
open_goat_door <- function( game, a.pick )
{
doors <- c(1, 2, 3)
# SCENARIO 1: contestant selects goat
a.pick <- 1
if ( game[ a.pick ] == "goat" )
{
opened.door <- doors[-c (this.game =="goat", my.initial.pick) ]
}
# SCENARIO 2: contestant selects car
if ( game[ a.pick ] == "car" )
{
opened.door <- doors[-c (this.game =="car", my.initial.pick) ]
}
return(opened.door)
}
# test it
this.game <- create_game()
this.game
my.initial.pick <- select_door()
my.initial.pick
open_goat_door( this.game, my.initial.pick )
Try this and see what you get:
this.game <- 2
my.initial.pick <- 2
open_goat_door( this.game, my.initial.pick )
Do you see the problem?
The other problem is your use of arguments. You can name temporary objects anything you want.
my.initial.pick <- select_door()
first.door <- select_door()
# etc
But inside functions you need to be very strict. You should only reference variables that are passed as arguments.
Note the issue with your arguments above:
# define argument here
function( game, a.pick )
# argument reference inside function
if ( game[ a.pick ] == "car" )
{
opened.door <- doors[-c (this.game =="car", my.initial.pick) ]
}
You should be using the argument (a.pick), not an object defined outside the function (my.initial.pick).
Try this and see what you get:
this.game <- 2 my.initial.pick <- 2 open_goat_door( this.game, my.initial.pick )
Do you see the problem?
Yup! The only output that it is giving is 1. How come that is? If we are assigning the number 2 to those variables.
The other problem is your use of arguments. You can name temporary objects anything you want.
my.initial.pick <- select_door() first.door <- select_door() # etc
But inside functions you need to be very strict. You should only reference variables that are passed as arguments.
Note the issue with your arguments above:
# define argument here function( game, a.pick ) # argument reference inside function if ( game[ a.pick ] == "car" ) { opened.door <- doors[-c (this.game =="car", my.initial.pick) ] }
You should be using the argument (a.pick), not an object defined outside the function (my.initial.pick).
In this case:
open_goat_door <- function( game, a.pick )
{
doors <- c(1, 2, 3)
# SCENARIO 1: contestant selects goat
if (game[a.pick] == "goat") {
opened.door <- sample(doors[game != "car" & doors != a.pick], 1)
}
# SCENARIO 2: contestant selects car
if (game[a.pick] == "car") {
opened.door <- sample(doors[game == "goat"], 1)
}
return(opened.door)
}
with the different scenarios we need to specify what the code does
Like in scenario 1 a.pick equals goat and game does not equal "car" and cannot be the same door as the first door a.pick? And sample randomizes that option?
Same thing applying to "car" but can only pick one goat door.
Is that what you mean to fix instead of using my.initial.pick?
@lecy
On the third question I just noticed it stopped doing it correctly and my step #4 is not working either
change_door <- function( stay=T, opened.door, a.pick )
{
if ( stay ){ final.pick <- a.pick }
else{ final.pick <- sample( x=c(1:3)[ - c( -a.pick, -opened.door ) ], size=1, replace=F ) }
return( final.pick )
}
# test it
opened.door <- open_goat_door( this.game, my.initial.pick )
change_door( stay=T,
opened.door=opened.door,
a.pick=my.initial.pick )
change_door( stay=F,
opened.door=opened.door,
a.pick=my.initial.pick )
my.final.pick <- change_door( stay=F,
opened.door=opened.door,
a.pick=my.initial.pick )
this.game
my.initial.pick
my.final.pick
For my.inital.pick I am not sure why the output is only 2 and for this game it is staying as
> this.game
[1] "goat" "goat" "car"
Is that what you mean to fix instead of using my.initial.pick?
# define argument here
function( game, a.pick )
# ORIGINAL
# argument reference inside function
if ( game[ a.pick ] == "car" )
{
opened.door <- doors[-c (this.game =="car", my.initial.pick) ]
}
# UPDATED:
# variable names inside the function should be consistent with arguments:
if ( game[ a.pick ] == "car" )
{
opened.door <- doors[-c ( game =="car", a.pick ) ]
}
Functions are recipes for generic cases. The arguments in functions are placeholders for whatever values are passed to them.
# setting up game using stochastic functions
# (the values will be different each time)
this.game <- create_game()
my.initial.pick <- select_door()
# setting up the game for unit testing
# (you are creating specific scenarios where you know
# what the answer should be)
this.game <- c( "goat", "car", "goat" )
my.initial.pick <- 1
# passing current objects to the next function
open_goat_door( game=this.game, a.pick=my.initial.pick )
# ARGUMENT ASSIGNMENT:
# what is actually happening with the arguments when calling a function:
# open_goat_door( game=this.game, a.pick=my.initial.pick )
game <- this.game
a.pick <- my.initial.pick
# the rest of the function should be able to run
# using only arguments, no other variables
The other way to illustrate this is by "breaking open" the function and running it as a linear script:
this.game <- c( "goat", "car", "goat" )
my.initial.pick <- 1
# open_goat_door <- function( game, a.pick )
# {
# argument assignment steps
game <- this.game
a.pick <- my.initial.pick
doors <- c(1, 2, 3)
# SCENARIO 1: contestant selects goat
if (game[a.pick] == "goat") {
opened.door <- sample(doors[game != "car" & doors != a.pick], 1)
}
# SCENARIO 2: contestant selects car
if (game[a.pick] == "car") {
opened.door <- sample(doors[game == "goat"], 1)
}
# return(opened.door)
# }
# print the final result
opened.door
It looks like you have corrected these in the last code you shared. It's an important principle, though. Always check to ensure your function code is only using variables that have been explicitly defined as arguments.
I also try to name objects in analysis scripts different than the arguments:
# generic versions - placeholders for ANY game setup or ANY pick
function( game, a.pick )
# concrete instances - they represent one specific game setup, one specific door
this.game <- create_game()
my.initial.pick <- select_door()
To identify the problem you need to break it into the smallest steps possible so you can isolate the behavior of each line of code.
For example, if you have two scenarios in your code they try testing them one at a time.
The only way you will know if the code is working is by using examples where you know what the answer should be so you can confirm the code is producing the right result.
# SCENARIO 1: contestant selects goat
# selects 1, opened door can only be door 3
game <- c( "goat", "car", "goat" )
a.pick <- 1
doors <- 1:3
opened.door <- doors[ - c( game =="goat", a.pick ) ]
opened.door
> [1] 2 3
# selects 3, opened door can only be door 1
game <- c( "goat", "car", "goat" )
a.pick <- 3
doors <- 1:3
opened.door <- doors[ - c( game =="goat", a.pick ) ]
opened.door
> [1] 2
You can see here that something is wrong with how you are making the selection. What are you intending this line of code to do?
doors[ - c( game =="goat", a.pick ) ]
You can break it down further by looking at the parts:
> game =="goat"
[1] TRUE FALSE TRUE
> a.pick
[1] 3
So what you have would look something like:
selector <- c( TRUE, FALSE, TRUE, 3 ) # a.pick=3
> - selector
[1] -1 0 -1 -3
doors <- 1:3
doors[ - selector ]
[1] 2
You can start to see why the code is not working. The selector does not make sense because you are combining a logical statement with numeric values. See the practice problems this week on implicit casting. You are also combining two statements with a concatenate c() operation instead of a logical statement (AND or OR operations).
You may need to review LOGICAL OPERATORS.
I would start by thinking about what the selector SHOULD look like:
# can't be the car
game != "car"
[1] TRUE FALSE TRUE
# can't be the opened door
doors != a.pick
[1] TRUE TRUE FALSE
# selector combines both criteria:
criteria.1 <- game != "car"
criteria.2 <- doors != a.pick
selector <- criteria.1 & criteria.2
selector
[1] TRUE FALSE FALSE
# should be 1
game <- c( "goat", "car", "goat" )
a.pick <- 3
doors <- 1:3
criteria.1 <- game != "car"
criteria.2 <- doors != a.pick
selector <- criteria.1 & criteria.2
opened.door <- doors[ selector ]
opened.door
[1] 1
# should be 3
game <- c( "goat", "car", "goat" )
a.pick <- 1
doors <- 1:3
criteria.1 <- game != "car"
criteria.2 <- doors != a.pick
selector <- criteria.1 & criteria.2
opened.door <- doors[ selector ]
opened.door
[1] 3
You can simplify the code once you know it's working, but I would start by splitting it into as many parts as possible so you know exactly what each line of code is doing.
Please make sure you are adding fences (three back ticks ``` ) around your code examples so they are readable:
```r
# SCENARIO 2: contestant selects car
if ( game[a.pick] == "car" ) {
opened.door <- sample( doors[ game == "goat" ], 1 )
}
Otherwise it looks like this and will give readers a headache:
# SCENARIO 2: contestant selects car
if ( game[a.pick] == "car" ) {
opened.door <- sample( doors[ game == "goat" ], 1 )
}
<br>
<br>
---
I added the code formatting to your questions above.
Please make sure you are adding fences around your code examples so they are readable:
```r # SCENARIO 2: contestant selects car if ( game[a.pick] == "car" ) { opened.door <- sample( doors[ game == "goat" ], 1 ) }
Otherwise it looks like this and will give readers a headache: # SCENARIO 2: contestant selects car if ( game[a.pick] == "car" ) { opened.door <- sample( doors[ game == "goat" ], 1 ) } I fixed your cases above.
@lecy I am sorry I am not quite following and am still confused.
```r # fences
code <- goes( here )
``` # fences
CODE WITH FENCES:
# SCENARIO 2: contestant selects car
if ( game[a.pick] == "car" ) {
opened.door <- sample( doors[ game == "goat" ], 1 )
}
CODE WITHOUT:
if ( game[a.pick] == "car" ) { opened.door <- sample( doors[ game == "goat" ], 1 ) }
Hi Professor Lecy!
I am having trouble with the 3rd step of this lab and would like some assistance since I have been stumped for the past couple of hours on trying to correlate the number to either being a goat or the car.
Thank you!