Watts-College / paf-514-template

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

LAB-01: STEP 3 #4

Closed JJSpaeth closed 2 weeks ago

JJSpaeth commented 1 year ago

Hello everyone,

I've been facing some challenges with Step 3 of Lab 01. I've attempted many different approaches, but I've encountered issues where either a car door is being opened instead of a goat door, or the goat door that was initially picked is being opened. This has been quite frustrating.

Could anyone provide any tips or insights into what I might be doing wrong? I would greatly appreciate any assistance or guidance you can offer. Thank you in advance!

First just the dependecies:

library(dplyr)
create_game <- function( )
{
    a.game <- sample( x=c("goat","goat","car"), size=3, replace=F )
    return( a.game )
} 
select_door <- function( )
{
  doors <- c(1,2,3) 
  a.pick <- sample( x=doors, size=1, replace=F )
  return( a.pick )  # number between 1 and 3
}

Here is STEP 3 where I am having trouble:

SOLUTION 1:

open_goat_door <- function( game, a.pick )
{
  available_goat_doors <- which(seq_along(game) != a.pick & game != "car")
  opened.door <- sample(available_goat_doors, size = 1)
  return( opened.door ) # number between 1 and 3
}

SOLUTION 2:

open_goat_door <- function(game, a.pick) {
  this_game <- data.frame(door_number = 1:3, door_prize = game)
  unpicked_doors <- this_game %>% filter(door_number != a.pick)
  available_goat_doors <- unpicked_doors %>% filter(door_prize != "car") %>% pull(door_number)
  opened.door <- sample(available_goat_doors, size = 1)
  return(opened.door)
}

