Watts-College / paf-514-template

https://watts-college.github.io/paf-514-template/
1 stars 0 forks source link

LAB-01: Question 3 #33

Closed jasminacosta closed 1 month ago

jasminacosta commented 9 months ago

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.

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" )
  {
     c("goat","car","goat")
  }

  if ( game[ a.pick ] == "car" )
  {
     c("goat","car","goat")
  }

  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 )

Thank you!

jasminacosta commented 9 months 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
lecy commented 8 months ago

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)]
  }
jasminacosta commented 8 months ago

@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 )
lecy commented 8 months ago

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?

lecy commented 8 months ago

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).

jasminacosta commented 8 months ago

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.

jasminacosta commented 8 months ago

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

jasminacosta commented 8 months ago

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" 
lecy commented 8 months ago

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()
lecy commented 8 months ago

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.

lecy commented 8 months ago

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. 
jasminacosta commented 8 months ago

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.

lecy commented 8 months ago
```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:


SCENARIO 2: contestant selects car

if ( game[a.pick] == "car" ) { opened.door <- sample( doors[ game == "goat" ], 1 ) }