
Utilisation du pipeline dans Powershell
L'algorithme est simple, le premier est le générateur de porte aléatoire, puis le générateur de choix de l'utilisateur, puis la logique d'ouverture de la porte du présentateur, une autre action de l'utilisateur et le comptage des statistiques.
Et nous serons aidés avec cela par l'outil électrique
ValueFromPipeline
, qui nous permet de spécifier l'applet de commande une par une, en transformant l'objet étape par étape. Notre pipeline devrait ressembler à ceci:
New-Doors | Select-Door | Open-Door | Invoke-UserAction
New-Doors
génère de nouvelles portes, dans l'équipe le
Select-Door
joueur choisit l'une des portes, le
Open-Door
leader ouvre la porte dans laquelle il n'y a définitivement pas de chèvre et qui n'a pas été choisie par le joueur, et dans
Invoke-UserAction
nous simulons différents comportements d'utilisateurs.
L'objet décrivant la porte se déplace de gauche à droite, se transformant progressivement.
Cette méthode d'écriture du code permet de le garder en morceaux avec une répartition claire des responsabilités.
Powershell a ses propres conventions. Y compris les conventions sur la dénomination correcte des fonctions , elles doivent également être respectées et nous les respectons presque.
Faire des portes
Puisque nous allons simuler la situation, nous décrirons également les portes en détail.
La porte contient soit une chèvre, soit une voiture. La porte peut être choisie par le joueur ou ouverte par l'hôte.
class Door {
<#
, .
.
#>
[string]$Contains = "Goat"
[bool]$Selected = $false
[bool]$Opened = $false
}
Nous placerons chacune des portes dans un champ séparé dans une classe distincte.
class Doors {
<#
, 3
#>
[Door]$DoorOne
[Door]$DoorTwo
[Door]$DoorThree
}
Il était possible de mettre toutes les portes dans un tableau, mais plus tout est détaillé, mieux c'est. À propos, dans Powershell 7, les classes, leurs constructeurs, leurs méthodes et tout le reste sont de la POO, qui fonctionne presque comme il se doit, mais plus à ce sujet une autre fois.
Le générateur de porte aléatoire ressemble à ceci. Tout d'abord, pour chaque montant de porte, sa propre porte est générée, puis le générateur choisit lequel d'entre eux la voiture se tiendra derrière.
function New-Doors {
<#
.
#>
$i = [Doors]::new()
$i.DoorOne = [Door]::new()
$i.DoorTwo = [Door]::new()
$i.DoorThree = [Door]::new()
switch ( Get-Random -Maximum 3 -Minimum 0 ) {
0 {
$i.DoorOne.Contains = "Car"
}
1 {
$i.DoorTwo.Contains = "Car"
}
2 {
$i.DoorThree.Contains = "Car"
}
Default {
Write-Error "Something in door generator went wrong"
break
}
}
return $i
Notre pipe ressemble à ceci:
New-Doors
Le joueur choisit la porte
Décrivons maintenant le choix initial. Le joueur peut choisir l'une des trois portes. Pour simuler davantage de situations, laissez le joueur choisir uniquement la première, la deuxième, la troisième et la porte au hasard à chaque fois.
[Parameter(Mandatory)]
[ValidateSet("First", "Second", "Third", "Random")]
$Principle
Pour accepter les arguments du pipeline, vous devez spécifier une variable dans le bloc de paramètres qui fera cela. Ceci est fait comme ceci:
[parameter(ValueFromPipeline)]
[Doors]$i
Vous pouvez écrire
ValueFromPipeline
sans
True
.
Voici à quoi ressemble le bloc de sélection de porte fini:
function Select-Door {
<#
.
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i,
[Parameter(Mandatory)]
[ValidateSet("First", "Second", "Third", "Random")]
$Principle
)
switch ($Principle) {
"First" {
$i.DoorOne.Selected = $true
}
"Second" {
$i.DoorTwo.Selected = $true
}
"Third" {
$i.DoorThree.Selected = $true
}
"Random" {
switch ( Get-Random -Maximum 3 -Minimum 0 ) {
0 {
$i.DoorOne.Selected = $true
}
1 {
$i.DoorTwo.Selected = $true
}
2 {
$i.DoorThree.Selected = $true
}
Default {
Write-Error "Something in door selector went wrong"
break
}
}
}
Default {
Write-Error "Something in door selector went wrong"
break
}
}
return $i
Notre pipe ressemble à ceci:
New-Doors | Select-Door -Principle Random
Diriger ouvre la porte
Tout est très simple ici. Si la porte n'a pas été choisie par le joueur et s'il y a une chèvre derrière, changez le champ
Opened
en
True
. Plus précisément, dans ce cas, il n'est
Open
pas correct de nommer la commande avec un mot , la ressource appelée n'est pas lue, mais modifiée. Dans de tels cas, utilisez
Set
, mais
Open
laissez pour plus de clarté.
function Open-Door {
<#
, , .
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i
)
switch ($false) {
$i.DoorOne.Selected {
if ($i.DoorOne.Contains -eq "Goat") {
$i.DoorOne.Opened = $true
continue
}
}
$i.DoorTwo.Selected {
if ($i.DoorTwo.Contains -eq "Goat") {
$i.DoorTwo.Opened = $true
continue
}
}
$i.DoorThree.Selected {
if ($i.DoorThree.Contains -eq "Goat") {
$i.DoorThree.Opened = $true
continue
}
}
}
return $i
Pour rendre notre simulation plus convaincante, nous «ouvrons» cette porte en remplaçant le champ .opened par au
$true
lieu de supprimer l'objet du tableau de portes.
N'oubliez pas les
continue
interrupteurs, la comparaison ne s'arrête pas après le premier match.
Coninue
quitte le commutateur et continue d'exécuter le script, et l'opérateur
break
du commutateur met fin au script.
Ajoutez une autre fonction au tube, cela ressemble maintenant à ceci:
New-Doors | Select-Door -Principle Random | Open-Door
Le joueur change son choix
Le joueur change la porte ou ne la change pas. Dans le bloc de paramètres, nous n'avons qu'une variable du tube et un argument booléen.
Utilisez le mot
Invoke
dans les noms de ces fonctions, car cela
Invoke
signifie appeler une opération synchrone, et
Start
asynchrone, suivez les conventions et recommandations.
function Invoke-UserAction {
<#
, .
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i,
[Parameter(Mandatory)]
[bool]$SwitchDoor
)
if ($true -eq $SwitchDoor) {
switch ($false) {
$i.DoorOne.Opened {
if ( $i.DoorOne.Selected ) {
$i.DoorOne.Selected = $false
}
else {
$i.DoorOne.Selected = $true
}
}
$i.DoorTwo.Opened {
if ( $i.DoorTwo.Selected ) {
$i.DoorTwo.Selected = $false
}
else {
$i.DoorTwo.Selected = $true
}
}
$i.DoorThree.Opened {
if ( $i.DoorThree.Selected ) {
$i.DoorThree.Selected = $false
}
else {
$i.DoorThree.Selected = $true
}
}
}
}
return $i
Dans les opérateurs de branchement et de comparaison, le système et les variables statiques doivent être précisés en premier. Probablement, il peut y avoir des difficultés à convertir un objet en un autre, mais l'auteur n'a pas rencontré de telles difficultés lorsqu'il écrivait d'une manière différente auparavant.
Une autre fonction dans le pipeline.
New-Doors | Select-Door -Principle Random | Open-Door | Invoke-UserAction -SwitchDoor $True
L'avantage de cette approche d'écriture est clair, car il n'a jamais été aussi pratique de diviser le code en parties avec une séparation claire des fonctions.
Comportement du joueur
À quelle fréquence le joueur change la porte. Il y a 5 lignes de comportement:
Never
- le joueur ne change jamais son choixFifty-Fifty
- 50 à 50. Le nombre de simulations est divisé en deux passes. La première passe le joueur ne change pas la porte, la seconde passe.Random
- à chaque nouvelle simulation, le joueur lance une pièceAlways
- le joueur change toujours son choix.Ration
- le joueur change son choix dans N% des cas.
switch ($SwitchDoors) {
"Never" {
0..$Count | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
continue
}
"FiftyFifty" {
$Fifty = [math]::Round($Count / 2)
0..$Fifty | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
0..$Fifty | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
continue
}
"Random" {
0..$Count | ForEach-Object {
[bool]$Random = Get-Random -Maximum 2 -Minimum 0
$Win += Invoke-Simulation -Door $Door -SwitchDoors $Random
}
continue
}
"Always" {
0..$Count | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
continue
}
"Ratio" {
$TrueRatio = $Ratio / 100 * $Count
$FalseRatio = $Count - $TrueRatio
0..$TrueRatio | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
0..$FalseRatio | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
continue
}
}
ForEach-Object
dans Powershell 7, cela fonctionne beaucoup plus rapidement qu'une boucle
for
, en plus il peut être parallélisé, donc il est utilisé ici au lieu d'une boucle
for
.
Styliser l'applet de commande
Vous devez maintenant corriger l'applet de commande. Tout d'abord, vous devez faire la validation des arguments entrants. Le bonus n'est pas seulement qu'une personne ne peut pas entrer un argument non valide dans le champ, mais une liste de tous les arguments disponibles apparaît dans les invites.
Voici à quoi ressemble le code du bloc de paramètres:
param (
[Parameter(Mandatory = $false,
HelpMessage = "How often the player changes his choice.")]
[ValidateSet("Never", "FiftyFifty", "Random", "Always", "Ratio")]
$SwitchDoors = "Random"
)
Voici le conseil:

Avant que le bloc de paramètres puisse être fait
comment based help
. Voici à quoi ressemble le code avant le bloc de paramètres:
<#
.SYNOPSIS
Performs monty hall paradox simulation.
.DESCRIPTION
The Invoke-MontyHallParadox.ps1 script invoke monty hall paradox simulation.
.PARAMETER Door
Specifies door the player will choose during the entire simulation
.PARAMETER SwitchDoors
Specifies principle how the player changes his choice.
.PARAMETER Count
Specifies how many times to run the simulation.
.PARAMETER Ratio
If -SwitchDoors Ratio, specifies how often the player changes his choice. As a percentage."
.INPUTS
None. You cannot pipe objects to Update-Month.ps1.
.OUTPUTS
None. Update-Month.ps1 does not generate any output.
.EXAMPLE
PS> Invoke-MontyHallParadox -SwitchDoors Always -Count 10000
#>
Voici à quoi ressemble l'invite:

Lancer la simulation
Résultats de la simulation:

Si une personne ne change jamais son choix, elle gagne 33,37% du temps.
Dans le cas de deux passes, dont la moitié nous refusons de modifier notre choix, les chances de gagner sont de 49,9134%, ce qui est très proche d'exactement 50%.
Dans le cas d'un tirage au sort, rien ne change, les chances de gagner restent autour de 50,131%.
Eh bien, si le joueur change toujours son choix, les chances de gagner s'élèvent à 66,6184%, c'est-à-dire ennuyeuses et rien de nouveau.
Performance:
en termes de performances. Le script ne semble pas optimal.
String
au lieu de cela
Bool
, de nombreuses fonctions différentes avec un interrupteur à l'intérieur, se passant un objet entre elles, mais néanmoins, voici les résultats
Measure-Command
pour ce script et un script d'un autre auteur .
La comparaison a été effectuée sur deux systèmes, pwsh 7.1 était partout, 100 000 passes.
▍I5-5200u
Cet algorithme:
Days : 0 Hours : 0 Minutes : 0 Seconds : 4 Milliseconds : 581 Ticks : 45811819 TotalDays : 5,30229386574074E-05 TotalHours : 0,00127255052777778 TotalMinutes : 0,0763530316666667 TotalSeconds : 4,5811819 TotalMilliseconds : 4581,1819
Cet algorithme:
Days : 0 Hours : 0 Minutes : 0 Seconds : 5 Milliseconds : 104 Ticks : 51048392 TotalDays : 5,9083787037037E-05 TotalHours : 0,00141801088888889 TotalMinutes : 0,0850806533333333 TotalSeconds : 5,1048392 TotalMilliseconds : 5104,8392
▍I9-9900K
Cet algorithme:
Days : 0 Hours : 0 Minutes : 0 Seconds : 1 Milliseconds : 891 Ticks : 18917629 TotalDays : 2,18954039351852E-05 TotalHours : 0,000525489694444444 TotalMinutes : 0,0315293816666667 TotalSeconds : 1,8917629 TotalMilliseconds : 1891,7629
Cet algorithme:
Days : 0 Hours : 0 Minutes : 0 Seconds : 1 Milliseconds : 954 Ticks : 19543236 TotalDays : 2,26194861111111E-05 TotalHours : 0,000542867666666667 TotalMinutes : 0,03257206 TotalSeconds : 1,9543236 TotalMilliseconds : 1954,3236
Avantage de 63 ms, mais les résultats sont toujours très étranges compte tenu du nombre de fois que le script compare des chaînes.
L'auteur espère que cet article servira d'exemple convaincant pour ceux qui croient que les chances sont toujours de 50 à 50, mais vous pouvez lire le code sous ce spoiler.
Le code entier
class Doors {
<#
, 3
#>
[Door]$DoorOne
[Door]$DoorTwo
[Door]$DoorThree
}
class Door {
<#
, .
.
#>
[string]$Contains = «Goat»
[bool]$Selected = $false
[bool]$Opened = $false
}
function New-Doors {
<#
.
#>
$i = [Doors]::new()
$i.DoorOne = [Door]::new()
$i.DoorTwo = [Door]::new()
$i.DoorThree = [Door]::new()
switch ( Get-Random -Maximum 3 -Minimum 0 ) {
0 {
$i.DoorOne.Contains = «Car»
}
1 {
$i.DoorTwo.Contains = «Car»
}
2 {
$i.DoorThree.Contains = «Car»
}
Default {
Write-Error «Something in door generator went wrong»
break
}
}
return $i
}
function Select-Door {
<#
.
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i,
[Parameter(Mandatory)]
[ValidateSet(«First», «Second», «Third», «Random»)]
$Principle
)
switch ($Principle) {
«First» {
$i.DoorOne.Selected = $true
continue
}
«Second» {
$i.DoorTwo.Selected = $true
continue
}
«Third» {
$i.DoorThree.Selected = $true
continue
}
«Random» {
switch ( Get-Random -Maximum 3 -Minimum 0 ) {
0 {
$i.DoorOne.Selected = $true
continue
}
1 {
$i.DoorTwo.Selected = $true
continue
}
2 {
$i.DoorThree.Selected = $true
continue
}
Default {
Write-Error «Something in selector generator went wrong»
break
}
}
continue
}
Default {
Write-Error «Something in door selector went wrong»
break
}
}
return $i
}
function Open-Door {
<#
, , .
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i
)
switch ($false) {
$i.DoorOne.Selected {
if ($i.DoorOne.Contains -eq «Goat») {
$i.DoorOne.Opened = $true
continue
}
}
$i.DoorTwo.Selected {
if ($i.DoorTwo.Contains -eq «Goat») {
$i.DoorTwo.Opened = $true
continue
}
}
$i.DoorThree.Selected {
if ($i.DoorThree.Contains -eq «Goat») {
$i.DoorThree.Opened = $true
continue
}
}
}
return $i
}
function Invoke-UserAction {
<#
, .
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i,
[Parameter(Mandatory)]
[bool]$SwitchDoor
)
if ($true -eq $SwitchDoor) {
switch ($false) {
$i.DoorOne.Opened {
if ( $i.DoorOne.Selected ) {
$i.DoorOne.Selected = $false
}
else {
$i.DoorOne.Selected = $true
}
}
$i.DoorTwo.Opened {
if ( $i.DoorTwo.Selected ) {
$i.DoorTwo.Selected = $false
}
else {
$i.DoorTwo.Selected = $true
}
}
$i.DoorThree.Opened {
if ( $i.DoorThree.Selected ) {
$i.DoorThree.Selected = $false
}
else {
$i.DoorThree.Selected = $true
}
}
}
}
return $i
}
function Get-Win {
Param (
[parameter(ValueFromPipeline)]
[Doors]$i
)
switch ($true) {
($i.DoorOne.Selected -and $i.DoorOne.Contains -eq «Car») {
return $true
}
($i.DoorTwo.Selected -and $i.DoorTwo.Contains -eq «Car») {
return $true
}
($i.DoorThree.Selected -and $i.DoorThree.Contains -eq «Car») {
return $true
}
default {
return $false
}
}
}
function Invoke-Simulation {
param (
[Parameter(Mandatory = $false,
HelpMessage = «Which door the player will choose during the entire simulation.»)]
[ValidateSet(«First», «Second», «Third», «Random»)]
$Door = «Random»,
[bool]$SwitchDoors
)
return New-Doors | Select-Door -Principle $Door | Open-Door | Invoke-UserAction -SwitchDoor $SwitchDoors | Get-Win
}
function Invoke-MontyHallParadox {
<#
.SYNOPSIS
Performs monty hall paradox simulation.
.DESCRIPTION
The Invoke-MontyHallParadox.ps1 script invoke monty hall paradox simulation.
.PARAMETER Door
Specifies door the player will choose during the entire simulation
.PARAMETER SwitchDoors
Specifies principle how the player changes his choice.
.PARAMETER Count
Specifies how many times to run the simulation.
.PARAMETER Ratio
If -SwitchDoors Ratio, specifies how often the player changes his choice. As a percentage."
.INPUTS
None. You cannot pipe objects to Update-Month.ps1.
.OUTPUTS
None. Update-Month.ps1 does not generate any output.
.EXAMPLE
PS> Invoke-MontyHallParadox -SwitchDoors Always -Count 10000
#>
param (
[Parameter(Mandatory = $false,
HelpMessage = «Which door the player will choose during the entire simulation.»)]
[ValidateSet(«First», «Second», «Third», «Random»)]
$Door = «Random»,
[Parameter(Mandatory = $false,
HelpMessage = «How often the player changes his choice.»)]
[ValidateSet(«Never», «FiftyFifty», «Random», «Always», «Ratio»)]
$SwitchDoors = «Random»,
[Parameter(Mandatory = $false,
HelpMessage = «How many times to run the simulation.»)]
[uint32]$Count = 10000,
[Parameter(Mandatory = $false,
HelpMessage = «How often the player changes his choice. As a percentage.»)]
[uint32]$Ratio = 30
)
[uint32]$Win = 0
switch ($SwitchDoors) {
«Never» {
0..$Count | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
continue
}
«FiftyFifty» {
$Fifty = [math]::Round($Count / 2)
0..$Fifty | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
0..$Fifty | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
continue
}
«Random» {
0..$Count | ForEach-Object {
[bool]$Random = Get-Random -Maximum 2 -Minimum 0
$Win += Invoke-Simulation -Door $Door -SwitchDoors $Random
}
continue
}
«Always» {
0..$Count | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
continue
}
«Ratio» {
$TrueRatio = $Ratio / 100 * $Count
$FalseRatio = $Count — $TrueRatio
0..$TrueRatio | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
0..$FalseRatio | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
continue
}
}
Write-Output («Player won in » + $Win + " times out of " + $Count)
Write-Output («Whitch is » + ($Win / $Count * 100) + "%")
return $Win
}
#Invoke-MontyHallParadox -SwitchDoors Always -Count 500000
<#
, 3
#>
[Door]$DoorOne
[Door]$DoorTwo
[Door]$DoorThree
}
class Door {
<#
, .
.
#>
[string]$Contains = «Goat»
[bool]$Selected = $false
[bool]$Opened = $false
}
function New-Doors {
<#
.
#>
$i = [Doors]::new()
$i.DoorOne = [Door]::new()
$i.DoorTwo = [Door]::new()
$i.DoorThree = [Door]::new()
switch ( Get-Random -Maximum 3 -Minimum 0 ) {
0 {
$i.DoorOne.Contains = «Car»
}
1 {
$i.DoorTwo.Contains = «Car»
}
2 {
$i.DoorThree.Contains = «Car»
}
Default {
Write-Error «Something in door generator went wrong»
break
}
}
return $i
}
function Select-Door {
<#
.
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i,
[Parameter(Mandatory)]
[ValidateSet(«First», «Second», «Third», «Random»)]
$Principle
)
switch ($Principle) {
«First» {
$i.DoorOne.Selected = $true
continue
}
«Second» {
$i.DoorTwo.Selected = $true
continue
}
«Third» {
$i.DoorThree.Selected = $true
continue
}
«Random» {
switch ( Get-Random -Maximum 3 -Minimum 0 ) {
0 {
$i.DoorOne.Selected = $true
continue
}
1 {
$i.DoorTwo.Selected = $true
continue
}
2 {
$i.DoorThree.Selected = $true
continue
}
Default {
Write-Error «Something in selector generator went wrong»
break
}
}
continue
}
Default {
Write-Error «Something in door selector went wrong»
break
}
}
return $i
}
function Open-Door {
<#
, , .
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i
)
switch ($false) {
$i.DoorOne.Selected {
if ($i.DoorOne.Contains -eq «Goat») {
$i.DoorOne.Opened = $true
continue
}
}
$i.DoorTwo.Selected {
if ($i.DoorTwo.Contains -eq «Goat») {
$i.DoorTwo.Opened = $true
continue
}
}
$i.DoorThree.Selected {
if ($i.DoorThree.Contains -eq «Goat») {
$i.DoorThree.Opened = $true
continue
}
}
}
return $i
}
function Invoke-UserAction {
<#
, .
#>
Param (
[parameter(ValueFromPipeline)]
[Doors]$i,
[Parameter(Mandatory)]
[bool]$SwitchDoor
)
if ($true -eq $SwitchDoor) {
switch ($false) {
$i.DoorOne.Opened {
if ( $i.DoorOne.Selected ) {
$i.DoorOne.Selected = $false
}
else {
$i.DoorOne.Selected = $true
}
}
$i.DoorTwo.Opened {
if ( $i.DoorTwo.Selected ) {
$i.DoorTwo.Selected = $false
}
else {
$i.DoorTwo.Selected = $true
}
}
$i.DoorThree.Opened {
if ( $i.DoorThree.Selected ) {
$i.DoorThree.Selected = $false
}
else {
$i.DoorThree.Selected = $true
}
}
}
}
return $i
}
function Get-Win {
Param (
[parameter(ValueFromPipeline)]
[Doors]$i
)
switch ($true) {
($i.DoorOne.Selected -and $i.DoorOne.Contains -eq «Car») {
return $true
}
($i.DoorTwo.Selected -and $i.DoorTwo.Contains -eq «Car») {
return $true
}
($i.DoorThree.Selected -and $i.DoorThree.Contains -eq «Car») {
return $true
}
default {
return $false
}
}
}
function Invoke-Simulation {
param (
[Parameter(Mandatory = $false,
HelpMessage = «Which door the player will choose during the entire simulation.»)]
[ValidateSet(«First», «Second», «Third», «Random»)]
$Door = «Random»,
[bool]$SwitchDoors
)
return New-Doors | Select-Door -Principle $Door | Open-Door | Invoke-UserAction -SwitchDoor $SwitchDoors | Get-Win
}
function Invoke-MontyHallParadox {
<#
.SYNOPSIS
Performs monty hall paradox simulation.
.DESCRIPTION
The Invoke-MontyHallParadox.ps1 script invoke monty hall paradox simulation.
.PARAMETER Door
Specifies door the player will choose during the entire simulation
.PARAMETER SwitchDoors
Specifies principle how the player changes his choice.
.PARAMETER Count
Specifies how many times to run the simulation.
.PARAMETER Ratio
If -SwitchDoors Ratio, specifies how often the player changes his choice. As a percentage."
.INPUTS
None. You cannot pipe objects to Update-Month.ps1.
.OUTPUTS
None. Update-Month.ps1 does not generate any output.
.EXAMPLE
PS> Invoke-MontyHallParadox -SwitchDoors Always -Count 10000
#>
param (
[Parameter(Mandatory = $false,
HelpMessage = «Which door the player will choose during the entire simulation.»)]
[ValidateSet(«First», «Second», «Third», «Random»)]
$Door = «Random»,
[Parameter(Mandatory = $false,
HelpMessage = «How often the player changes his choice.»)]
[ValidateSet(«Never», «FiftyFifty», «Random», «Always», «Ratio»)]
$SwitchDoors = «Random»,
[Parameter(Mandatory = $false,
HelpMessage = «How many times to run the simulation.»)]
[uint32]$Count = 10000,
[Parameter(Mandatory = $false,
HelpMessage = «How often the player changes his choice. As a percentage.»)]
[uint32]$Ratio = 30
)
[uint32]$Win = 0
switch ($SwitchDoors) {
«Never» {
0..$Count | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
continue
}
«FiftyFifty» {
$Fifty = [math]::Round($Count / 2)
0..$Fifty | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
0..$Fifty | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
continue
}
«Random» {
0..$Count | ForEach-Object {
[bool]$Random = Get-Random -Maximum 2 -Minimum 0
$Win += Invoke-Simulation -Door $Door -SwitchDoors $Random
}
continue
}
«Always» {
0..$Count | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
continue
}
«Ratio» {
$TrueRatio = $Ratio / 100 * $Count
$FalseRatio = $Count — $TrueRatio
0..$TrueRatio | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $true
}
0..$FalseRatio | ForEach-Object {
$Win += Invoke-Simulation -Door $Door -SwitchDoors $false
}
continue
}
}
Write-Output («Player won in » + $Win + " times out of " + $Count)
Write-Output («Whitch is » + ($Win / $Count * 100) + "%")
return $Win
}
#Invoke-MontyHallParadox -SwitchDoors Always -Count 500000