EDIT: SOLUTION 3 (Which also doesn't work)

open_goat_door <- function(game, a.pick) 
{
  doors <- c(1, 2, 3)
  car_door <- which(game == "car")
  unpicked_doors <- doors[doors != a.pick]
  available_goat_doors <- unpicked_doors[unpicked_doors != car_door]
  opened_door <- sample(available_goat_doors, size = 1)
  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 1 year ago

There can be two issues with solutions - your logic of how you are trying to solve the problem, and the code used to execute your logic.

It is really helpful to start with pseudocode - at a high level in plain English, what are the steps in your data recipe?

After you are perfectly clear on that, it is much easier to implement your code.

Can you walk us through what you want your code to do here?

open_goat_door <- function( game, a.pick )
{
  available_goat_doors <- which(seq_along(game) != a.pick & game != "car")
  opened.door <- sample(available_goat_doors, size = 1)
  return( opened.door ) # number between 1 and 3
}

What is your expected behavior in these cases? What are all of the allowable values the function can return in each case? How is the function ensuring it returns the correct value?

CASE 1:

my.game <- c("goat","car","goat")
my.pick <- 1
open_goat_door( game=my.game, pick=my.pick )

CASE 2:

my.game <- c("goat","car","goat")
my.pick <- 2
open_goat_door( game=my.game, pick=my.pick )
JJSpaeth commented 1 year ago
# The function is designed to work with two inputs: "game," which signifies the placements of cars and goats behind doors, and "pick," representing the door initially chosen by the contestant.

# The available goat doors are determined using the which() function. This involves:

# * Ensuring that the contestant's selection is excluded using seq_along(game) != pick.
# * Filtering out doors with cars behind them using game != "car".
# The resultant vector comprises doors that the contestant did not pick and do not have cars behind them.
# The sample() function is then employed to choose one door randomly from the available_goat_doors vector. This emulates the host's action of revealing a goat behind one of the doors.

# The chosen door is returned as "opened.door."
open_goat_door <- function( game, pick )
{
  available_goat_doors <- which(seq_along(game) != pick & game != "car")
  opened.door <- sample(available_goat_doors, size = 1)
  return( opened.door )
}

CASE 1: The expected and only possible selection is door 3. However, I am observing doors 1 and 2 also being chosen instead.

CASE 2: It appears to be functioning correctly as it exclusively selects doors 1 and 3.

EDIT: Despite my best efforts, I've encountered difficulties with every solution I've run against CASE 1. However, I am convinced that there is an effective way to phrase IF in a function to address this issue.

JJSpaeth commented 1 year ago

Okay I'm still stumped after many, many hours. All of these lines of code work perfectly until I put them all together in the function, then it will not give me the correct result if the picked door is a goat door.

# create a vector of doors
# get the door which has the car behind it
# remove the picked door from the list of doors
# remove the car door from the list of doors
# select one of the remaining doors.
open_goat_door <- function(game, pick) 
{
  doors <- c(1, 2, 3)
  car_door <- which(game == "car")
  unpicked_doors <- doors[doors != pick]
  available_goat_doors <- unpicked_doors[unpicked_doors != car_door]
  opened_door <- sample(available_goat_doors, size = 1)
  return(opened_door)
}
JJSpaeth commented 1 year ago

I've managed to solve the issue! Thank you for your assistance. I'm now progressing to the next question.

lecy commented 1 year ago

For the record, it is a challenging assignment so do not feel frustrated if it is taking several hours. It's the first assignment where you are combining logic and process.

The skill to focus on is the ability to translate from a plain English statement to computer code. In this case logical operators will be hugely helpful.

There are two parts to the problem. First, how to identify the correct position of the door.

game <- c("goat","car","goat")
pick <- 3
door <- c(1,2,3)

# cannot be the door with the car
game != "car"
[1]  TRUE FALSE  TRUE

# cannot be the door the current selection
door != pick
[1]  TRUE  TRUE FALSE

# now put them together
game != "car" & door != pick
[1]  TRUE FALSE FALSE

Note that it is important to pay attention to the congruence of your data types. When creating the condition for the car door, we are acting as the host that can see behind the doors. We need to use the game setup to specify the condition.

When we are eliminating the current selection we are referencing the door numbers (the door object) and the contestants selection is also a door number. So we need to use those objects to specify the condition.

Recall that compound logical statements can combine multiple object types (females in the control group). And recall that all conditions must be true for a case to evaluate as true. So the compound statement is combining (read from the top down):

  TRUE FALSE  TRUE  # game != "car"
+ TRUE  TRUE FALSE  # door != pick
= TRUE FALSE FALSE  # game != "car" & door != pick

We have no identified the correct position, but the function requires that we return an opened door (the door number specifically), not a logical vector. So we need to combine our logical statement with another object to get the correct return type.

Recall that logical vectors are sometimes called selector vectors because we can use them for filtering. Which would look like:

game[ game != "car" & door != pick ]
[1] "goat"

door[ game != "car" & door != pick ]
[1] 1

The second statement would return the correct object type (the door number) here.

That works for CASE1 when there’s a single solution, but for CASE2 where you have two goat doors remaining you will need to randomly select one.

lecy commented 1 year ago

Issues stay open otherwise they disappear.

JJSpaeth commented 1 year ago

I apologize, I did not know.

lecy commented 1 year ago

No worries!

gmendez9 commented 1 year ago

Hi Professor Lecy, I'm having a hard time determining If I have set up my code for step three correctly. I've been working on this since 10 AM, but am admittedly behind due to recovering from COVID and pink eye, so I offer my sincere apologies for posting late. Here's my code, any guidance is appreciated, thank you:


current.game <- c("goat","car", "goat")
pick <- 3 

open_goat_door <- function( game=current.game, a.pick=pick )
{

   doors <- c(1,2,3) # vector of doors
   available.doors <- doors[ doors != pick & game != "car" ] #  condition on doors not to include the picked choice or "cars" 
   opened.door <- sample(doors, size=1, replace=F)
   return( opened.door ) # number between 1 and 3

}
lecy commented 1 year ago

Make sure your argument names line up with the function code.

You name your argument a.pick then reference it as pick inside the function.

pick <- 3
###
a.pick=pick  # argument
doors != pick  # function code

You are assigning the value of pick to the placeholder a.pick here, so the function code should also be using a.pick (you can also use "pick" in both cases - just be consistent).

More importantly, you are currently sampling from all doors in the game.

sample( doors, size=1, replace=F )

But you have eliminated some options already. You should only be sampling from the remaining doors.

sample( available.doors, size=1, replace=F )
gmendez9 commented 1 year ago

Make sure your argument names line up with the function code.

You name your argument a.pick then reference it as pick inside the function.

pick <- 3
###
a.pick=pick  # argument
doors != pick  # function code

You are assigning the value of pick to the placeholder a.pick here, so the function code should also be using a.pick (you can also use "pick" in both cases - just be consistent).

More importantly, you are currently sampling from all doors in the game.

sample( doors, size=1, replace=F )

But you have eliminated some options already. You should only be sampling from the remaining doors.

sample( available.doors, size=1, replace=F )

Thank you.