Verwenden der Pipeline in Powershell
Der Algorithmus ist einfach, der erste ist der Zufallstürgenerator, dann der Benutzerauswahlgenerator, dann die Türöffnungslogik des Präsentators, eine weitere Benutzeraktion und das Zählen von Statistiken.
Und das Elektrowerkzeug hilft uns dabei
ValueFromPipeline
, das Cmdlet einzeln anzugeben und das Objekt Schritt für Schritt zu transformieren. So sollte unsere Pipeline aussehen:
New-Doors | Select-Door | Open-Door | Invoke-UserAction
New-Doors
erzeugt neue Türen, im Team
Select-Door
wählt der Spieler eine der Türen, der
Open-Door
Anführer öffnet die Tür, in der es definitiv keine Ziege gibt und die vom Spieler nicht ausgewählt wurde, und in
Invoke-UserAction
simulieren wir ein anderes Benutzerverhalten.
Das Objekt, das die Tür beschreibt, bewegt sich von links nach rechts und verwandelt sich allmählich.
Diese Methode zum Schreiben von Code hilft, ihn in Teilen mit klaren Verantwortungsbereichen zu halten.
Powershell hat seine eigenen Konventionen. Einschließlich der Konventionen zur korrekten Benennung von Funktionen müssen diese ebenfalls beachtet werden und wir halten sie fast ein.
Türen machen
Da wir die Situation simulieren werden, werden wir auch die Türen im Detail beschreiben.
Die Tür enthält entweder eine Ziege oder ein Auto. Die Tür kann vom Spieler ausgewählt oder vom Gastgeber geöffnet werden.
class Door {
<#
, .
.
#>
[string]$Contains = "Goat"
[bool]$Selected = $false
[bool]$Opened = $false
}
Wir werden jede der Türen in einem separaten Feld in einer separaten Klasse platzieren.
class Doors {
<#
, 3
#>
[Door]$DoorOne
[Door]$DoorTwo
[Door]$DoorThree
}
Es war möglich, alle Türen in einer Reihe anzuordnen, aber je detaillierter alles beschrieben wird, desto besser. Übrigens sind in Powershell 7 Klassen, ihre Konstruktoren, Methoden und alles andere OOP, was fast so funktioniert, wie es sollte, aber dazu ein anderes Mal mehr.
Der Zufallstürgenerator sieht so aus. Zuerst wird für jeden Türpfosten eine eigene Tür erzeugt, und dann wählt der Generator aus, hinter welcher von ihnen das Auto stehen soll.
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
Unsere Pfeife sieht so aus:
New-Doors
Der Spieler wählt die Tür
Beschreiben wir nun die anfängliche Wahl. Der Spieler kann eine von drei Türen wählen. Um mehr Situationen zu simulieren, lassen Sie den Spieler jedes Mal nur die erste, nur die zweite, nur die dritte und zufällige Tür auswählen.
[Parameter(Mandatory)]
[ValidateSet("First", "Second", "Third", "Random")]
$Principle
Um Argumente aus der Pipeline zu akzeptieren, müssen Sie im Parameterblock eine Variable angeben, die dies ausführt. Dies geschieht folgendermaßen:
[parameter(ValueFromPipeline)]
[Doors]$i
Sie können
ValueFromPipeline
ohne schreiben
True
.
So sieht der fertige Türauswahlblock aus:
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
Unsere Pfeife sieht so aus:
New-Doors | Select-Door -Principle Random
Führen öffnet die Tür
Hier ist alles sehr einfach. Wenn die Tür nicht vom Spieler ausgewählt wurde und sich eine Ziege dahinter befindet, ändern Sie das Feld
Opened
in
True
. Insbesondere ist es in diesem Fall
Open
nicht korrekt , den Befehl als Wort zu bezeichnen . Die aufgerufene Ressource wird nicht gelesen, sondern geändert. In solchen Fällen verwenden
Set
, aber
Open
zur Klarheit lassen.
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
Um unsere Simulation überzeugender zu gestalten, "öffnen" wir diese Tür, indem wir das geöffnete Feld in ändern, anstatt das
$true
Objekt aus dem Türarray zu löschen .
Vergessen Sie nicht die
continue
Schalter, der Vergleich wird nach dem ersten Spiel nicht beendet.
Coninue
Beendet den Switch und führt das Skript weiter aus. Der Operator
break
im Switch beendet das Skript.
Wir fügen der Pipe eine weitere Funktion hinzu, die jetzt so aussieht:
New-Doors | Select-Door -Principle Random | Open-Door
Der Spieler ändert seine Wahl
Der Spieler wechselt entweder die Tür oder ändert sie nicht. Im Parameterblock haben wir nur eine Variable aus der Pipe und ein boolesches Argument.
Verwenden Sie das Wort
Invoke
in den Namen solcher Funktionen, da dies
Invoke
bedeutet, dass eine synchrone Operation
Start
aufgerufen und asynchron die Konventionen und Empfehlungen befolgt werden.
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
In den Operatoren Verzweigung und Vergleich müssen Sie zuerst das System und die statischen Variablen angeben. Wahrscheinlich kann es Schwierigkeiten geben, ein Objekt in ein anderes umzuwandeln, aber der Autor hatte solche Schwierigkeiten nicht, als er zuvor auf eine andere Weise schrieb.
Eine weitere Funktion in der Pipeline.
New-Doors | Select-Door -Principle Random | Open-Door | Invoke-UserAction -SwitchDoor $True
Der Vorteil dieses Schreibansatzes liegt auf der Hand, da es noch nie so bequem war, Code mit einer klaren Funktionstrennung in Teile aufzuteilen.
Spielerverhalten
Wie oft wechselt der Spieler die Tür. Es gibt 5 Verhaltenslinien:
Never
- Der Spieler ändert nie seine WahlFifty-Fifty
- 50 bis 50. Die Anzahl der Simulationen ist in zwei Durchgänge unterteilt. Beim ersten Durchgang ändert der Spieler die Tür nicht, beim zweiten Durchgang ändert sich.Random
- In jeder neuen Simulation wirft der Spieler eine MünzeAlways
- Der Spieler ändert immer seine Wahl.Ration
- Der Spieler ändert seine Wahl in N% der Fälle.
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
In Powershell 7 funktioniert es viel schneller als eine Schleife
for
. Außerdem kann es parallelisiert werden, sodass es hier anstelle einer Schleife verwendet wird
for
.
Cmdlet stylen
Jetzt müssen Sie das Cmdlet korrigieren. Zunächst müssen Sie die eingehenden Argumente validieren. Der Bonus besteht nicht nur darin, dass eine Person kein ungültiges Argument in das Feld eingeben kann, sondern eine Liste aller verfügbaren Argumente in den Eingabeaufforderungen angezeigt wird.
So sieht der Code im Parameterblock aus:
param (
[Parameter(Mandatory = $false,
HelpMessage = "How often the player changes his choice.")]
[ValidateSet("Never", "FiftyFifty", "Random", "Always", "Ratio")]
$SwitchDoors = "Random"
)
Dies ist der Hinweis:
Bevor der Parameterblock ausgeführt werden kann
comment based help
. So sieht der Code vor dem Parameterblock aus:
<#
.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
#>
So sieht die Eingabeaufforderung aus:
Ausführen der Simulation
Simulationsergebnisse:
Wenn eine Person ihre Wahl nie ändert, gewinnt sie 33,37% der Zeit.
Bei zwei Pässen, bei denen wir uns zur Hälfte weigern, unsere Wahl zu ändern, liegen die Gewinnchancen bei 49,9134%, was sehr genau 50% entspricht.
Bei einem Münzwurf ändert sich nichts, die Gewinnchance bleibt bei 50,131%.
Wenn der Spieler seine Wahl immer ändert, steigt die Gewinnchance auf 66,6184%, dh langweilig und nichts Neues.
Leistung:
In Bezug auf die Leistung. Das Skript scheint nicht optimal zu sein.
String
Stattdessen
Bool
gibt es viele verschiedene Funktionen mit einem Schalter im Inneren, der ein Objekt aneinander weitergibt. Dennoch sind hier die Ergebnisse
Measure-Command
für dieses Skript und ein Skript eines anderen Autors .
Der Vergleich wurde auf zwei Systemen durchgeführt, pwsh 7.1 war überall, 100.000 Durchgänge.
▍I5-5200u
Dieser Algorithmus:
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
Dieser Algorithmus:
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
Dieser Algorithmus:
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
Dieser Algorithmus:
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
63ms Vorteil, aber die Ergebnisse sind immer noch sehr seltsam, wenn man bedenkt, wie oft das Skript Zeichenfolgen vergleicht.
Der Autor hofft, dass dieser Artikel als überzeugendes Beispiel für diejenigen dienen wird, die glauben, dass die Chancen immer zwischen 50 und 50 liegen, aber Sie können den Code unter diesem Spoiler lesen.
Der ganze Code
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