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}}
 
<langsyntaxhighlight lang="11l">UInt32 seed = 0
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))</langsyntaxhighlight>
 
{{out}}
Line 130:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">methods =
(
load, spin, load, spin, fire, spin, fire
Line 180:
sixGun[1] := temp
}
}</langsyntaxhighlight>
{{out}}
<pre>55.478% Deaths for : "load, spin, load, spin, fire, spin, fire"
Line 189:
=={{header|C}}==
{{trans|Go}}
<langsyntaxhighlight lang="c">#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
Line 308:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>load, spin, load, spin, fire, spin, fire produces 55.456% deaths.
Line 317:
=={{header|C++}}==
{{trans|C}}
<langsyntaxhighlight lang="cpp">#include <array>
#include <iomanip>
#include <iostream>
Line 444:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>load, spin, load, spin, fire, spin, fire produces 55.487% deaths.
Line 453:
=={{header|EasyLang}}==
{{trans|C}}
<syntaxhighlight>
<lang>len cyl[] 6
len cyl[] 6
func rshift . .
proc rshift . .
h = cyl[5]
for ih = 5 downto 1cyl[6]
for cyl[i] = cyl[i6 -downto 1]2
cyl[i] = cyl[i - 1]
.
cyl[0] = h.
cyl[1] = h
.
funcproc unload . .
for i range= 1 to 6
cyl[i] = 0
.
.
funcproc load . .
while cyl[01] = 1
call rshift
.
cyl[01] = 1
call rshift
.
funcproc spin . .
lim = randomrandint 6 + 1
for i = 1 to lim - 1
call rshift
.
.
func fire . shot .
shot = cyl[01]
call rshift
return shot
.
func method m[] . shot .
call unload
shot =for 0m in m[]
for m in if m[] = 1
if m = 0 load
callelif loadm = 2
elif m = 1 spin
callelif spinm = 3
elif m if fire = 21
call fire shot return 1
if shot = 1.
break 1
.
.
return 0
.
.
method$[] = [ "load" "spin" "fire" ]
funcproc test m[] . .
n = 100000
for i range= 1 to n
call sum += method m[] shot
.
sum += shot
for i = 1 to len m[]
.
for m in write method$[m[i]] & " "
.
write method$[m] & " "
print "-> " & 100 * sum / n & "% death"
.
print "-> " & 100 * sum / n & "% deaths"
.
call test [ 0 1 02 1 2 13 2 3 ]
call test [ 0 1 02 1 2 23 3 ]
call test [ 0 01 1 2 13 2 3 ]
call test [ 0 01 1 2 23 3 ]</lang>
</syntaxhighlight>
 
=={{header|Factor}}==
{{trans|Julia}}
{{trans|Python}}
<langsyntaxhighlight lang="factor">USING: accessors assocs circular formatting fry kernel literals
math random sequences ;
IN: rosetta-code.roulette
Line 556 ⟶ 557:
} [ run-test ] assoc-each ;
 
MAIN: main</langsyntaxhighlight>
{{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.
<langsyntaxhighlight lang="go">package main
 
import (
Line 658 ⟶ 748:
fmt.Printf("%-40s produces %6.3f%% deaths.\n", mstring(m), pc)
}
}</langsyntaxhighlight>
 
{{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}}==
<langsyntaxhighlight lang="javascript">
let Pistol = function(method) {
this.fired = false;
Line 722 ⟶ 979:
console.log();
}
</syntaxhighlight>
</lang>
{{out}}
Example:
Line 743 ⟶ 1,000:
=={{header|Julia}}==
{{trans|Python}}
<langsyntaxhighlight lang="julia">const cyl = zeros(Bool, 6)
 
function load()
Line 796 ⟶ 1,053:
 
testmethods()
</langsyntaxhighlight>{{out}}
<pre>
Method load, spin, load, spin, fire, spin, fire produces 55.54253 per cent deaths.
Line 806 ⟶ 1,063:
=={{header|Kotlin}}==
{{trans|C}}
<langsyntaxhighlight lang="scala">import kotlin.random.Random
 
val cylinder = Array(6) { false }
Line 907 ⟶ 1,164:
test("LLSFSF");
test("LLSFF");
}</langsyntaxhighlight>
{{out}}
<pre>load, spin, load, spin, fire, spin, fire produces 55.638% deaths.
Line 915 ⟶ 1,172:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">ClearAll[Unload, Load, Spin, Fire]
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]</langsyntaxhighlight>
{{out}}
<pre>0.55243
Line 1,010 ⟶ 1,267:
=={{header|Nim}}==
 
<langsyntaxhighlight Nimlang="nim">import algorithm, random, sequtils, strformat, strutils, tables
 
type
Line 1,053 ⟶ 1,310:
randomize()
for scenario in ["LSLSFSF", "LSLSFF", "LLSFSF", "LLSFF"]:
test(scenario)</langsyntaxhighlight>
 
{{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}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 1,114 ⟶ 1,460:
$total += &$ref for 1..$trials;
printf "%7s %.2f%%\n", $ref, $total / $trials * 100;
}</langsyntaxhighlight>
{{out}}
<pre>LSLSFSF 55.04%
Line 1,122 ⟶ 1,468:
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 1,180 ⟶ 1,526:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">""" Russian roulette problem """
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.")
</langsyntaxhighlight>{{out}}
<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" perl6line>unit sub MAIN ($shots = 6);
 
my @cyl;
Line 1,337 ⟶ 1,683:
 
say "{.fmt('%7s')}: %{(%revolver{$_} / $trials × 100).fmt('%.2f')}"
for <LSLSFSF LSLSFF LLSFSF LLSFF></langsyntaxhighlight>
{{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 &nbsp; '''200%''' &nbsp; faster.
<langsyntaxhighlight lang="rexx">/*REXX pgm simulates scenarios for a two─bullet Russian roulette game with a 6 cyl. gun.*/
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)</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs, &nbsp; showing that 2<sup>nd</sup> option &nbsp; '''B''' &nbsp; 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}}
<langsyntaxhighlight ecmascriptlang="wren">import "random" for Random
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)
}</langsyntaxhighlight>
 
{{out}}
2,122

edits