Dice game probabilities: Difference between revisions

Add C# implementation
m (→‎optimized: added whitespace.)
(Add C# implementation)
 
(47 intermediate revisions by 25 users not shown)
Line 11:
=={{header|11l}}==
{{trans|C}}
<langsyntaxhighlight lang="11l">F throw_die(n_sides, n_dice, s, [Int] &counts)
I n_dice == 0
counts[s]++
Line 37:
 
print(‘#.16’.format(beating_probability(4, 9, 6, 6)))
print(‘#.16’.format(beating_probability(10, 5, 7, 6)))</langsyntaxhighlight>
 
{{out}}
Line 43:
0.5731440767829814
0.6427886287176272
</pre>
 
 
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit
 
BYTE FUNC Roll(BYTE sides,dices)
BYTE i,sum
 
sum=0
FOR i=1 TO dices
DO
sum==+Rand(sides)+1
OD
RETURN (sum)
 
PROC Test(BYTE sides1,dices1,sides2,dices2)
INT i,count=[10000],sum1,sum2,wins1,wins2,draws
REAL r1,r2,p
 
wins1=0 wins2=0 draws=0
FOR i=1 TO count
DO
sum1=Roll(sides1,dices1)
sum2=Roll(sides2,dices2)
IF sum1>sum2 THEN
wins1==+1
ELSEIF sum1<sum2 THEN
wins2==+1
ELSE
draws==+1
FI
OD
 
IntToReal(wins1,r1)
IntToReal(wins2,r2)
RealDiv(r2,r1,p)
 
PrintF("Tested %I times%E",count)
PrintF("Player 1 with %B dice of %B sides%E",dices1,sides1)
PrintF("Player 2 with %B dice of %B sides%E",dices2,sides2)
PrintF("Player 1 wins %I times%E",wins1)
PrintF("Player 2 wins %I times%E",wins2)
PrintF("Draw %I times%E",draws)
Print("Player 1 beating Player 2 probability:")
PrintRE(p)
PutE()
RETURN
 
PROC Main()
Put(125) PutE() ;clear the screen
 
Test(4,9,6,6)
Test(10,5,7,6)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Dice_game_probabilities.png Screenshot from Atari 8-bit computer]
<pre>
Tested 10000 times
Player 1 with 9 dice of 4 sides
Player 2 with 6 dice of 6 sides
Player 1 wins 5770 times
Player 2 wins 3493 times
Draw 737 times
Player 1 beating Player 2 probability:
.6053726169
 
Tested 10000 times
Player 1 with 5 dice of 10 sides
Player 2 with 6 dice of 7 sides
Player 1 wins 6417 times
Player 2 wins 3140 times
Draw 443 times
Player 1 beating Player 2 probability:
.4893252298
</pre>
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
 
procedure Main is
package real_io is new Float_IO (Long_Float);
use real_io;
 
type Dice is record
Faces : Positive;
Num_Dice : Positive;
end record;
 
procedure Roll_Dice (The_Dice : in Dice; Count : out Natural) is
subtype Faces is Integer range 1 .. The_Dice.Faces;
package Die_Random is new Ada.Numerics.Discrete_Random (Faces);
use Die_Random;
Seed : Generator;
begin
Reset (Seed);
Count := 0;
for I in 1 .. The_Dice.Num_Dice loop
Count := Count + Random (Seed);
end loop;
end Roll_Dice;
 
function Win_Prob
(Dice_1 : Dice; Dice_2 : Dice; Tries : Positive) return Long_Float
is
Count_1 : Natural := 0;
Count_2 : Natural := 0;
Count_1_Wins : Natural := 0;
begin
for I in 1 .. Tries loop
Roll_Dice (Dice_1, Count_1);
Roll_Dice (Dice_2, Count_2);
if Count_1 > Count_2 then
Count_1_Wins := Count_1_Wins + 1;
end if;
end loop;
return Long_Float (Count_1_Wins) / Long_Float (Tries);
end Win_Prob;
 
D1 : Dice := (Faces => 4, Num_Dice => 9);
D2 : Dice := (Faces => 6, Num_Dice => 6);
D3 : Dice := (Faces => 10, Num_Dice => 5);
D4 : Dice := (Faces => 7, Num_Dice => 6);
 
P1 : Long_Float := Win_Prob (D1, D2, 1_000_000);
P2 : Long_Float := Win_Prob (D3, D4, 1_000_000);
begin
Put ("Dice D1 wins = ");
Put (Item => P1, Fore => 1, Aft => 7, Exp => 0);
New_Line;
Put ("Dice D2 wins = ");
Put (Item => P2, Fore => 1, Aft => 7, Exp => 0);
New_Line;
end Main;
</syntaxhighlight>
{{output}}
<pre>
Dice D1 wins = 0.5727800
Dice D2 wins = 0.6427660
</pre>
 
=={{header|BASIC}}==
==={{header|BASIC256}}===
{{trans|Yabasic}}
<syntaxhighlight lang="basic256">dado1 = 9: lado1 = 4
dado2 = 6: lado2 = 6
total1 = 0: total2 = 0
 
for i = 0 to 1
for cont = 1 to 100000
jugador1 = lanzamiento(dado1, lado1)
jugador2 = lanzamiento(dado2, lado2)
if jugador1 > jugador2 then
total1 = total1 + 1
else
if jugador1 <> jugador2 then total2 = total2 + 1
endif
next cont
 
print "Lanzado el dado "; (cont - 1); " veces"
print "jugador1 con "; dado1; " dados de "; lado1; " lados"
print "jugador2 con "; dado2; " dados de "; lado2; " lados"
print "Total victorias jugador1 = "; total1; " => "; left(string(total2 / total1), 9)
print "Total victorias jugador2 = "; total2
print (cont - 1) - (total1 + total2); " empates" + chr(10)
 
dado1 = 5: lado1 = 10
dado2 = 6: lado2 = 7
total1 = 0: total2 = 0
next i
end
 
function lanzamiento(dado, lado)
total = 0
 
for lanza = 1 to dado
total = total + int(rand * lado) + 1
next lanza
return total
end function</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de Yabasic.
</pre>
 
==={{header|FreeBASIC}}===
{{trans|Gambas}}
<syntaxhighlight lang="freebasic">Dim As Integer lado, jugador1, jugador2, total1, total2, cont, i
Dim As Integer dado1 = 9, lado1 = 4
Dim As Integer dado2 = 6, lado2 = 6
 
Randomize Timer
 
Function Lanzamiento(dado As Integer, lado As Integer) As Integer
Dim As Short lanza, total
For lanza = 1 To dado
total += Int(Rnd * lado) + 1
Next lanza
Return total
End Function
 
For i = 0 To 1
For cont = 1 To 100000
jugador1 = Lanzamiento(dado1, lado1)
jugador2 = Lanzamiento(dado2, lado2)
If jugador1 > jugador2 Then
total1 += 1
Elseif jugador1 <> jugador2 Then
total2 += 1
End If
Next cont
Print Using "Lanzado el dado & veces"; (cont - 1)
Print "jugador1 con"; dado1; " dados de"; lado1; " lados"
Print "jugador2 con"; dado2; " dados de"; lado2; " lados"
Print Using "Total victorias jugador1 = & => #.#######"; total1; (total2 / total1)
Print "Total victorias jugador2 ="; total2
Print (cont - 1) - (total1 + total2); !" empates\n"
dado1 = 5: lado1 = 10
dado2 = 6: lado2 = 7
total1 = 0: total2 = 0
Next i
 
Sleep</syntaxhighlight>
{{out}}
<pre>
Lanzado el dado 100000 veces
jugador1 con 9 dados de 4 lados
jugador2 con 6 dados de 6 lados
Total victorias jugador1 = 57274 => 0.6237211
Total victorias jugador2 = 35723
7003 empates
 
Lanzado el dado 100000 veces
jugador1 con 5 dados de 10 lados
jugador2 con 6 dados de 7 lados
Total victorias jugador1 = 64093 => 0.4893826
Total victorias jugador2 = 31366
4541 empates
</pre>
 
==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="yabasic">dado1 = 9: lado1 = 4
dado2 = 6: lado2 = 6
total1 = 0: total2 = 0
 
for i = 0 to 1
for cont = 1 to 100000
jugador1 = lanzamiento(dado1, lado1)
jugador2 = lanzamiento(dado2, lado2)
if jugador1 > jugador2 then
total1 = total1 + 1
elseif jugador1 <> jugador2 then
total2 = total2 + 1
endif
next cont
print "Lanzado el dado ", (cont - 1), " veces"
print "jugador1 con ", dado1, " dados de ", lado1, " lados"
print "jugador2 con ", dado2, " dados de ", lado2, " lados"
print "Total victorias jugador1 = ", total1, " => ", (total2 / total1)
print "Total victorias jugador2 = ", total2
print (cont - 1) - (total1 + total2), " empates\n"
dado1 = 5: lado1 = 10
dado2 = 6: lado2 = 7
total1 = 0: total2 = 0
next i
 
sub lanzamiento(dado, lado)
local lanza, total
for lanza = 1 to dado
total = total + int(ran(lado)) + 1
next lanza
return total
end sub</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdint.h>
 
Line 100 ⟶ 385:
printf("%1.16f\n", beating_probability(10, 5, 7, 6));
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>0.5731440767829801
0.6427886287176260</pre>
 
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
 
class Program
{
static uint MinOf(uint x, uint y)
{
return x < y ? x : y;
}
 
static void ThrowDie(uint nSides, uint nDice, uint s, uint[] counts)
{
if (nDice == 0)
{
counts[s]++;
return;
}
for (uint i = 1; i <= nSides; i++)
{
ThrowDie(nSides, nDice - 1, s + i, counts);
}
}
 
static double BeatingProbability(uint nSides1, uint nDice1, uint nSides2, uint nDice2)
{
uint len1 = (nSides1 + 1) * nDice1;
uint[] c1 = new uint[len1]; // initialized to zero by default
ThrowDie(nSides1, nDice1, 0, c1);
 
uint len2 = (nSides2 + 1) * nDice2;
uint[] c2 = new uint[len2];
ThrowDie(nSides2, nDice2, 0, c2);
double p12 = Math.Pow(nSides1, nDice1) * Math.Pow(nSides2, nDice2);
 
double tot = 0.0;
for (uint i = 0; i < len1; i++)
{
for (uint j = 0; j < MinOf(i, len2); j++)
{
tot += (double)(c1[i] * c2[j]) / p12;
}
}
return tot;
}
 
static void Main(string[] args)
{
Console.WriteLine(BeatingProbability(4, 9, 6, 6));
Console.WriteLine(BeatingProbability(10, 5, 7, 6));
}
}
</syntaxhighlight>
{{out}}
<pre>
0.573144076782982
0.642788628717627
 
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <cmath>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <map>
 
// Returns map from sum of faces to number of ways it can happen
std::map<uint32_t, uint32_t> get_totals(uint32_t dice, uint32_t faces) {
std::map<uint32_t, uint32_t> result;
for (uint32_t i = 1; i <= faces; ++i)
result.emplace(i, 1);
for (uint32_t d = 2; d <= dice; ++d) {
std::map<uint32_t, uint32_t> tmp;
for (const auto& p : result) {
for (uint32_t i = 1; i <= faces; ++i)
tmp[p.first + i] += p.second;
}
tmp.swap(result);
}
return result;
}
 
double probability(uint32_t dice1, uint32_t faces1, uint32_t dice2, uint32_t faces2) {
auto totals1 = get_totals(dice1, faces1);
auto totals2 = get_totals(dice2, faces2);
double wins = 0;
for (const auto& p1 : totals1) {
for (const auto& p2 : totals2) {
if (p2.first >= p1.first)
break;
wins += p1.second * p2.second;
}
}
double total = std::pow(faces1, dice1) * std::pow(faces2, dice2);
return wins/total;
}
 
int main() {
std::cout << std::setprecision(10);
std::cout << probability(9, 4, 6, 6) << '\n';
std::cout << probability(5, 10, 6, 7) << '\n';
return 0;
}</syntaxhighlight>
 
{{out}}
<pre>
0.5731440768
0.6427886287
</pre>
 
=={{header|Common Lisp}}==
''DRAFT''
 
====1. Note====
 
We use total probability rule.
 
====2. Program====
 
Player i gets s<sub>i</sub> points as the sum of rolling n<sub>i</sub> dices, each with f<sub>i</sub> faces.
 
<syntaxhighlight lang=lisp>(defun n-ways (n f s &optional (mem (make-array '(999 99) :initial-element -1)))
(cond ((and (= n 0) (= s 0)) 1)
((or (= n 0) (<= s 0)) 0)
((>= (aref mem s n) 0) (aref mem s n))
(t (loop for i from 1 to f
sum (n-ways (1- n) f (- s i) mem) into total
finally (return (setf (aref mem s n) total))))))
 
(defun winning-probability (n1 f1 n2 f2 &aux (w 0))
(loop for i from n1 to (* n1 f1)
do (loop for j from n2 to (* n2 f2)
do (if (> i j)
(setf w (+ w (* (n-ways n1 f1 i) (n-ways n2 f2 j))))))
finally (return (/ w (* (expt f1 n1) (expt f2 n2))))))</syntaxhighlight>
 
==== 3. Execution ====
 
<pre>(winning-probability 9 4 6 6)
(winning-probability 5 10 6 7)</pre>
 
{{out}}
<pre>48679795/84934656 ; ≈ 0.573
3781171969/5882450000 ; ≈ 0.643</pre>
 
That's all Folks !
 
''cyril nocton (cyril.nocton@gmail.com) w/ google translate''
 
=={{header|D}}==
===version 1===
<langsyntaxhighlight lang="d">import std.stdio, std.range, std.algorithm;
 
void throwDie(in uint nSides, in uint nDice, in uint s, uint[] counts)
Line 141 ⟶ 577:
writefln("%1.16f", beatingProbability!(4, 9, 6, 6));
writefln("%1.16f", beatingProbability!(10, 5, 7, 6));
}</langsyntaxhighlight>
{{out}}
<pre>0.5731440767829801
Line 148 ⟶ 584:
===version 2 (Faster Alternative Version)===
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.range, std.algorithm;
 
ulong[] combos(R)(R sides, in uint n) pure nothrow @safe
Line 186 ⟶ 622:
writefln("%1.16f", winning(iota(1u, 5u), 9, iota(1u, 7u), 6));
writefln("%1.16f", winning(iota(1u, 11u), 5, iota(1u, 8u), 6));
}</langsyntaxhighlight>
{{out}}
<pre>0.5731440767829801
0.6427886287176262</pre>
 
=={{header|EasyLang}}==
{{trans|Phix}}
<syntaxhighlight>
proc throw_die n_sides n_dice s . counts[] .
if n_dice = 0
counts[s] += 1
return
.
for i = 1 to n_sides
throw_die n_sides (n_dice - 1) (s + i) counts[]
.
.
func proba n_sides1 n_dice1 n_sides2 n_dice2 .
len c1[] (n_sides1 + 1) * n_dice1
len c2[] (n_sides2 + 1) * n_dice2
throw_die n_sides1 n_dice1 0 c1[]
throw_die n_sides2 n_dice2 0 c2[]
p12 = pow n_sides1 n_dice1 * pow n_sides2 n_dice2
for i = 1 to len c1[]
for j = 1 to lower (i - 1) len c2[]
tot += c1[i] * c2[j] / p12
.
.
return tot
.
numfmt 5 0
print proba 4 9 6 6
print proba 10 5 7 6
</syntaxhighlight>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: dice generalizations kernel math prettyprint sequences ;
IN: rosetta-code.dice-probabilities
 
Line 200 ⟶ 666:
 
9 4 6 6 winning-prob
5 10 6 7 winning-prob [ . ] bi@</langsyntaxhighlight>
{{out}}
<pre>
Line 206 ⟶ 672:
0.64174
</pre>
 
=={{header|Forth}}==
{{works with|gforth|0.7.3}}
<br>
<syntaxhighlight lang="forth">#! /usr/bin/gforth
 
\ Dice game probabilities
 
: min? ( addr -- min )
@
;
 
: max? ( addr -- max )
cell + @
;
 
: max+1-min? ( addr -- max+1 min )
dup max? 1+ swap min?
;
 
: addr? ( addr x -- addr' )
over min? - 2 + cells +
;
 
: weight? ( addr x -- w )
2dup swap min? < IF
2drop 0
ELSE
2dup swap max? > IF
2drop 0
ELSE
addr? @
THEN
THEN
;
 
: total-weight? ( addr -- w )
dup max? 1+ ( addr max+1 )
over min? ( addr max+1 min )
0 -rot ?DO ( adrr 0 max+1 min )
over i weight? +
LOOP
nip
;
 
: uniform-aux ( min max x -- addr )
>r 2dup
2dup swap - 3 + cells allocate throw ( min max min max addr )
tuck cell + ! ( min max min addr )
tuck ! ( min max addr )
-rot swap ( addr max min )
r> -rot ( addr x max min )
- 3 + 2 ?DO ( addr x )
2dup swap i cells + !
LOOP
drop
;
 
: convolve { addr1 addr2 -- addr }
addr1 min? addr2 min? +
addr1 max? addr2 max? +
0 uniform-aux { addr }
addr1 max+1-min? ?DO
addr2 max+1-min? ?DO
addr1 j weight?
addr2 i weight? *
addr i j + addr? +!
LOOP
LOOP
addr
;
 
: even? ( n -- f )
2 mod 0=
;
 
: power ( addr exp -- addr' )
dup 1 = IF
drop
ELSE
dup even? IF
2/ recurse dup convolve
ELSE
over swap 2/ recurse dup convolve convolve
THEN
THEN
;
 
: .dist { addr -- }
addr total-weight? { tw }
addr max+1-min? ?DO
i 10 .r
addr i weight? dup 20 .r
0 d>f tw 0 d>f f/ ." " f. cr
LOOP
;
 
: dist-cmp { addr1 addr2 xt -- p }
0
addr1 max+1-min? ?DO
addr2 max+1-min? ?DO
j i xt execute IF
addr1 j weight?
addr2 i weight?
* +
THEN
LOOP
LOOP
0 d>f
addr1 total-weight? addr2 total-weight? um* d>f
f/
;
 
: dist> ( addr1 addr2 -- p )
['] > dist-cmp
;
 
\ creates the uniform distribution with outcomes from min to max
: uniform ( min max -- addr )
1 uniform-aux
;
 
\ example
 
1 4 uniform 9 power
1 6 uniform 6 power
dist> f. cr
 
1 10 uniform 5 power
1 7 uniform 6 power
dist> f. cr
 
bye
</syntaxhighlight>
 
{{out}}
<pre>
time ./dice-game-probabilities.fs
0.57314407678298
0.642788628717626
 
real 0m0,008s
user 0m0,005s
sys 0m0,003s
</pre>
 
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
local fn RollTheDice( dice as long, sides as long ) as long
long i, total = 0
for i = 1 to dice
total += rnd(sides)
next
end fn = total
 
 
void local fn CaclulateProbabilities( dice1 as long, sides1 as long, dice2 as long, sides2 as long )
long i, player1, player2
float total1 = 0, total2 = 0, total3 = 0
for i = 1 to 100000
player1 = fn RollTheDice( dice1, sides1 )
player2 = fn RollTheDice( dice2, sides2 )
if ( player1 > player2 ) then total1++ : continue
if ( player1 < player2 ) then total2++ : continue
if ( player1 == player2 ) then total3++ : continue
next
printf @"Dice cast %ld times.", i - 1
printf @"Player 1 with %ld dice of %ld sides.", dice1, sides1
printf @"Player 2 with %ld dice of %ld sides.", dice2, sides2
printf @"Total wins Player 1 = %.f. Probability of winning: %0.4f%%.", total1, (total1 / i ) * 100
printf @"Total wins Player 2 = %.f", total2
printf @"Number of ties: %.f.", total3
end fn
 
randomize
print
fn CaclulateProbabilities( 9, 4, 6, 6 )
print
fn CaclulateProbabilities( 5, 10, 6, 7 )
print
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
Dice cast 100000 times.
Player 1 with 9 dice of 4 sides.
Player 2 with 6 dice of 6 sides.
Total wins Player 1 = 57301. Probability of winning: 57.3004%.
Total wins Player 2 = 35733
Number of ties: 6966.
 
Dice cast 100000 times.
Player 1 with 5 dice of 10 sides.
Player 2 with 6 dice of 7 sides.
Total wins Player 1 = 64289. Probability of winning: 64.2884%.
Total wins Player 2 = 31296
Number of ties: 4415.
</pre>
 
 
 
=={{header|Gambas}}==
'''[https://gambas-playground.proko.eu/?gist=ef255e4239a713aba35598a4617af3c9 Click this link to run this code]'''
<langsyntaxhighlight lang="gambas">' Gambas module file
 
Public Sub Main()
Line 257 ⟶ 929:
Return iTotal
 
End</langsyntaxhighlight>
Output:
<pre>
Line 277 ⟶ 949:
=={{header|Go}}==
{{trans|C}}
<langsyntaxhighlight lang="go">package main
 
import(
Line 324 ⟶ 996:
fmt.Println(beatingProbability(4, 9, 6, 6))
fmt.Println(beatingProbability(10, 5, 7, 6))
}</langsyntaxhighlight>
 
{{out}}
Line 334 ⟶ 1,006:
More idiomatic go:
 
<langsyntaxhighlight lang="go">package main
 
import (
Line 365 ⟶ 1,037:
fmt.Println(set{9, 4}.beats(set{6, 6}, 1000))
fmt.Println(set{5, 10}.beats(set{6, 7}, 1000))
}</langsyntaxhighlight>
 
{{out}}
Line 374 ⟶ 1,046:
=={{header|Haskell}}==
{{trans|Python}}
<langsyntaxhighlight lang="haskell">import Control.Monad (replicateM)
import Data.List (group, sort)
 
Line 395 ⟶ 1,067:
main = do
print $ (4, 9) `succeeds` (6, 6)
print $ (10, 5) `succeeds` (7, 6)</langsyntaxhighlight>
{{out}}
<pre>0.5731440767829815
Line 402 ⟶ 1,074:
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight Jlang="j">gen_dict =: (({. , #)/.~@:,@:(+/&>)@:{@:(# <@:>:@:i.)~ ; ^)&x:
 
beating_probability =: dyad define
Line 408 ⟶ 1,080:
'C1 P1' =. gen_dict/ y
(C0 +/@:,@:(>/&:({."1) * */&:({:"1)) C1) % (P0 * P1)
)</langsyntaxhighlight>
'''Example Usage:'''
<langsyntaxhighlight Jlang="j"> 10 5 (;x:inv)@:beating_probability 7 6
┌─────────────────────┬────────┐
│3781171969r5882450000│0.642789│
Line 417 ⟶ 1,089:
┌─────────────────┬────────┐
│48679795r84934656│0.573144│
└─────────────────┴────────┘</langsyntaxhighlight>
gen_dict explanation:<br>
<code>gen_dict</code> is akin to <code>gen_dict</code> in the python solution and
Line 441 ⟶ 1,113:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import java.util.Random;
 
public class Dice{
Line 498 ⟶ 1,170:
System.out.println("p1 wins " + (100.0 * p1Wins / rolls) + "% of the time");
}
}</langsyntaxhighlight>
{{out}}
<pre>10000 rolls, p1 = 9d4, p2 = 6d6
Line 511 ⟶ 1,183:
1000000 rolls, p1 = 5d10, p2 = 6d7
p1 wins 64.279% of the time</pre>
 
=={{header|JavaScript}}==
===simulating===
<syntaxhighlight lang="javascript">
let Player = function(dice, faces) {
this.dice = dice;
this.faces = faces;
this.roll = function() {
let results = [];
for (let x = 0; x < dice; x++)
results.push(Math.floor(Math.random() * faces +1));
return eval(results.join('+'));
}
}
 
function contest(player1, player2, rounds) {
let res = [0, 0, 0];
for (let x = 1; x <= rounds; x++) {
let a = player1.roll(),
b = player2.roll();
switch (true) {
case (a > b): res[0]++; break;
case (a < b): res[1]++; break;
case (a == b): res[2]++; break;
}
}
document.write(`
<p>
<b>Player 1</b> (${player1.dice} × d${player1.faces}): ${res[0]} wins<br>
<b>Player 2</b> (${player2.dice} × d${player2.faces}): ${res[1]} wins<br>
<b>Draws:</b> ${res[2]}<br>
Chances for Player 1 to win:
~${Math.round(res[0] / eval(res.join('+')) * 100)} %
</p>
`);
}
 
let p1, p2;
 
p1 = new Player(9, 4),
p2 = new Player(6, 6);
contest(p1, p2, 1e6);
 
p1 = new Player(5, 10);
p2 = new Player(6, 7);
contest(p1, p2, 1e6);
</syntaxhighlight>
{{out}}
<pre>
Player 1 (9 × d4): 572753 wins
Player 2 (6 × d6): 356478 wins
Draws: 70769
Chances for Player 1 to win: ~57 %
 
Player 1 (5 × d10): 643127 wins
Player 2 (6 × d7): 312151 wins
Draws: 44722
Chances for Player 1 to win: ~64 %
</pre>
 
=={{header|jq}}==
{{trans|Wren}}
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq"># To take advantage of gojq's arbitrary-precision integer arithmetic:
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);
 
# Input: an array (aka: counts)
def throwDie($nSides; $nDice; $s):
if $nDice == 0
then .[$s] += 1
else reduce range(1; $nSides + 1) as $i (.;
throwDie($nSides; $nDice-1; $s + $i) )
end ;
 
def beatingProbability(nSides1; nDice1; nSides2; nDice2):
def a: [range(0; .) | 0];
 
((nSides1 + 1) * nDice1) as $len1
| ($len1 | a | throwDie(nSides1; nDice1; 0)) as $c1
 
| ((nSides2 + 1) * nDice2) as $len2
| ($len2 | a | throwDie(nSides2; nDice2; 0)) as $c2
 
|((nSides1|power(nDice1)) * (nSides2|power(nDice2))) as $p12
 
| reduce range(0; $len1) as $i (0;
reduce range(0; [$i, $len2] | min) as $j (.;
. + ($c1[$i] * $c2[$j] / $p12) ) ) ;
 
beatingProbability(4; 9; 6; 6),
beatingProbability(10; 5; 7; 6)</syntaxhighlight>
{{out}}
<pre>
0.5731440767829815
0.6427886287176273
</pre>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">play(ndices::Integer, nfaces::Integer) = (nfaces, ndices) ∋ 0 ? 0 : sum(rand(1:nfaces) for i in 1:ndices)
 
simulate(d1::Integer, f1::Integer, d2::Integer, f2::Integer; nrep::Integer=1_000_000) =
Line 521 ⟶ 1,290:
 
println("\nPlayer 1: 9 dices, 4 faces\nPlayer 2: 6 dices, 6 faces\nP(Player1 wins) = ", simulate(9, 4, 6, 6))
println("\nPlayer 1: 5 dices, 10 faces\nPlayer 2: 6 dices, 7 faces\nP(Player1 wins) = ", simulate(5, 10, 6, 7))</langsyntaxhighlight>
 
{{out}}
Line 534 ⟶ 1,303:
=={{header|Kotlin}}==
{{trans|C}}
<langsyntaxhighlight lang="scala">// version 1.1.2
 
fun throwDie(nSides: Int, nDice: Int, s: Int, counts: IntArray) {
Line 568 ⟶ 1,337:
println(beatingProbability(4, 9, 6, 6))
println(beatingProbability(10, 5, 7, 6))
}</langsyntaxhighlight>
 
{{out}}
Line 578 ⟶ 1,347:
=={{header|Lua}}==
===Simulated===
<langsyntaxhighlight lang="lua">
local function simu(ndice1, nsides1, ndice2, nsides2)
local function roll(ndice, nsides)
Line 600 ⟶ 1,369:
simu(9, 4, 6, 6)
simu(5, 10, 6, 7)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 608 ⟶ 1,377:
 
===Computed===
<langsyntaxhighlight lang="lua">
local function comp(ndice1, nsides1, ndice2, nsides2)
local function throws(ndice, nsides)
Line 642 ⟶ 1,411:
comp(9, 4, 6, 6)
comp(5, 10, 6, 7)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 648 ⟶ 1,417:
computed: p1 = 5d10, p2 = 6d7, prob = 7562343938 / 11764900000 = 0.64278862871763
</pre>
 
=={{header|M2000 Interpreter}}==
Using a buffer of random numbers for all games.
 
 
<syntaxhighlight lang="m2000 interpreter">
Declare random1 lib "advapi32.SystemFunction036" {long lpbuffer, long length}
Flush
Prob(4, 9, 6, 6, 55555)
Prob(10, 5, 7, 6, 55555)
Sub Prob(face1 as long=4 ,dice1=9, face2 as long=6,dice2=6, games=1000)
if face1<1 or face1>256 or face2<1 or face2>256 then Error "Faces out of limits"
profiler
local m=@PlayAll(dice1,dice2, games), tt=timecount
print "Time to fill the buffer with random bytes ";str$(tt, "#0.00 ms")
local s1=dice1-1, s2=dice2-1, k, l, f1=face1/256, f2=face2/256, i, n1=0&, n2=0&
print "Buffer size ";str$(len(m)/1024,"#0.#");" Kbyte": Refresh
profiler
for i=0 to games-1
long n1=dice1:for j=0to s1{n1+=eval(m, i!n1!j)*f1}
long n2=dice2:for j=0to s2{n2+=eval(m, i!n2!j)*f2}
if n1>n2 then k++ else if n1<n2 then l++
next
print "Games Total "; games
print "Player 1 wins ";k; " probability of winning:" ;str$(k/games, "#0.00 %")
print "Player 2 wins ";l; " probability of winning:" ;str$(l/games, "#0.00 %")
print "Number of ties ";games-k-l
print "Execution time ";str$(timecount/1000, "#0.0 s")
End Sub
Function PlayAll(dice1, dice2, games as long)
if games<1 then error "games<1"
local onegame
structure onegame {
n1 as byte * dice1
n2 as byte * dice2
}
buffer Alfa as onegame*games
call void random1(alfa(0), len(alfa))
= Alfa
End Function
</syntaxhighlight>
{{out}}
<pre>
Time to fill the buffer with random bytes 2.00 ms
Buffer size 813.8 Kbyte
Games Total 55555
Player 1 wins 31870 probability of winning:57.37 %
Player 2 wins 19729 probability of winning:35.51 %
Number of ties 3956
Execution time 179.9 s
 
Time to fill the buffer with random bytes 1.65 ms
Buffer size 596.8 Kbyte
Games Total 55555
Player 1 wins 35441 probability of winning:63.79 %
Player 2 wins 17605 probability of winning:31.69
Number of ties 2509
Execution time 138.7 s
</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[GetProbability]
GetProbability[{dice1_List, n_Integer}, {dice2_List, m_Integer}] :=
Module[{a, b, lena, lenb},
a = Tuples[dice1, n];
a = Plus @@@ a;
lena = a // Length;
a = Tally[a];
a[[All, 2]] /= lena;
b = Tuples[dice2, m];
b = Plus @@@ b;
lenb = b // Length;
b = Tally[b];
b[[All, 2]] /= lenb;
Total[If[#[[1, 1]] > #[[2, 1]], #[[1, 2]] #[[2, 2]], 0] & /@
Tuples[{a, b}]]
]
GetProbability[{Range[4], 9}, {Range[6], 6}]
GetProbability[{Range[10], 5}, {Range[7], 6}]</syntaxhighlight>
{{out}}
<pre>48679795/84934656
3781171969/5882450000</pre>
 
=={{header|Nim}}==
{{libheader|bignum}}
<syntaxhighlight lang="nim">import bignum
from math import sum
 
proc counts(ndices, nsides: int): seq[int] =
result.setlen(ndices * nsides + 1)
for i in 1..nsides:
result[i] = 1
for i in 1..<ndices:
var c = newSeq[int](result.len)
for sum in i..(i * nsides):
for val in 1..nsides:
inc c[sum + val], result[sum]
result = move(c)
 
proc probabilities(counts: seq[int]): seq[Rat] =
result.setLen(counts.len)
let total = sum(counts)
for i, n in counts:
result[i] = newRat(n, total)
 
proc beatingProbability(ndices1, nsides1, ndices2, nsides2: int): Rat =
let counts1 = counts(ndices1, nsides1)
let counts2 = counts(ndices2, nsides2)
var p1 = counts1.probabilities()
var p2 = counts2.probabilities()
 
result = newRat(0)
for sum1 in ndices1..p1.high:
var p = newRat(0)
for sum2 in ndices2..min(sum1 - 1, p2.high):
p += p2[sum2]
result += p1[sum1] * p
 
echo beatingProbability(9, 4, 6, 6).toFloat
echo beatingProbability(5, 10, 6, 7).toFloat</syntaxhighlight>
 
{{out}}
<pre>0.5731440767829801
0.6427886287176261</pre>
 
=={{header|ooRexx}}==
===Algorithm===
<langsyntaxhighlight lang="oorexx">Numeric Digits 30
Call test '9 4 6 6'
Call test '5 10 6 7'
Line 707 ⟶ 1,602:
psum+=p1.x
End
Return</langsyntaxhighlight>
{{out}}
<pre>Player 1 has 9 dice with 4 sides each
Line 718 ⟶ 1,613:
 
===Algorithm using rational arithmetic===
<langsyntaxhighlight lang="oorexx">Numeric Digits 30
Call test '9 4 6 6'
Call test '5 10 6 7'
Line 820 ⟶ 1,715:
Parse Arg a,b
if b = 0 then return abs(a)
return ggt(b,a//b)</langsyntaxhighlight>
{{out}}
<pre>Player 1 has 9 dice with 4 sides each
Line 834 ⟶ 1,729:
===Algorithm using class fraction===
Class definition adapted from Arithmetic/Raional.
<langsyntaxhighlight lang="oorexx">Numeric Digits 50
Call test '9 4 6 6'
Call test '5 10 6 7'
Line 992 ⟶ 1,887:
::attribute denominator GET
 
::requires rxmath library</langsyntaxhighlight>
{{out}}
<pre>Player 1 has 9 dice with 4 sides each
Line 1,006 ⟶ 1,901:
===Test===
Result from 10 million tries.
<langsyntaxhighlight lang="oorexx">oid='diet.xxx'; Call sysFileDelete oid
Call test '9 4 6 6'
Call test '5 10 6 7'
Line 1,051 ⟶ 1,946:
o:
Say arg(1)
Return lineout(oid,arg(1))</langsyntaxhighlight>
 
{{out}}
Line 1,069 ⟶ 1,964:
=={{header|Perl}}==
{{trans|Python}}
<langsyntaxhighlight lang="perl">use List::Util qw(sum0 max);
 
sub comb {
Line 1,103 ⟶ 1,998:
 
print '(', join(', ', winning([1 .. 4], 9, [1 .. 6], 6)), ")\n";
print '(', join(', ', winning([1 .. 10], 5, [1 .. 7], 6)), ")\n";</langsyntaxhighlight>
{{out}}
<pre>
Line 1,112 ⟶ 2,007:
=={{header|Phix}}==
{{trans|Go}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function throwDie(integer nSides, nDice, s, sequence counts)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
if nDice == 0 then
<span style="color: #008080;">function</span> <span style="color: #000000;">throwDie</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">nSides</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">)</span>
counts[s] += 1
<span style="color: #008080;">if</span> <span style="color: #000000;">nDice</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
for i=1 to nSides do
<span style="color: #008080;">else</span>
counts = throwDie(nSides, nDice-1, s+i, counts)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nSides</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">counts</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">throwDie</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nSides</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">+</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">counts</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return counts
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">counts</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function beatingProbability(integer nSides1, nDice1, nSides2, nDice2)
integer len1 := (nSides1 + 1) * nDice1,
<span style="color: #008080;">function</span> <span style="color: #000000;">beatingProbability</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">nSides1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nSides2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice2</span><span style="color: #0000FF;">)</span>
len2 := (nSides2 + 1) * nDice2
<span style="color: #004080;">integer</span> <span style="color: #000000;">len1</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">nSides1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">nDice1</span><span style="color: #0000FF;">,</span>
sequence c1 = throwDie(nSides1, nDice1, 0, repeat(0,len1)),
<span style="color: #000000;">len2</span> <span style="color: #0000FF;">:=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">nSides2</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">nDice2</span>
c2 = throwDie(nSides2, nDice2, 0, repeat(0,len2))
<span style="color: #004080;">sequence</span> <span style="color: #000000;">c1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">throwDie</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nSides1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len1</span><span style="color: #0000FF;">)),</span>
atom p12 := power(nSides1, nDice1) * power(nSides2, nDice2),
<span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">throwDie</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nSides2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len2</span><span style="color: #0000FF;">))</span>
tot := 0.0
<span style="color: #004080;">atom</span> <span style="color: #000000;">p12</span> <span style="color: #0000FF;">:=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nSides1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nSides2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nDice2</span><span style="color: #0000FF;">),</span>
for i=1 to len1 do
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0.0</span>
for j=1 to min(i-1,len2) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">len1</span> <span style="color: #008080;">do</span>
tot += (c1[i] * c2[j]) / p12
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">c2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">p12</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return tot
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">tot</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
printf(1,"%0.16f\n",beatingProbability(4, 9, 6, 6))
printf(1,"%0.16f\n",beatingProbability(10, 5, 7, 6))</lang>
<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;">"%0.16f\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">beatingProbability</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">))</span>
<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;">"%0.16f\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">beatingProbability</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">))</span>
<!--</syntaxhighlight>-->
{{out}}
<small>
Line 1,157 ⟶ 2,055:
=={{header|PL/I}}==
===version 1===
<langsyntaxhighlight lang="pli">*process source attributes xref;
dicegame: Proc Options(main);
Call test(9, 4,6,6);
Line 1,231 ⟶ 2,129:
End;
End;
End;</langsyntaxhighlight>
{{out}}
<pre>Player 1 has 9 dice with 4 sides each
Line 1,241 ⟶ 2,139:
Probability for player 1 to win: 0.642703175544738770</pre>
===version 2 using rational arithmetic===
<langsyntaxhighlight lang="pli">*process source attributes xref;
dgf: Proc Options(main);
Call test(9, 4,6,6);
Line 1,385 ⟶ 2,283:
End;
 
End;</langsyntaxhighlight>
{{out}}
<pre>Player 1 has 9 dice with 4 sides each
Line 1,398 ⟶ 2,296:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">from itertools import product
 
def gen_dict(n_faces, n_dice):
Line 1,416 ⟶ 2,314:
 
print beating_probability(4, 9, 6, 6)
print beating_probability(10, 5, 7, 6)</langsyntaxhighlight>
{{out}}
<pre>0.573144076783
Line 1,422 ⟶ 2,320:
 
To handle larger number of dice (and faster in general):
<langsyntaxhighlight lang="python">from __future__ import print_function, division
 
def combos(sides, n):
Line 1,447 ⟶ 2,345:
 
# mountains of dice test case
# print(winning((1, 2, 3, 5, 9), 700, (1, 2, 3, 4, 5, 6), 800))</langsyntaxhighlight>
{{out}}
<pre>
Line 1,455 ⟶ 2,353:
 
If we further restrict die faces to be 1 to n instead of arbitrary values, the combo generation can be made much faster:
<langsyntaxhighlight lang="python">from __future__ import division, print_function
from itertools import accumulate # Python3 only
 
Line 1,478 ⟶ 2,376:
print(winning(5, 10, 6, 7))
 
#print(winning(6, 700, 8, 540))</langsyntaxhighlight>
{{out}}
<pre>
Line 1,484 ⟶ 2,382:
0.6427886287176262
</pre>
 
=={{header|R}}==
Solving these sorts of problems by simulation is trivial in R.
<syntaxhighlight lang="rsplus">probability <- function(facesCount1, diceCount1, facesCount2, diceCount2)
{
mean(replicate(10^6, sum(sample(facesCount1, diceCount1, replace = TRUE)) > sum(sample(facesCount2, diceCount2, replace = TRUE))))
}
cat("Player 1's probability of victory is", probability(4, 9, 6, 6),
"in the first game and", probability(10, 5, 7, 6), "in the second.")</syntaxhighlight>
{{out}}
<pre>Player 1's probability of victory is 0.572652 in the first game and 0.642817 in the second.</pre>
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">#lang racket
 
(define probs# (make-hash))
Line 1,523 ⟶ 2,432:
 
(printf "GAME 2 (5D10 vs 6D7) [what is a D7?]~%")
(game-probs 5 10 6 7)</langsyntaxhighlight>
 
{{out}}
Line 1,540 ⟶ 2,449:
=={{header|Raku}}==
(formerly Perl 6)
{{Worksworks with|rakudoRakudo|20182020.0208.1}}
<syntaxhighlight lang="raku" perl6line>sub likelihoods ($roll) {
my ($dice, $faces) = $roll.comb(/\d+/);
my @counts;
Line 1,559 ⟶ 2,468:
 
# We're using standard DnD notation for dice rolls here.
say .gist, "\t", .perlraku given beating-probability < 9d4 6d6 >;
say .gist, "\t", .perlraku given beating-probability < 5d10 6d7 >;</langsyntaxhighlight>
{{out}}
<pre>0.573144077 <48679795/84934656>
Line 1,570 ⟶ 2,479:
{{trans|ooRexx}}
(adapted for Classic Rexx)
<langsyntaxhighlight lang="rexx">/* REXX */
Numeric Digits 30
Call test '9 4 6 6'
Line 1,633 ⟶ 2,542:
res=res p.x
End
Return res</langsyntaxhighlight>
{{out}}
<pre>
Line 1,646 ⟶ 2,555:
 
===version 2===
<langsyntaxhighlight lang="rexx">/* REXX */
oid='diet.xxx'; 'erase' oid
Call test '9 4 6 6'
Line 1,692 ⟶ 2,601:
o:
Say arg(1)
Return lineout(oid,arg(1))</langsyntaxhighlight>
{{out}}
<pre>Player 1: 9 dice with 4 sides each
Line 1,709 ⟶ 2,618:
===optimized===
This REXX version is an optimized and reduced version of the first part of the 1<sup>st</sup> REXX example.
<langsyntaxhighlight lang="rexx">/*REXX pgm computes and displays the probabilities of a two─player S─sided, N─dice game.*/
numeric digits 100 /*increase│decreaseincrease/decrease forto heart's desire. */
call game 9 4, 6 6 /*1st player: 9 dice, 4 sides; 2nd player: 6 dice, 6 sides*/
call game 5 10, 6 7 /* " " 5 " 10 " " " 6 " 7 " */
Line 1,717 ⟶ 2,626:
game: parse arg w.1 s.1, w.2 s.2 /*1st player(dice sides), 2nd player···*/
p.= 0
do j=1 for 2; @@.j= prob(w.j, s.j)
do k=w.j to w.j*s.j; parse var @@.j p.j.k @@.j; end /*k*/
end /*j*/
low.= 0
do j=w.1 to w.1*s.1
do k=0 for j; low.j= low.j + p.2.k; end /*k*/
end /*j*/
say ' Player 1 has ' w.1 " dice with " s.1 ' sides each.'
say ' Player 2 has ' w.2 " dice with " s.2 ' sides each.'
winP= 0
do j=w.1 to w.1*s.1; winP= winP + p.1.j * low.j
end /*j*/
say 'The probability for first player to win is ' format(winP*100, , 30digits()%2) "%."
say /* */
return /*displayshow 301/2 decimalof digits────┘100 dec. digits────┘ */
/*──────────────────────────────────────────────────────────────────────────────────────*/
prob: procedure; parse arg n,s,,@ $; #.= 0; pow= s**n
do j=1 for n; @= @'DO _'j"=1 forFOR" s';'; end /*j*/
@= @'_='; do k=1 for n-1; @= @"_"k'+' ; end /*k*/
interpret @'_'n"; #."_'= #.'_"+1" copies('; END', k)
ns= n*s; do j=0 to ns; p.j= #.j / pow; end /*j*/
do k=n to ns; $= $ p.k; end /*k*/
return $ /* ◄──────────────── probability of 1st player to win, S─sided, N dice.*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Player 1 has 9 dice with 4 sides each.
Player 2 has 6 dice with 6 sides each.
The probability for first player to win is 57.31440767829800829475308641975331440767829800829475308641975308641975308641975309 %.
 
Player 1 has 5 dice with 10 sides each.
Player 2 has 6 dice with 7 sides each.
The probability for first player to win is 64.27886287176261591683737218335927886287176261591683737218335897457691948082856633 %.
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">def roll_dice(n_dice, n_faces)
return [[0,1]] if n_dice.zero?
one = [1] * n_faces
Line 1,776 ⟶ 2,685:
puts "Probability for player 1 to win: #{win[1]} / #{sum}",
" -> #{win[1].fdiv(sum)}", ""
end</langsyntaxhighlight>
 
{{out}}
Line 1,789 ⟶ 2,698:
Probability for player 1 to win: 7562343938 / 11764900000
-> 0.6427886287176262
</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">// Returns a vector containing the number of ways each possible sum of face
// values can occur.
fn get_totals(dice: usize, faces: usize) -> Vec<f64> {
let mut result = vec![1.0; faces + 1];
for d in 2..=dice {
let mut tmp = vec![0.0; d * faces + 1];
for i in d - 1..result.len() {
for j in 1..=faces {
tmp[i + j] += result[i];
}
}
result = tmp;
}
result
}
 
fn probability(dice1: usize, faces1: usize, dice2: usize, faces2: usize) -> f64 {
let totals1 = get_totals(dice1, faces1);
let totals2 = get_totals(dice2, faces2);
let mut wins = 0.0;
let mut total = 0.0;
for i in dice1..totals1.len() {
for j in dice2..totals2.len() {
let n = totals1[i] * totals2[j];
total += n;
if j < i {
wins += n;
}
}
}
wins / total
}
 
fn main() {
println!("{}", probability(9, 4, 6, 6));
println!("{}", probability(5, 10, 6, 7));
}</syntaxhighlight>
 
{{out}}
<pre>
0.5731440767829801
0.6427886287176262
</pre>
 
=={{header|Sidef}}==
{{trans|Python}}
<langsyntaxhighlight lang="ruby">func combos(sides, n) {
n || return [1]
var ret = ([0] * (n*sides.max + 1))
Line 1,806 ⟶ 2,760:
var (win,loss,tie) = (0,0,0)
p1.each_kv { |i, x|
win += x*p2.ftfirst(0,i-1).sum
tie += x*p2.ftslice(i, i).first(1).sum
loss += x*p2.ftslice(i+1).sum
}
[win, tie, loss] »/» p1.sum*p2.sum
Line 1,822 ⟶ 2,776:
 
display_results('9D4 vs 6D6', winning(range(1, 4), 9, range(1,6), 6))
display_results('5D10 vs 6D7', winning(range(1,10), 5, range(1,7), 6))</langsyntaxhighlight>
{{out}}
<pre>
Line 1,839 ⟶ 2,793:
 
To handle the nested loop in <tt>NdK</tt>, [[Tcl]]'s metaprogramming abilities are exercised. The goal is to produce a script that looks like:
<langsyntaxhighlight Tcllang="tcl">foreach d0 {1 2 3 4 5 6} {
foreach d1 {1 2 3 4 5 6} {
...
Line 1,847 ⟶ 2,801:
...
}
}</langsyntaxhighlight>
 
See the comments attached to that procedure for a more thorough understanding of how that is achieved (with the caveat that <tt>$d0..$dN</tt> are reversed).
Line 1,853 ⟶ 2,807:
Such metaprogramming is a very powerful technique in Tcl for building scripts where other approaches (in this case, recursion) might not be appealing, and should be in every programmer's toolbox!
 
<langsyntaxhighlight Tcllang="tcl">proc range {b} { ;# a common standard proc: [range 5] -> {0 1 2 3 4}
set a 0
set res {}
Line 1,910 ⟶ 2,864:
puts [format "p1 has %dd%d; p2 has %dd%d" {*}$p1 {*}$p2]
puts [format " p1 wins with Pr(%s)" [win_pr [NdK {*}$p1] [NdK {*}$p2]]]
}</langsyntaxhighlight>
 
{{Out}}
Line 1,924 ⟶ 2,878:
I include this to <em>emphasise</em> the importance and power of metaprogramming in a Tcler's toolbox, as well as sharing a useful proc.
 
<langsyntaxhighlight Tcllang="tcl">package require Tcl 8.6 ;# for [tailcall] - otherwise use [uplevel 1 $script]
# This proc builds up a nested foreach call, then evaluates it.
#
Line 1,967 ⟶ 2,921:
foreach* {*}$args $script
return $sum
}</langsyntaxhighlight>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">import math
 
fn min_of(x int, y int) int {
if x < y {
return x
}
return y
}
fn throw_die(n_sides int, n_dice int, s int, mut counts []int) {
if n_dice == 0 {
counts[s]++
return
}
for i := int(1); i <= n_sides; i++ {
throw_die(n_sides, n_dice - 1, s + i, mut counts)
}
}
fn beating_probability(n_sides1 int, n_dice1 int, n_sides2 int, n_dice2 int) f64 {
len1 := (n_sides1 + 1) * n_dice1
mut c1 := []int{len: len1} // all elements zero by default
throw_die(n_sides1, n_dice1, 0, mut c1)
len2 := (n_sides2 + 1) * n_dice2
mut c2 := []int{len: len2}
throw_die(n_sides2, n_dice2, 0, mut c2)
p12 := math.pow(f64(n_sides1), f64(n_dice1)) *
math.pow(f64(n_sides2), f64(n_dice2))
mut tot := 0.0
for i := int(0); i < len1; i++ {
for j := int(0); j < min_of(i, len2); j++ {
tot += f64(c1[i] * c2[j]) / p12
}
}
return tot
}
fn main() {
println(beating_probability(4, 9, 6, 6))
println(beating_probability(10, 5, 7, 6))
}</syntaxhighlight>
 
{{out}}
<pre>
0.57314407678298
0.64278862871763
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">var throwDie // recursive
throwDie = Fn.new { |nSides, nDice, s, counts|
if (nDice == 0) {
counts[s] = counts[s] + 1
return
}
for (i in 1..nSides) throwDie.call(nSides, nDice-1, s + i, counts)
}
 
var beatingProbability = Fn.new { |nSides1, nDice1, nSides2, nDice2|
var len1 = (nSides1 + 1) * nDice1
var c1 = List.filled(len1, 0)
throwDie.call(nSides1, nDice1, 0, c1)
 
var len2 = (nSides2 + 1) * nDice2
var c2 = List.filled(len2, 0)
throwDie.call(nSides2, nDice2, 0, c2)
 
var p12 = nSides1.pow(nDice1) * nSides2.pow(nDice2)
var tot = 0
for (i in 0...len1) {
for (j in 0...i.min(len2)) {
tot = tot + c1[i] * c2[j] / p12
}
}
return tot
}
 
System.print(beatingProbability.call(4, 9, 6, 6))
System.print(beatingProbability.call(10, 5, 7, 6))</syntaxhighlight>
 
{{out}}
<pre>
0.57314407678298
0.64278862871763
</pre>
 
=={{header|zkl}}==
{{trans|Python}}
<langsyntaxhighlight lang="zkl">fcn combos(sides, n){
if(not n) return(T(1));
ret:=((0).max(sides)*n + 1).pump(List(),0);
Line 1,992 ⟶ 3,037:
s := p1.sum(0)*p2.sum(0);
return(win.toFloat()/s, tie.toFloat()/s, loss.toFloat()/s);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">println(winning([1..4].walk(), 9, [1..6].walk(),6));
println(winning([1..10].walk(),5, [1..7].walk(),6)); # this seem hardly fair</langsyntaxhighlight>
{{out}}
<pre>
337

edits