Monty Hall Problem – Test Script

A quick script knocked up to test the theories in the Monty Hall Problem. Defaults to run 1000 tests, but this can be adjusted using the $NumberOfTests parameter.

A second parameter controls the choice of whether to switch doors, or stick with the same one. This is the $Choice parameter and can accept the following options. The default option is LetFateDecide.

  • StickWithDoor
  • SwitchDoor
  • LetFateDecide

Examples

Runs 1000 instances of the Monty Hall Problem

./Test-MontyHallProblem.ps1

Runs 1000 instances of the Monty Hall Problem where the door gets switched every time

./Test-MontyHallProblem.ps1 -Choice 'SwitchDoor'

Runs 5000 instances of the Monty Hall Problem, sticking with the same door everytime.

./Test-MontyHallProblem.ps1 -NumberOfTests 5000 -Choice 'StickWithDoor'


Full ScriptTest-MontyHallProblem.ps1

[CmdLetBinding()]
param
(
    [Parameter()]
    [int]$NumberOfTests = 1000,

    [Parameter()]
    [ValidateSet('StickWithDoor','SwitchDoor','LetFateDecide')]
    [string]$Choice = 'LetFateDecide'
)

$gameShowClass = @"
public class GameShow
{
    public GameShow()
    {
        this.Door1 = "Goat";
        this.Door2 = "Goat";
        this.Door3 = "Goat";
    }

    public string Door1 { get; set; }
    public string Door2 { get; set; }
    public string Door3 { get; set; }
}
"@
Add-Type -TypeDefinition $gameShowClass

$resultsClass = @"
public class GameShowResults
{
    public int TestNumber { get; set; }
    public string FirstChoice { get; set; }
    public string DoorRemoved { get; set; }
    public string FinalChoice { get; set; }
    public string Decision { get; set; }
    public string Prize { get; set; }
}
"@
Add-Type -TypeDefinition $resultsClass

function New-GameShow
{
    $gameShow = New-Object -TypeName 'GameShow'

    $prizeDoor = Get-Random -Minimum 1 -Maximum 4

    switch ($prizeDoor)
    {
        1 { $gameShow.Door1 = "Car" }
        2 { $gameShow.Door2 = "Car" }
        3 { $gameShow.Door3 = "Car" }
    }

    Write-Output $gameShow
}

function Test-MontyHallProblem
{
    param
    (
        [int]$TestNumber,
        [string]$Choice
    )

    $GameShow = New-GameShow
    $Results = New-Object -TypeName GameShowResults

    $Results.TestNumber = $TestNumber

    $PrizeDoor = 1..3 | ForEach-Object {
        $Property = "Door$($_)"
        if ($GameShow.$Property -eq 'Car') { $_ }
    }

    $FirstChoice = Get-Random -Minimum 1 -Maximum 4
    $Results.FirstChoice = "Door$($FirstChoice)"

    $RemainingDoors = 1..3 | Where { $_ -ne $FirstChoice }

    $DoorRemoved = Get-Random -InputObject ($RemainingDoors | Where { $_ -ne $PrizeDoor })
    $Results.DoorRemoved = "Door$($DoorRemoved)"

    switch ($Choice)
    {
        'LetFateDecide'
        {
            $FinalChoice = Get-Random -InputObject (1..3 | Where { $_ -ne $DoorRemoved })
        }

        'StickWithDoor'
        {
            $FinalChoice = $FirstChoice
        }

        'SwitchDoor'
        {
            $FinalChoice = 1..3 | Where { $_ -ne $DoorRemoved -and $_ -ne $FirstChoice }
        }
    }

    $Results.FinalChoice = "Door$($FinalChoice)"

    if ($FirstChoice -eq $FinalChoice)
    {
        $Results.Decision = 'Stick'
    }
    else
    {
        $Results.Decision = 'Switch'
    }

    $FinalDoor = "Door$($FinalChoice)"

    $Results.Prize = $GameShow.$FinalDoor

    Write-Output $Results
}

Clear-Host

$ResultsArray = @()

$Counter = 1

1..$NumberOfTests | ForEach-Object {
    
    Write-Progress -Activity 'Testing the Monty Hall Problem' 
                   -Status "Running Test Number $($_)" 
                   -PercentComplete (($Counter / $NumberOfTests) * 100)

    $ResultsArray += Test-MontyHallProblem -TestNumber $Counter -Choice $Choice

    $Counter++
}

$NumberOfSticks = ($ResultsArray | Where { $_.Decision -eq 'Stick' }).Count
$NumberOfStickWins = ($ResultsArray | Where { $_.Decision -eq 'Stick' -and $_.Prize -eq 'Car' }).Count
$NumberOfSwitches = ($ResultsArray | Where { $_.Decision -eq 'Switch' }).Count
$NumberOfSwitchWins = ($ResultsArray | Where { $_.Decision -eq 'Switch' -and $_.Prize -eq 'Car' }).Count

$global:TestResults = $null
$global:TestResults = $ResultsArray

Write-Host
Write-Host "Monty Hall Problem Tester" -ForegroundColor Yellow
Write-Host "----- ---- ------- ------" -ForegroundColor White
Write-Host
Write-Host "Number of Tests Run: " -ForegroundColor Yellow -NoNewline
Write-Host $NumberOfTests -ForegroundColor White

if ($Choice -match "(LetFateDecide|StickWithDoor)")
{
    Write-Host
    Write-Host "Number of Times Staying with the Same Door: " -ForegroundColor Yellow -NoNewline
    Write-Host ("$($NumberOfSticks) ({0:N2} %)" -f $(($NumberOfSticks / $NumberOfTests) * 100)) -ForegroundColor White
    Write-Host "Number of Times Staying with the Same Door Won the Car: " -ForegroundColor Yellow -NoNewline
    if ($NumberOfStickWins)
    {
        Write-Host ("$($NumberOfStickWins) ({0:N2} %)" -f (($NumberOfStickWins / $NumberOfSticks) * 100)) -ForegroundColor White
    }
    else
    {
        Write-Host "$($NumberOfStickWins) (0.00 %)" -ForegroundColor White
    }
}

if ($Choice -match "(LetFateDecide|SwitchDoor)")
{
    Write-Host
    Write-Host "Number of Times Switching Doors: " -ForegroundColor Yellow -NoNewline
    Write-Host ("$($NumberOfSwitches) ({0:N2} %)" -f $(($NumberOfSwitches / $NumberOfTests) * 100)) -ForegroundColor White
    Write-Host "Number of Times Switching Doors Won the Car: " -ForegroundColor Yellow -NoNewline
    if ($NumberOfSwitchWins)
    {
        Write-Host ("$($NumberOfSwitchWins) ({0:N2} %)" -f (($NumberOfSwitchWins / $NumberOfSwitches) * 100)) -ForegroundColor White
    }
    else
    {
        Write-Host "$($NumberOfSwitchWins) (0.00 %)" -ForegroundColor White
    }
}
Write-Host
Write-Host
Write-Host "To view all Test Results run the following command:" -ForegroundColor Yellow
Write-Host
Write-Host "    `$TestResults | Out-GridView" -ForegroundColor White
Write-Host
Write-Host

Leave a Reply

Your email address will not be published. Required fields are marked *