Two bullet roulette: Difference between revisions
Added FreeBASIC
m (→{{header|Phix}}: syntax coloured, added expected outcomes) |
(Added FreeBASIC) |
||
(21 intermediate revisions by 8 users not shown) | |||
Line 56:
{{trans|Go}}
<
F nonrandom(n)
:seed = 1664525 * :seed + 1013904223
Line 119:
sum += method(m)
V pc = Float(sum) * 100 / tests
print(‘#<40 produces #2.3% deaths.’.format(mstring(m), pc))</
{{out}}
Line 130:
=={{header|AutoHotkey}}==
<
(
load, spin, load, spin, fire, spin, fire
Line 180:
sixGun[1] := temp
}
}</
{{out}}
<pre>55.478% Deaths for : "load, spin, load, spin, fire, spin, fire"
Line 189:
=={{header|C}}==
{{trans|Go}}
<
#include <stdio.h>
#include <stdlib.h>
Line 308:
return 0;
}</
{{out}}
<pre>load, spin, load, spin, fire, spin, fire produces 55.456% deaths.
Line 317:
=={{header|C++}}==
{{trans|C}}
<
#include <iomanip>
#include <iostream>
Line 444:
return 0;
}</
{{out}}
<pre>load, spin, load, spin, fire, spin, fire produces 55.487% deaths.
Line 453:
=={{header|EasyLang}}==
{{trans|C}}
<syntaxhighlight>
len cyl[] 6
proc rshift . .
for
cyl[i] = cyl[i - 1]
cyl[1] = h
.
for i
cyl[i] = 0
.
.
while cyl[
.
cyl[
.
lim =
for i = 1 to lim - 1
.
.
func fire
shot = cyl[
return shot
.
func method m[]
.
return 0
.
method$[] = [ "load" "spin" "fire" ]
n = 100000
for i
.
for i = 1 to len m[]
.
print "-> " & 100 * sum / n & "% death"
.
</syntaxhighlight>
=={{header|Factor}}==
{{trans|Julia}}
{{trans|Python}}
<
math random sequences ;
IN: rosetta-code.roulette
Line 556 ⟶ 557:
} [ run-test ] assoc-each ;
MAIN: main</
{{out}}
<pre>"rosetta-code.roulette" run</pre>
Line 565 ⟶ 566:
Method <load, load, spin, fire, fire> produces 49.841% deaths.
</pre>
=={{header|FreeBASIC}}==
{{trans|Wren}}
<syntaxhighlight lang="vbnet">Type Revolver
cylinder(0 To 5) As Integer
End Type
Sub rshift(r As Revolver)
Dim t As Integer = r.cylinder(5)
For i As Integer = 4 To 0 Step -1
r.cylinder(i + 1) = r.cylinder(i)
Next i
r.cylinder(0) = t
End Sub
Sub unload(r As Revolver)
For i As Integer = 0 To 5
r.cylinder(i) = 0
Next i
End Sub
Sub load(r As Revolver)
While r.cylinder(0) <> 0
rshift(r)
Wend
r.cylinder(0) = -1
rshift(r)
End Sub
Sub spin(r As Revolver)
For i As Integer = 1 To Int(Rnd * 6) + 1
rshift(r)
Next i
End Sub
Function fire(r As Revolver) As Integer
Dim As Integer shot = r.cylinder(0)
rshift(r)
Return shot
End Function
Function method(r As Revolver, s As String) As Integer
unload(r)
For i As Integer = 1 To Len(s)
Dim c As String = Mid(s, i, 1)
If c = "L" Then
load(r)
Elseif c = "S" Then
spin(r)
Elseif c = "F" Then
If fire(r) <> 0 Then Return 1
End If
Next i
Return 0
End Function
Function mstring(s As String) As String
Dim As String l = ""
For i As Integer = 1 To Len(s)
Dim As String c = Mid(s, i, 1)
If c = "L" Then
l &= "load, "
Elseif c = "S" Then
l &= "spin, "
Elseif c = "F" Then
l &= "fire, "
End If
Next i
Return Left(l, Len(l) - 2)
End Function
Dim As Revolver rev
Dim As Integer tests = 100000
Dim As String methods(0 To 3) = {"LSLSFSF", "LSLSFF", "LLSFSF", "LLSFF"}
For m As Integer = 0 To 3 'In methods
Dim sum As Integer = 0
For t As Integer = 1 To tests
sum += method(rev, methods(m))
Next t
Print mstring(methods(m)), " produces "; sum * 100.0 / tests; "% deaths."
Next m
Sleep</syntaxhighlight>
{{out}}
<pre>load, spin, load, spin, fire, spin, fire produces 55.385% deaths.
load, spin, load, spin, fire, fire produces 58.204% deaths.
load, load, spin, fire, spin, fire produces 55.372% deaths.
load, load, spin, fire, fire produces 50.052% deaths.</pre>
=={{header|Go}}==
{{trans|Wren}}
Though procedural rather than OO.
<
import (
Line 658 ⟶ 748:
fmt.Printf("%-40s produces %6.3f%% deaths.\n", mstring(m), pc)
}
}</
{{out}}
Line 667 ⟶ 757:
load, load, spin, fire, spin, fire produces 55.405% deaths.
load, load, spin, fire, fire produces 49.889% deaths.
</pre>
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.util.BitSet;
import java.util.concurrent.ThreadLocalRandom;
public class TwoBulletRoulette {
public static void main(String[] aArgs) {
Revolver handgun = new Revolver();
final int simulationCount = 100_000;
for ( Situation situation : Situation.values() ) {
double deaths = 0.0;
for ( int i = 0; i < simulationCount; i++ ) {
ResultState resultState = handgun.operateInMode(situation);
if ( resultState == ResultState.DEAD) {
deaths += 1.0;
}
}
final double deathRate = ( deaths / simulationCount ) * 100;
String percentage = String.format("%4.1f%%", deathRate);
System.out.println("Situation " + situation + " produces " + percentage + " deaths");
}
}
}
enum Situation { A, B, C, D }
enum ResultState { ALIVE, DEAD }
/**
* Representation of a six cylinder revolving chamber pistol.
*/
class Revolver {
public Revolver() {
chambers = new BitSet(chamberCount);
random = ThreadLocalRandom.current();
}
public ResultState operateInMode(Situation aSituation) {
return switch ( aSituation ) {
case A -> useSituationA();
case B -> useSituationB();
case C -> useSituationC();
case D -> useSituationD();
};
}
// PRIVATE //
private void unload() {
chambers.clear();
}
private void load() {
while ( chambers.get(loadingChamber) ) {
rotateClockwise();
}
chambers.set(loadingChamber);
rotateClockwise();
}
private void spin() {
final int spins = random.nextInt(0, chamberCount);
for ( int i = 0; i < spins; i++ ) {
rotateClockwise();
}
}
private boolean fire() {
boolean fire = chambers.get(firingChamber);
chambers.set(firingChamber, false);
rotateClockwise();
return fire;
}
private void rotateClockwise() {
final boolean temp = chambers.get(chamberCount - 1);
for ( int i = chamberCount - 2; i >= 0; i-- ) {
chambers.set(i + 1, chambers.get(i));
}
chambers.set(firingChamber, temp);
}
private ResultState useSituationA() {
unload();
load();
spin();
load();
spin();
if ( fire() ) {
return ResultState.DEAD;
};
spin();
if ( fire() ) {
return ResultState.DEAD;
};
return ResultState.ALIVE;
}
private ResultState useSituationB() {
unload();
load();
spin();
load();
spin();
if ( fire() ) {
return ResultState.DEAD;
};
if ( fire() ) {
return ResultState.DEAD;
};
return ResultState.ALIVE;
}
private ResultState useSituationC() {
unload();
load();
load();
spin();
if ( fire() ) {
return ResultState.DEAD;
};
spin();
if ( fire() ) {
return ResultState.DEAD;
};
return ResultState.ALIVE;
}
private ResultState useSituationD() {
unload();
load();
load();
spin();
if ( fire() ) {
return ResultState.DEAD;
};
if ( fire() ) {
return ResultState.DEAD;
};
return ResultState.ALIVE;
}
private BitSet chambers;
private ThreadLocalRandom random;
private final int firingChamber = 0;
private final int loadingChamber = 1;
private final int chamberCount = 6;
}
</syntaxhighlight>
{{ out }}
<pre>
Situation A produces 55.6% deaths
Situation B produces 58.2% deaths
Situation C produces 55.7% deaths
Situation D produces 49.7% deaths
</pre>
=={{header|JavaScript}}==
<
let Pistol = function(method) {
this.fired = false;
Line 722 ⟶ 979:
console.log();
}
</syntaxhighlight>
{{out}}
Example:
Line 743 ⟶ 1,000:
=={{header|Julia}}==
{{trans|Python}}
<
function load()
Line 796 ⟶ 1,053:
testmethods()
</
<pre>
Method load, spin, load, spin, fire, spin, fire produces 55.54253 per cent deaths.
Line 806 ⟶ 1,063:
=={{header|Kotlin}}==
{{trans|C}}
<
val cylinder = Array(6) { false }
Line 907 ⟶ 1,164:
test("LLSFSF");
test("LLSFF");
}</
{{out}}
<pre>load, spin, load, spin, fire, spin, fire produces 55.638% deaths.
Line 915 ⟶ 1,172:
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
Unload[] := ConstantArray[False, 6]
Load[state_List] := Module[{s = state},
Line 1,001 ⟶ 1,258:
Count[Table[LSLSFF[], n], True]/N[n]
Count[Table[LLSFSF[], n], True]/N[n]
Count[Table[LLSFF[], n], True]/N[n]</
{{out}}
<pre>0.55243
Line 1,010 ⟶ 1,267:
=={{header|Nim}}==
<
type
Line 1,053 ⟶ 1,310:
randomize()
for scenario in ["LSLSFSF", "LSLSFF", "LLSFSF", "LLSFF"]:
test(scenario)</
{{out}}
Line 1,060 ⟶ 1,317:
55.74% deaths for scenario Load, Load, Spin, Fire, Spin, Fire.
50.14% deaths for scenario Load, Load, Spin, Fire, Fire.</pre>
=={{header|Odin}}==
<syntaxhighlight lang="Go">
/* imports */
import "core:fmt"
import "core:strings"
import "core:math/rand"
/* globals */
cylinder := [6]bool{}
/* main block */
main :: proc() {
rand.set_global_seed(42)
tests := 100000
sequence := [?]string{"LSLSFSF", "LSLSFF", "LLSFSF", "LLSFF"}
for m in sequence {
sum := 0
for t in 0 ..< tests {
sum += method(m)
}
pc: f64 = cast(f64)sum * 100 / cast(f64)tests
fmt.printf("%-40s produces %6.3f%% deaths.\n", mstring(m), pc)
}
}
/* definitions */
rshift :: proc() {
t := cylinder[len(cylinder) - 1]
copy(cylinder[1:], cylinder[0:])
cylinder[0] = t
}
unload :: proc() {
cylinder = false // array programming
}
load :: proc() {
for cylinder[0] {
rshift()
}
cylinder[0] = true
rshift()
}
spin :: proc() {
data: []int = {1, 2, 3, 4, 5, 6}
lim := rand.choice(data[:])
for i in 0 ..< lim {
rshift()
}
}
fire :: proc() -> bool {
shot := cylinder[0]
rshift()
return shot
}
method :: proc(s: string) -> int {
unload()
for character in s {
switch character {
case 'L':
load()
case 'S':
spin()
case 'F':
if fire() {
return 1
}
}
}
return 0
}
mstring :: proc(s: string) -> string {
l: [dynamic]string
for character in s {
switch character {
case 'L':
append(&l, "load")
case 'S':
append(&l, "spin")
case 'F':
append(&l, "fire")
}
}
return strings.join(l[:], ", ")
}
</syntaxhighlight>
{{out}}
<pre>
load, spin, load, spin, fire, spin, fire produces 55.771% deaths.
load, spin, load, spin, fire, fire produces 58.313% deaths.
load, load, spin, fire, spin, fire produces 55.487% deaths.
load, load, spin, fire, fire produces 49.972% deaths.
</pre>
=={{header|Perl}}==
{{trans|Raku}}
<
use warnings;
use feature 'say';
Line 1,114 ⟶ 1,460:
$total += &$ref for 1..$trials;
printf "%7s %.2f%%\n", $ref, $total / $trials * 100;
}</
{{out}}
<pre>LSLSFSF 55.04%
Line 1,122 ⟶ 1,468:
=={{header|Phix}}==
<!--<
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">spin</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">revolver</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">)</span>
Line 1,169 ⟶ 1,515:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Load/Spin/Fire method percentage fatalities:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">papply</span><span style="color: #0000FF;">({{</span><span style="color: #008000;">"LSLSFSF"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">/</span><span style="color: #000000;">9</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">"LSLSFF"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">/</span><span style="color: #000000;">12</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">"LLSFSF"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">/</span><span style="color: #000000;">9</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">"LLSFF"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},</span><span style="color: #000000;">test</span><span style="color: #0000FF;">)</span>
<!--</
{{out}}
<pre>
Line 1,180 ⟶ 1,526:
=={{header|Python}}==
<
import numpy as np
Line 1,274 ⟶ 1,620:
percentage = 100 * sum([method() for _ in range(TESTCOUNT)]) / TESTCOUNT
print("Method", name, "produces", percentage, "per cent deaths.")
</
<pre>
Method load, spin, load, spin, fire, spin, fire produces 55.652 per cent deaths.
Line 1,284 ⟶ 1,630:
=={{header|Raku}}==
<syntaxhighlight lang="raku"
my @cyl;
Line 1,337 ⟶ 1,683:
say "{.fmt('%7s')}: %{(%revolver{$_} / $trials × 100).fmt('%.2f')}"
for <LSLSFSF LSLSFF LLSFSF LLSFF></
{{out|Sample output (default; 6 shooter)}}
<pre>LSLSFSF: %55.37
Line 1,373 ⟶ 1,719:
Changing the cartridge chamber from an index array to a simple string made the program around '''200%''' faster.
<
parse arg cyls tests seed . /*obtain optional arguments from the CL*/
if cyls=='' | cyls=="," then cyls= 6 /*Not specified? Then use the default.*/
Line 1,406 ⟶ 1,752:
if y=='S' then $= $", spin"
if y=='F' then $= $", fire"
end /*a*/; return right( strip( strip($, , ",") ), 45)</
{{out|output|text= when using the default inputs, showing that 2<sup>nd</sup> option '''B''' has the highest probability for a suicide:}}
<pre>
Line 1,413 ⟶ 1,759:
load, load, spin, fire, spin, fire (option C) produces 55.82% deaths.
load, load, spin, fire, fire (option D) produces 50.021% deaths.
</pre>
=={{header|Ruby}}==
Out of morbid interest I added strategy E: load, spin, shoot, load, spin, shoot.
<syntaxhighlight lang="ruby">class Revolver
attr_accessor :strategy
attr_reader :notches, :shot_count
def initialize(strategy = [:load, :spin, :shoot], num_chambers = 6) # default like Deer hunter
@chambers = Array.new(num_chambers) # by default 6 nils
@strategy = strategy
@notches, @shot_count, @loaded_count = 0, 0, 0
end
def load
raise "gun completely loaded " if @chambers.all? :loaded
@chambers.rotate! until @chambers[1] == nil #not sure about this; Raku rotates -1
@chambers[1] = :loaded
@chambers.rotate! #not sure about this; Raku rotates -1
@loaded_count += 1
end
def spin
@chambers.rotate!(rand(1..@chambers.size))
end
def unload
@chambers.fill(nil)
@loaded_count = 0
end
def shoot
@chambers[0] = nil
@chambers.rotate!
end
def play
strategy.each{|action| send(action)}
@shot_count += 1
@notches += 1 unless @chambers.count(:loaded) == @loaded_count # all bullets still there?
unload
end
end
strategies = {:A => [:load, :spin, :load, :spin, :shoot, :spin, :shoot],
:B => [:load, :spin, :load, :spin, :shoot, :shoot],
:C => [:load, :load, :spin, :shoot, :spin, :shoot],
:D => [:load, :load, :spin, :shoot, :shoot],
:E => [:load, :spin, :shoot, :load, :spin, :shoot]}
n = 100_000
puts "simulation of #{n} runs:"
strategies.each do |name, strategy|
gun = Revolver.new(strategy) # Revolver.new(strategy, 10) for a 10-shooter
n.times{gun.play}
puts "Strategy #{name}: #{gun.notches.fdiv(gun.shot_count)}"
end
</syntaxhighlight>
{{out}}
<pre>simulation of 100000 runs:
Strategy A: 0.55728
Strategy B: 0.58316
Strategy C: 0.5598
Strategy D: 0.49876
Strategy E: 0.44323
</pre>
=={{header|V (Vlang)}}==
{{trans|Kotlin}}
<syntaxhighlight lang="v (vlang)">
import rand
__global cylinder = []bool{len:6}
fn main() {
test("LSLSFSF")
test("LSLSFF")
test("LLSFSF")
test("LLSFF")
}
fn test(src string) {
tests := 100000
mut sum := 0
for _ in 0..tests {
sum += method(src)
}
println('${m_string(src)} produces ${100.0 * f32(sum) / f32(tests)}% deaths.')
}
fn rshift() {
t := cylinder[5]
for i := 4; i >= 0; i-- {
cylinder[i+1] = cylinder[i]
}
cylinder[0] = t
}
fn unload() {
for i := 0; i < 6; i++ {
cylinder[i] = false
}
}
fn load() {
for cylinder[0] {
rshift()
}
cylinder[0] = true
rshift()
}
fn spin() {
mut lim := 1 + rand.intn(6) or {exit(1)}
for i := 1; i < lim; i++ {
rshift()
}
}
fn fire() bool {
shot := cylinder[0]
rshift()
return shot
}
fn method(s string) int {
unload()
for c in s {
match c.ascii_str() {
'L' {load()}
'S' {spin()}
'F' {if fire() == true {return 1}}
else {}
}
}
return 0
}
fn m_string(s string) string {
mut l := []string{}
for c in s {
match c.ascii_str() {
'L' {l << "load"}
'S' {l << "spin"}
'F' {l << "fire"}
else {}
}
}
return l.join(', ')
}
</syntaxhighlight>
{{out}}
<pre>
load, spin, load, spin, fire, spin, fire produces 55.795% deaths.
load, spin, load, spin, fire, fire produces 58.453% deaths.
load, load, spin, fire, spin, fire produces 55.468% deaths.
load, load, spin, fire, fire produces 49.868% deaths.
</pre>
=={{header|Wren}}==
{{libheader|Wren-fmt}}
<
import "./fmt" for Fmt
var Rand = Random.new()
Line 1,488 ⟶ 1,992:
for (t in 1..tests) sum = sum + rev.method(m)
Fmt.print("$-40s produces $6.3f\% deaths.", Revolver.mstring(m), sum * 100 / tests)
}</
{{out}}
|