Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Dice-game-probabilities/00-META.yaml
Normal file
2
Task/Dice-game-probabilities/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Dice_game_probabilities
|
||||
9
Task/Dice-game-probabilities/00-TASK.txt
Normal file
9
Task/Dice-game-probabilities/00-TASK.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
Two players have a set of dice each. The first player has nine dice with four faces each, with numbers one to four. The second player has six normal dice with six faces each, each face has the usual numbers from one to six.
|
||||
|
||||
They roll their dice and sum the totals of the faces. The player with the highest total wins (it's a draw if the totals are the same). What's the probability of the first player beating the second player?
|
||||
|
||||
Later the two players use a different set of dice each. Now the first player has five dice with ten faces each, and the second player has six dice with seven faces each. Now what's the probability of the first player beating the second player?
|
||||
|
||||
This task was adapted from the Project Euler Problem n.205:
|
||||
https://projecteuler.net/problem=205
|
||||
|
||||
27
Task/Dice-game-probabilities/11l/dice-game-probabilities.11l
Normal file
27
Task/Dice-game-probabilities/11l/dice-game-probabilities.11l
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
F throw_die(n_sides, n_dice, s, [Int] &counts)
|
||||
I n_dice == 0
|
||||
counts[s]++
|
||||
R
|
||||
L(i) 1..n_sides
|
||||
throw_die(n_sides, n_dice - 1, s + i, counts)
|
||||
|
||||
F beating_probability(n_sides1, n_dice1,
|
||||
n_sides2, n_dice2)
|
||||
V len1 = (n_sides1 + 1) * n_dice1
|
||||
V C1 = [0] * len1
|
||||
throw_die(n_sides1, n_dice1, 0, &C1)
|
||||
|
||||
V len2 = (n_sides2 + 1) * n_dice2
|
||||
V C2 = [0] * len2
|
||||
throw_die(n_sides2, n_dice2, 0, &C2)
|
||||
|
||||
Float p12 = (n_sides1 ^ n_dice1) * (n_sides2 ^ n_dice2)
|
||||
|
||||
V tot = 0.0
|
||||
L(i) 0 .< len1
|
||||
L(j) 0 .< min(i, len2)
|
||||
tot += Float(C1[i]) * C2[j] / p12
|
||||
R tot
|
||||
|
||||
print(‘#.16’.format(beating_probability(4, 9, 6, 6)))
|
||||
print(‘#.16’.format(beating_probability(10, 5, 7, 6)))
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
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
|
||||
57
Task/Dice-game-probabilities/Ada/dice-game-probabilities.ada
Normal file
57
Task/Dice-game-probabilities/Ada/dice-game-probabilities.ada
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
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;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
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
|
||||
43
Task/Dice-game-probabilities/C++/dice-game-probabilities.cpp
Normal file
43
Task/Dice-game-probabilities/C++/dice-game-probabilities.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#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;
|
||||
}
|
||||
55
Task/Dice-game-probabilities/C/dice-game-probabilities.c
Normal file
55
Task/Dice-game-probabilities/C/dice-game-probabilities.c
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint32_t uint;
|
||||
typedef uint64_t ulong;
|
||||
|
||||
ulong ipow(const uint x, const uint y) {
|
||||
ulong result = 1;
|
||||
for (uint i = 1; i <= y; i++)
|
||||
result *= x;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint min(const uint x, const uint y) {
|
||||
return (x < y) ? x : y;
|
||||
}
|
||||
|
||||
void throw_die(const uint n_sides, const uint n_dice, const uint s, uint counts[]) {
|
||||
if (n_dice == 0) {
|
||||
counts[s]++;
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint i = 1; i < n_sides + 1; i++)
|
||||
throw_die(n_sides, n_dice - 1, s + i, counts);
|
||||
}
|
||||
|
||||
double beating_probability(const uint n_sides1, const uint n_dice1,
|
||||
const uint n_sides2, const uint n_dice2) {
|
||||
const uint len1 = (n_sides1 + 1) * n_dice1;
|
||||
uint C1[len1];
|
||||
for (uint i = 0; i < len1; i++)
|
||||
C1[i] = 0;
|
||||
throw_die(n_sides1, n_dice1, 0, C1);
|
||||
|
||||
const uint len2 = (n_sides2 + 1) * n_dice2;
|
||||
uint C2[len2];
|
||||
for (uint j = 0; j < len2; j++)
|
||||
C2[j] = 0;
|
||||
throw_die(n_sides2, n_dice2, 0, C2);
|
||||
|
||||
const double p12 = (double)(ipow(n_sides1, n_dice1) * ipow(n_sides2, n_dice2));
|
||||
|
||||
double tot = 0;
|
||||
for (uint i = 0; i < len1; i++)
|
||||
for (uint j = 0; j < min(i, len2); j++)
|
||||
tot += (double)C1[i] * C2[j] / p12;
|
||||
return tot;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("%1.16f\n", beating_probability(4, 9, 6, 6));
|
||||
printf("%1.16f\n", beating_probability(10, 5, 7, 6));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
(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))))))
|
||||
35
Task/Dice-game-probabilities/D/dice-game-probabilities-1.d
Normal file
35
Task/Dice-game-probabilities/D/dice-game-probabilities-1.d
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import std.stdio, std.range, std.algorithm;
|
||||
|
||||
void throwDie(in uint nSides, in uint nDice, in uint s, uint[] counts)
|
||||
pure nothrow @safe @nogc {
|
||||
if (nDice == 0) {
|
||||
counts[s]++;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (immutable i; 1 .. nSides + 1)
|
||||
throwDie(nSides, nDice - 1, s + i, counts);
|
||||
}
|
||||
|
||||
real beatingProbability(uint nSides1, uint nDice1,
|
||||
uint nSides2, uint nDice2)()
|
||||
pure nothrow @safe /*@nogc*/ {
|
||||
uint[(nSides1 + 1) * nDice1] C1;
|
||||
throwDie(nSides1, nDice1, 0, C1);
|
||||
|
||||
uint[(nSides2 + 1) * nDice2] C2;
|
||||
throwDie(nSides2, nDice2, 0, C2);
|
||||
|
||||
immutable p12 = real((ulong(nSides1) ^^ nDice1) *
|
||||
(ulong(nSides2) ^^ nDice2));
|
||||
|
||||
return cartesianProduct(C1[].enumerate, C2[].enumerate)
|
||||
.filter!(p => p[0][0] > p[1][0])
|
||||
.map!(p => real(p[0][1]) * p[1][1] / p12)
|
||||
.sum;
|
||||
}
|
||||
|
||||
void main() @safe {
|
||||
writefln("%1.16f", beatingProbability!(4, 9, 6, 6));
|
||||
writefln("%1.16f", beatingProbability!(10, 5, 7, 6));
|
||||
}
|
||||
39
Task/Dice-game-probabilities/D/dice-game-probabilities-2.d
Normal file
39
Task/Dice-game-probabilities/D/dice-game-probabilities-2.d
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import std.stdio, std.range, std.algorithm;
|
||||
|
||||
ulong[] combos(R)(R sides, in uint n) pure nothrow @safe
|
||||
if (isForwardRange!R) {
|
||||
if (sides.empty)
|
||||
return null;
|
||||
if (!n)
|
||||
return [1];
|
||||
auto ret = new typeof(return)(reduce!max(sides[0], sides[1 .. $]) * n + 1);
|
||||
foreach (immutable i, immutable v; enumerate(combos(sides, n - 1))) {
|
||||
if (!v)
|
||||
continue;
|
||||
foreach (immutable s; sides)
|
||||
ret[i + s] += v;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
real winning(R)(R sides1, in uint n1, R sides2, in uint n2)
|
||||
pure nothrow @safe if (isForwardRange!R) {
|
||||
static void accumulate(T)(T[] arr) pure nothrow @safe @nogc {
|
||||
foreach (immutable i; 1 .. arr.length)
|
||||
arr[i] += arr[i - 1];
|
||||
}
|
||||
|
||||
immutable p1 = combos(sides1, n1);
|
||||
auto p2 = combos(sides2, n2);
|
||||
immutable s = p1.sum * p2.sum;
|
||||
accumulate(p2);
|
||||
ulong win = 0; // 'win' is 1 beating 2.
|
||||
foreach (immutable i, immutable x1; p1.dropOne.enumerate)
|
||||
win += x1 * p2[min(i, $ - 1)];
|
||||
return win / real(s);
|
||||
}
|
||||
|
||||
void main() @safe {
|
||||
writefln("%1.16f", winning(iota(1u, 5u), 9, iota(1u, 7u), 6));
|
||||
writefln("%1.16f", winning(iota(1u, 11u), 5, iota(1u, 8u), 6));
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
USING: dice generalizations kernel math prettyprint sequences ;
|
||||
IN: rosetta-code.dice-probabilities
|
||||
|
||||
: winning-prob ( a b c d -- p )
|
||||
[ [ random-roll ] 2bi@ > ] 4 ncurry [ 100000 ] dip replicate
|
||||
[ [ t = ] count ] [ length ] bi /f ;
|
||||
|
||||
9 4 6 6 winning-prob
|
||||
5 10 6 7 winning-prob [ . ] bi@
|
||||
129
Task/Dice-game-probabilities/Forth/dice-game-probabilities.fth
Normal file
129
Task/Dice-game-probabilities/Forth/dice-game-probabilities.fth
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#! /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
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
' Gambas module file
|
||||
|
||||
Public Sub Main()
|
||||
Dim iSides, iPlayer1, iPlayer2, iTotal1, iTotal2, iCount, iCount0 As Integer
|
||||
Dim iDice1 As Integer = 9
|
||||
Dim iDice2 As Integer = 6
|
||||
Dim iSides1 As Integer = 4
|
||||
Dim iSides2 As Integer = 6
|
||||
|
||||
Randomize
|
||||
|
||||
For iCount0 = 0 To 1
|
||||
For iCount = 1 To 100000
|
||||
iPlayer1 = Roll(iDice1, iSides1)
|
||||
iPlayer2 = Roll(iDice2, iSides2)
|
||||
If iPlayer1 > iPlayer2 Then
|
||||
iTotal1 += 1
|
||||
Else If iPlayer1 <> iPlayer2 Then
|
||||
iTotal2 += 1
|
||||
Endif
|
||||
Next
|
||||
|
||||
Print "Tested " & Str(iCount - 1) & " times"
|
||||
Print "Player1 with " & Str(iDice1) & " dice of " & Str(iSides1) & " sides"
|
||||
Print "Player2 with " & Str(iDice2) & " dice of " & Str(iSides2) & " sides"
|
||||
Print "Total wins Player1 = " & Str(iTotal1) & " - " & Str(iTotal2 / iTotal1)
|
||||
Print "Total wins Player2 = " & Str(iTotal2)
|
||||
Print Str((iCount - 1) - (iTotal1 + iTotal2)) & " draws" & gb.NewLine
|
||||
|
||||
iDice1 = 5
|
||||
iDice2 = 6
|
||||
iSides1 = 10
|
||||
iSides2 = 7
|
||||
iTotal1 = 0
|
||||
iTotal2 = 0
|
||||
Next
|
||||
|
||||
End
|
||||
|
||||
Public Sub Roll(iDice As Integer, iSides As Integer) As Integer
|
||||
Dim iCount, iTotal As Short
|
||||
|
||||
For iCount = 1 To iDice
|
||||
iTotal += Rand(1, iSides)
|
||||
Next
|
||||
|
||||
Return iTotal
|
||||
|
||||
End
|
||||
48
Task/Dice-game-probabilities/Go/dice-game-probabilities-1.go
Normal file
48
Task/Dice-game-probabilities/Go/dice-game-probabilities-1.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import(
|
||||
"math"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func minOf(x, y uint) uint {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func throwDie(nSides, nDice, s uint, counts []uint) {
|
||||
if nDice == 0 {
|
||||
counts[s]++
|
||||
return
|
||||
}
|
||||
for i := uint(1); i <= nSides; i++ {
|
||||
throwDie(nSides, nDice - 1, s + i, counts)
|
||||
}
|
||||
}
|
||||
|
||||
func beatingProbability(nSides1, nDice1, nSides2, nDice2 uint) float64 {
|
||||
len1 := (nSides1 + 1) * nDice1
|
||||
c1 := make([]uint, len1) // all elements zero by default
|
||||
throwDie(nSides1, nDice1, 0, c1)
|
||||
|
||||
len2 := (nSides2 + 1) * nDice2
|
||||
c2 := make([]uint, len2)
|
||||
throwDie(nSides2, nDice2, 0, c2)
|
||||
p12 := math.Pow(float64(nSides1), float64(nDice1)) *
|
||||
math.Pow(float64(nSides2), float64(nDice2))
|
||||
|
||||
tot := 0.0
|
||||
for i := uint(0); i < len1; i++ {
|
||||
for j := uint(0); j < minOf(i, len2); j++ {
|
||||
tot += float64(c1[i] * c2[j]) / p12
|
||||
}
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(beatingProbability(4, 9, 6, 6))
|
||||
fmt.Println(beatingProbability(10, 5, 7, 6))
|
||||
}
|
||||
32
Task/Dice-game-probabilities/Go/dice-game-probabilities-2.go
Normal file
32
Task/Dice-game-probabilities/Go/dice-game-probabilities-2.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
type set struct {
|
||||
n, s int
|
||||
}
|
||||
|
||||
func (s set) roll() (sum int) {
|
||||
for i := 0; i < s.n; i++ {
|
||||
sum += rand.Intn(s.s) + 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s set) beats(o set, n int) (p float64) {
|
||||
for i := 0; i < n; i++ {
|
||||
if s.roll() > o.roll() {
|
||||
p = p + 1.0
|
||||
}
|
||||
}
|
||||
p = p / float64(n)
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(set{9, 4}.beats(set{6, 6}, 1000))
|
||||
fmt.Println(set{5, 10}.beats(set{6, 7}, 1000))
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import Control.Monad (replicateM)
|
||||
import Data.List (group, sort)
|
||||
|
||||
succeeds :: (Int, Int) -> (Int, Int) -> Double
|
||||
succeeds p1 p2 =
|
||||
sum
|
||||
[ realToFrac (c1 * c2) / totalOutcomes
|
||||
| (s1, c1) <- countSums p1
|
||||
, (s2, c2) <- countSums p2
|
||||
, s1 > s2 ]
|
||||
where
|
||||
totalOutcomes = realToFrac $ uncurry (^) p1 * uncurry (^) p2
|
||||
countSums (nFaces, nDice) = f [1 .. nFaces]
|
||||
where
|
||||
f =
|
||||
fmap (((,) . head) <*> (pred . length)) .
|
||||
group . sort . fmap sum . replicateM nDice
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
print $ (4, 9) `succeeds` (6, 6)
|
||||
print $ (10, 5) `succeeds` (7, 6)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
gen_dict =: (({. , #)/.~@:,@:(+/&>)@:{@:(# <@:>:@:i.)~ ; ^)&x:
|
||||
|
||||
beating_probability =: dyad define
|
||||
'C0 P0' =. gen_dict/ x
|
||||
'C1 P1' =. gen_dict/ y
|
||||
(C0 +/@:,@:(>/&:({."1) * */&:({:"1)) C1) % (P0 * P1)
|
||||
)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
10 5 (;x:inv)@:beating_probability 7 6
|
||||
┌─────────────────────┬────────┐
|
||||
│3781171969r5882450000│0.642789│
|
||||
└─────────────────────┴────────┘
|
||||
4 9 (;x:inv)@:beating_probability 6 6
|
||||
┌─────────────────┬────────┐
|
||||
│48679795r84934656│0.573144│
|
||||
└─────────────────┴────────┘
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import java.util.Random;
|
||||
|
||||
public class Dice{
|
||||
private static int roll(int nDice, int nSides){
|
||||
int sum = 0;
|
||||
Random rand = new Random();
|
||||
for(int i = 0; i < nDice; i++){
|
||||
sum += rand.nextInt(nSides) + 1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private static int diceGame(int p1Dice, int p1Sides, int p2Dice, int p2Sides, int rolls){
|
||||
int p1Wins = 0;
|
||||
for(int i = 0; i < rolls; i++){
|
||||
int p1Roll = roll(p1Dice, p1Sides);
|
||||
int p2Roll = roll(p2Dice, p2Sides);
|
||||
if(p1Roll > p2Roll) p1Wins++;
|
||||
}
|
||||
return p1Wins;
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
int p1Dice = 9; int p1Sides = 4;
|
||||
int p2Dice = 6; int p2Sides = 6;
|
||||
int rolls = 10000;
|
||||
int p1Wins = diceGame(p1Dice, p1Sides, p2Dice, p2Sides, rolls);
|
||||
System.out.println(rolls + " rolls, p1 = " + p1Dice + "d" + p1Sides + ", p2 = " + p2Dice + "d" + p2Sides);
|
||||
System.out.println("p1 wins " + (100.0 * p1Wins / rolls) + "% of the time");
|
||||
|
||||
System.out.println();
|
||||
|
||||
p1Dice = 5; p1Sides = 10;
|
||||
p2Dice = 6; p2Sides = 7;
|
||||
rolls = 10000;
|
||||
p1Wins = diceGame(p1Dice, p1Sides, p2Dice, p2Sides, rolls);
|
||||
System.out.println(rolls + " rolls, p1 = " + p1Dice + "d" + p1Sides + ", p2 = " + p2Dice + "d" + p2Sides);
|
||||
System.out.println("p1 wins " + (100.0 * p1Wins / rolls) + "% of the time");
|
||||
|
||||
System.out.println();
|
||||
|
||||
p1Dice = 9; p1Sides = 4;
|
||||
p2Dice = 6; p2Sides = 6;
|
||||
rolls = 1000000;
|
||||
p1Wins = diceGame(p1Dice, p1Sides, p2Dice, p2Sides, rolls);
|
||||
System.out.println(rolls + " rolls, p1 = " + p1Dice + "d" + p1Sides + ", p2 = " + p2Dice + "d" + p2Sides);
|
||||
System.out.println("p1 wins " + (100.0 * p1Wins / rolls) + "% of the time");
|
||||
|
||||
System.out.println();
|
||||
|
||||
p1Dice = 5; p1Sides = 10;
|
||||
p2Dice = 6; p2Sides = 7;
|
||||
rolls = 1000000;
|
||||
p1Wins = diceGame(p1Dice, p1Sides, p2Dice, p2Sides, rolls);
|
||||
System.out.println(rolls + " rolls, p1 = " + p1Dice + "d" + p1Sides + ", p2 = " + p2Dice + "d" + p2Sides);
|
||||
System.out.println("p1 wins " + (100.0 * p1Wins / rolls) + "% of the time");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
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);
|
||||
28
Task/Dice-game-probabilities/Jq/dice-game-probabilities.jq
Normal file
28
Task/Dice-game-probabilities/Jq/dice-game-probabilities.jq
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# 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)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
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) =
|
||||
mean(play(d1, f1) > play(d2, f2) for _ in 1:nrep)
|
||||
|
||||
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))
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// version 1.1.2
|
||||
|
||||
fun throwDie(nSides: Int, nDice: Int, s: Int, counts: IntArray) {
|
||||
if (nDice == 0) {
|
||||
counts[s]++
|
||||
return
|
||||
}
|
||||
for (i in 1..nSides) throwDie(nSides, nDice - 1, s + i, counts)
|
||||
}
|
||||
|
||||
fun beatingProbability(nSides1: Int, nDice1: Int, nSides2: Int, nDice2: Int): Double {
|
||||
val len1 = (nSides1 + 1) * nDice1
|
||||
val c1 = IntArray(len1) // all elements zero by default
|
||||
throwDie(nSides1, nDice1, 0, c1)
|
||||
|
||||
val len2 = (nSides2 + 1) * nDice2
|
||||
val c2 = IntArray(len2)
|
||||
throwDie(nSides2, nDice2, 0, c2)
|
||||
|
||||
val p12 = Math.pow(nSides1.toDouble(), nDice1.toDouble()) *
|
||||
Math.pow(nSides2.toDouble(), nDice2.toDouble())
|
||||
|
||||
var tot = 0.0
|
||||
for (i in 0 until len1) {
|
||||
for (j in 0 until minOf(i, len2)) {
|
||||
tot += c1[i] * c2[j] / p12
|
||||
}
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println(beatingProbability(4, 9, 6, 6))
|
||||
println(beatingProbability(10, 5, 7, 6))
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
local function simu(ndice1, nsides1, ndice2, nsides2)
|
||||
local function roll(ndice, nsides)
|
||||
local result = 0;
|
||||
for i = 1, ndice do
|
||||
result = result + math.random(nsides)
|
||||
end
|
||||
return result
|
||||
end
|
||||
local wins, coms = 0, 1000000
|
||||
for i = 1, coms do
|
||||
local roll1 = roll(ndice1, nsides1)
|
||||
local roll2 = roll(ndice2, nsides2)
|
||||
if (roll1 > roll2) then
|
||||
wins = wins + 1
|
||||
end
|
||||
end
|
||||
print("simulated: p1 = "..ndice1.."d"..nsides1..", p2 = "..ndice2.."d"..nsides2..", prob = "..wins.." / "..coms.." = "..(wins/coms))
|
||||
end
|
||||
|
||||
simu(9, 4, 6, 6)
|
||||
simu(5, 10, 6, 7)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
local function comp(ndice1, nsides1, ndice2, nsides2)
|
||||
local function throws(ndice, nsides)
|
||||
local sums = {}
|
||||
for i = 1, ndice*nsides do
|
||||
sums[i] = 0
|
||||
end
|
||||
local function throw(ndice, nsides, s)
|
||||
if (ndice==0) then
|
||||
sums[s] = sums[s] + 1
|
||||
else
|
||||
for i = 1, nsides do
|
||||
throw(ndice-1, nsides, s+i)
|
||||
end
|
||||
end
|
||||
return sums
|
||||
end
|
||||
return throw(ndice, nsides, 0)
|
||||
end
|
||||
local p1 = throws(ndice1, nsides1)
|
||||
local p2 = throws(ndice2, nsides2)
|
||||
local wins, coms = 0, nsides1^ndice1 * nsides2^ndice2
|
||||
for k1,v1 in pairs(p1) do
|
||||
for k2,v2 in pairs(p2) do
|
||||
if (k1 > k2) then
|
||||
wins = wins + v1 * v2
|
||||
end
|
||||
end
|
||||
end
|
||||
print("computed: p1 = "..ndice1.."d"..nsides1..", p2 = "..ndice2.."d"..nsides2..", prob = "..wins.." / "..coms.." = "..(wins/coms))
|
||||
end
|
||||
|
||||
comp(9, 4, 6, 6)
|
||||
comp(5, 10, 6, 7)
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
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}]
|
||||
35
Task/Dice-game-probabilities/Nim/dice-game-probabilities.nim
Normal file
35
Task/Dice-game-probabilities/Nim/dice-game-probabilities.nim
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
Numeric Digits 30
|
||||
Call test '9 4 6 6'
|
||||
Call test '5 10 6 7'
|
||||
Exit
|
||||
test:
|
||||
Parse Arg w1 s1 w2 s2
|
||||
p1.=0
|
||||
p2.=0
|
||||
Call pp 1,w1,s1,p1.,p2.
|
||||
Call pp 2,w2,s2,p1.,p2.
|
||||
p2low.=0
|
||||
Do x=w1 To w1*s1
|
||||
Do y=0 To x-1
|
||||
p2low.x+=p2.y
|
||||
End
|
||||
End
|
||||
pwin1=0
|
||||
Do x=w1 To w1*s1
|
||||
pwin1+=p1.x*p2low.x
|
||||
End
|
||||
Say 'Player 1 has' w1 'dice with' s1 'sides each'
|
||||
Say 'Player 2 has' w2 'dice with' s2 'sides each'
|
||||
Say 'Probability for player 1 to win:' pwin1
|
||||
Say ''
|
||||
Return
|
||||
|
||||
pp: Procedure
|
||||
/*---------------------------------------------------------------------
|
||||
* Compute and assign probabilities to get a sum x
|
||||
* when throwing w dice each having s sides (marked from 1 to s)
|
||||
* k=1 sets p1.*, k=2 sets p2.*
|
||||
*--------------------------------------------------------------------*/
|
||||
Use Arg k,w,s,p1.,p2.
|
||||
str=''
|
||||
cnt.=0
|
||||
Do wi=1 To w
|
||||
str=str||'Do v'wi'=1 To' s';'
|
||||
End
|
||||
str=str||'sum='
|
||||
Do wi=1 To w-1
|
||||
str=str||'v'wi'+'
|
||||
End
|
||||
str=str||'v'w';'
|
||||
str=str||'cnt.'sum'+=1;'
|
||||
Do wi=1 To w
|
||||
str=str||'End;'
|
||||
End
|
||||
Interpret str
|
||||
psum=0
|
||||
Do x=0 To w*s
|
||||
If k=1 Then
|
||||
p1.x=cnt.x/(s**w)
|
||||
Else
|
||||
p2.x=cnt.x/(s**w)
|
||||
psum+=p1.x
|
||||
End
|
||||
Return
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
Numeric Digits 30
|
||||
Call test '9 4 6 6'
|
||||
Call test '5 10 6 7'
|
||||
Exit
|
||||
|
||||
test:
|
||||
Parse Arg w1 s1 w2 s2
|
||||
p1.='0/1'
|
||||
p2.='0/1'
|
||||
Call pp 1,w1,s1,p1.,p2.
|
||||
Call pp 2,w2,s2,p1.,p2.
|
||||
p2low.='0/1'
|
||||
Do x=w1 To w1*s1
|
||||
Do y=0 To x-1
|
||||
p2low.x=fr_add(p2low.x,p2.y)
|
||||
End
|
||||
End
|
||||
pwin1='0/1'
|
||||
Do x=w1 To w1*s1
|
||||
pwin1=fr_add(pwin1,fr_Mult(p1.x,p2low.x))
|
||||
End
|
||||
Say 'Player 1 has' w1 'dice with' s1 'sides each'
|
||||
Say 'Player 2 has' w2 'dice with' s2 'sides each'
|
||||
Say 'Probability for player 1 to win:' pwin1
|
||||
Parse Var pwin1 nom '/' denom
|
||||
Say ' ->' (nom/denom)
|
||||
Say ''
|
||||
Return
|
||||
|
||||
pp: Procedure
|
||||
/*---------------------------------------------------------------------
|
||||
* Compute and assign probabilities to get a sum x
|
||||
* when throwing w dice each having s sides (marked from 1 to s)
|
||||
* k=1 sets p1.*, k=2 sets p2.*
|
||||
*--------------------------------------------------------------------*/
|
||||
Use Arg k,w,s,p1.,p2.
|
||||
str=''
|
||||
cnt.=0
|
||||
Do wi=1 To w
|
||||
str=str||'Do v'wi'=1 To' s';'
|
||||
End
|
||||
str=str||'sum='
|
||||
Do wi=1 To w-1
|
||||
str=str||'v'wi'+'
|
||||
End
|
||||
str=str||'v'w';'
|
||||
str=str||'cnt.sum+=1;'
|
||||
Do wi=1 To w
|
||||
str=str||'End;'
|
||||
End
|
||||
Interpret str
|
||||
|
||||
psum='0/1'
|
||||
Do x=0 To w*s
|
||||
If k=1 Then
|
||||
p1.x=cnt.x'/'||(s**w)
|
||||
Else
|
||||
p2.x=cnt.x'/'||(s**w)
|
||||
psum=fr_add(psum,p1.x)
|
||||
End
|
||||
Return
|
||||
|
||||
|
||||
fr_add: Procedure
|
||||
Parse Arg a,b
|
||||
parse Var a an '/' az
|
||||
parse Var b bn '/' bz
|
||||
rn=an*bz+bn*az
|
||||
rz=az*bz
|
||||
res=fr_cancel(rn','rz)
|
||||
Return res
|
||||
|
||||
fr_div: Procedure
|
||||
Parse Arg a,b
|
||||
parse Var a an '/' az
|
||||
parse Var b bn '/' bz
|
||||
rn=an*bz
|
||||
rz=az*bn
|
||||
res=fr_cancel(rn','rz)
|
||||
Return res
|
||||
|
||||
fr_mult: Procedure
|
||||
Parse Arg a,b
|
||||
parse Var a an '/' az
|
||||
parse Var b bn '/' bz
|
||||
rn=an*bn
|
||||
rz=az*bz
|
||||
res=fr_cancel(rn','rz)
|
||||
Return res
|
||||
|
||||
fr_cancel: Procedure
|
||||
Parse Arg n ',' z
|
||||
k=ggt(n,z)
|
||||
Return n%k'/'z%k
|
||||
|
||||
ggt: Procedure
|
||||
/**********************************************************************
|
||||
* ggt (gcd) Greatest common Divisor
|
||||
* Recursive procedure as shown in PL/I
|
||||
**********************************************************************/
|
||||
Parse Arg a,b
|
||||
if b = 0 then return abs(a)
|
||||
return ggt(b,a//b)
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
Numeric Digits 50
|
||||
Call test '9 4 6 6'
|
||||
Call test '5 10 6 7'
|
||||
Exit
|
||||
|
||||
test:
|
||||
Parse Arg w1 s1 w2 s2
|
||||
p1.=.fraction~new(0,1)
|
||||
p2.=.fraction~new(0,1)
|
||||
Call pp 1,w1,s1,p1.,p2.
|
||||
Call pp 2,w2,s2,p1.,p2.
|
||||
p2low.=.fraction~new(0,1)
|
||||
Do x=w1 To w1*s1
|
||||
Do y=0 To x-1
|
||||
p2low.x=p2low.x+p2.y
|
||||
End
|
||||
End
|
||||
pwin1=.fraction~new(0,1)
|
||||
Do x=w1 To w1*s1
|
||||
pwin1=pwin1+(p1.x*p2low.x)
|
||||
End
|
||||
Say 'Player 1 has' w1 'dice with' s1 'sides each'
|
||||
Say 'Player 2 has' w2 'dice with' s2 'sides each'
|
||||
Say 'Probability for player 1 to win:' pwin1~string
|
||||
Say ' ->' pwin1~tonumber
|
||||
Say ''
|
||||
Return
|
||||
|
||||
pp: Procedure
|
||||
/*---------------------------------------------------------------------
|
||||
* Compute and assign probabilities to get a sum x
|
||||
* when throwing w dice each having s sides (marked from 1 to s)
|
||||
* k=1 sets p1.*, k=2 sets p2.*
|
||||
*--------------------------------------------------------------------*/
|
||||
Use Arg k,w,s,p1.,p2.
|
||||
str=''
|
||||
cnt.=0
|
||||
Do wi=1 To w
|
||||
str=str||'Do v'wi'=1 To' s';'
|
||||
End
|
||||
str=str||'sum='
|
||||
Do wi=1 To w-1
|
||||
str=str||'v'wi'+'
|
||||
End
|
||||
str=str||'v'w';'
|
||||
str=str||'cnt.sum+=1;'
|
||||
Do wi=1 To w
|
||||
str=str||'End;'
|
||||
End
|
||||
Interpret str
|
||||
|
||||
psum=.fraction~new(0,1)
|
||||
Do x=0 To w*s
|
||||
If k=1 Then
|
||||
p1.x=.fraction~new(cnt.x,s**w)
|
||||
Else
|
||||
p2.x=.fraction~new(cnt.x,s**w)
|
||||
psum=psum+p1.x
|
||||
End
|
||||
Return
|
||||
|
||||
::class fraction inherit orderable
|
||||
::options Digits 50
|
||||
::method init
|
||||
expose numerator denominator
|
||||
use strict arg numerator, denominator = 1
|
||||
--Trace ?R
|
||||
--if numerator == 0 then denominator = 0
|
||||
--else if denominator == 0 then raise syntax 98.900 array("Fraction denominator cannot be zero")
|
||||
|
||||
-- if the denominator is negative, make the numerator carry the sign
|
||||
if denominator < 0 then do
|
||||
numerator = -numerator
|
||||
denominator = - denominator
|
||||
end
|
||||
|
||||
|
||||
-- find the greatest common denominator and reduce to
|
||||
-- the simplest form
|
||||
gcd = self~gcd(numerator~abs, denominator~abs)
|
||||
|
||||
numerator /= gcd
|
||||
denominator /= gcd
|
||||
|
||||
-- fraction instances are immutable, so these are
|
||||
-- read only attributes
|
||||
|
||||
-- calculate the greatest common denominator of a numerator/denominator pair
|
||||
::method gcd private
|
||||
use arg x, y
|
||||
--Say 'gcd:' x y digits()
|
||||
loop while y \= 0
|
||||
-- check if they divide evenly
|
||||
temp = x // y
|
||||
x = y
|
||||
y = temp
|
||||
end
|
||||
return x
|
||||
|
||||
-- calculate the least common multiple of a numerator/denominator pair
|
||||
::method lcm private
|
||||
use arg x, y
|
||||
return x / self~gcd(x, y) * y
|
||||
|
||||
::method abs
|
||||
expose numerator denominator
|
||||
-- the denominator is always forced to be positive
|
||||
return self~class~new(numerator~abs, denominator)
|
||||
|
||||
-- convert a fraction to regular Rexx number
|
||||
::method toNumber
|
||||
expose numerator denominator
|
||||
if numerator == 0 then return 0
|
||||
return numerator/denominator
|
||||
|
||||
::method add
|
||||
expose numerator denominator
|
||||
use strict arg other
|
||||
-- convert to a fraction if a regular number
|
||||
if \other~isa(.fraction) then other = self~class~new(other, 1)
|
||||
|
||||
multiple = self~lcm(denominator, other~denominator)
|
||||
newa = numerator * multiple / denominator
|
||||
newb = other~numerator * multiple / other~denominator
|
||||
return self~class~new(newa + newb, multiple)
|
||||
|
||||
::method times
|
||||
expose numerator denominator
|
||||
use strict arg other
|
||||
-- convert to a fraction if a regular number
|
||||
if \other~isa(.fraction) then other = self~class~new(other, 1)
|
||||
return self~class~new(numerator * other~numerator, denominator * other~denominator)
|
||||
|
||||
-- some operator overrides -- these only work if the left-hand-side of the
|
||||
-- subexpression is a quaternion
|
||||
::method "*"
|
||||
forward message("TIMES")
|
||||
|
||||
::method "+"
|
||||
-- need to check if this is a prefix plus or an addition
|
||||
if arg() == 0 then
|
||||
return self -- we can return this copy since it is imutable
|
||||
else
|
||||
forward message("ADD")
|
||||
|
||||
::method string
|
||||
expose numerator denominator
|
||||
if denominator == 1 then return numerator
|
||||
return numerator"/"denominator
|
||||
|
||||
-- override hashcode for collection class hash uses
|
||||
::method hashCode
|
||||
expose numerator denominator
|
||||
return numerator~hashcode~bitxor(numerator~hashcode)
|
||||
|
||||
::attribute numerator GET
|
||||
::attribute denominator GET
|
||||
|
||||
::requires rxmath library
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
oid='diet.xxx'; Call sysFileDelete oid
|
||||
Call test '9 4 6 6'
|
||||
Call test '5 10 6 7'
|
||||
Exit
|
||||
test:
|
||||
Parse Arg n1 s1 n2 s2
|
||||
Call o 'Player 1:' n1 'dice with' s1 'sides each'
|
||||
Call o 'Player 2:' n2 'dice with' s2 'sides each'
|
||||
cnt1.=0
|
||||
cnt2.=0
|
||||
win.=0
|
||||
nn=10000000
|
||||
Call time 'R'
|
||||
Do i=1 To nn
|
||||
sum1=sum(n1 s1) ; cnt1.sum1+=1
|
||||
sum2=sum(n2 s2) ; cnt2.sum2+=1
|
||||
Select
|
||||
When sum1>sum2 Then win.1+=1
|
||||
When sum1<sum2 Then win.2+=1
|
||||
Otherwise win.0+=1
|
||||
End
|
||||
End
|
||||
Call o win.1/nn 'player 1 wins'
|
||||
Call o win.2/nn 'player 2 wins'
|
||||
Call o win.0/nn 'draws'
|
||||
/*
|
||||
Do i=min(n1,n2) To max(n1*s1,n2*s2)
|
||||
Call o right(i,2) format(cnt1.i,7) format(cnt2.i,7)
|
||||
End
|
||||
*/
|
||||
Call o time('E') 'seconds elapsed'
|
||||
Return
|
||||
|
||||
sum: Parse Arg n s
|
||||
sum=0
|
||||
Do k=1 To n
|
||||
sum+=rand(s)
|
||||
End
|
||||
Return sum
|
||||
|
||||
rand: Parse Arg n
|
||||
Return random(n-1)+1
|
||||
|
||||
o:
|
||||
Say arg(1)
|
||||
Return lineout(oid,arg(1))
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
*process source attributes xref;
|
||||
dicegame: Proc Options(main);
|
||||
Call test(9, 4,6,6);
|
||||
Call test(5,10,6,7);
|
||||
test: Proc(w1,s1,w2,s2);
|
||||
Dcl (w1,s1,w2,s2,x,y) Bin Fixed(31);
|
||||
Dcl p1(100) Dec Float(18) Init((100)0);
|
||||
Dcl p2(100) Dec Float(18) Init((100)0);
|
||||
Dcl p2low(100) Dec Float(18) Init((100)0);
|
||||
Call pp(w1,s1,p1);
|
||||
Call pp(w2,s2,p2);
|
||||
Do x=w1 To w1*s1;
|
||||
Do y=0 To x-1;
|
||||
p2low(x)+=p2(y);
|
||||
End;
|
||||
End;
|
||||
pwin1=0;
|
||||
Do x=w1 To w1*s1;
|
||||
pwin1+=p1(x)*p2low(x);
|
||||
End;
|
||||
Put Edit('Player 1 has ',w1,' dice with ',s1,' sides each')
|
||||
(Skip,3(a,f(2)));
|
||||
Put Edit('Player 2 has ',w2,' dice with ',s2,' sides each')
|
||||
(Skip,3(a,f(2)));
|
||||
Put Edit('Probability for player 1 to win: ',pwin1)(Skip,a,f(20,18));
|
||||
Put Edit('')(Skip,a);
|
||||
End;
|
||||
pp: Proc(w,s,p);
|
||||
/*--------------------------------------------------------------------
|
||||
* Compute and assign probabilities to get a sum x
|
||||
* when throwing w dice each having s sides (marked from 1 to s)
|
||||
*-------------------------------------------------------------------*/
|
||||
Dcl (w,s) Bin Fixed(31);
|
||||
Dcl p(100) Dec Float(18);
|
||||
Dcl cnt(100) Bin Fixed(31);
|
||||
Dcl (a(12),e(12),v(12),sum,i,n) Bin Fixed(31);
|
||||
a=0;
|
||||
e=0;
|
||||
Do i=1 To w;
|
||||
a(i)=1;
|
||||
e(i)=s;
|
||||
End;
|
||||
n=0;
|
||||
cnt=0;
|
||||
Do v(1)=a(1) To e(1);
|
||||
Do v(2)=a(2) To e(2);
|
||||
Do v(3)=a(3) To e(3);
|
||||
Do v(4)=a(4) To e(4);
|
||||
Do v(5)=a(5) To e(5);
|
||||
Do v(6)=a(6) To e(6);
|
||||
Do v(7)=a(7) To e(7);
|
||||
Do v(8)=a(8) To e(8);
|
||||
Do v(9)=a(9) To e(9);
|
||||
Do v(10)=a(10) To e(10);
|
||||
sum=0;
|
||||
Do i=1 To 10;
|
||||
sum=sum+v(i);
|
||||
End;
|
||||
cnt(sum)+=1;
|
||||
n+=1;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
Do k=w To w*s;
|
||||
p(k)=divide(cnt(k),n,18,16);
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
145
Task/Dice-game-probabilities/PL-I/dice-game-probabilities-2.pli
Normal file
145
Task/Dice-game-probabilities/PL-I/dice-game-probabilities-2.pli
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
*process source attributes xref;
|
||||
dgf: Proc Options(main);
|
||||
Call test(9, 4,6,6);
|
||||
Call test(5,10,6,7);
|
||||
test: Proc(w1,s1,w2,s2);
|
||||
Dcl (w1,s1,w2,s2,x,y) Dec Float(18);
|
||||
Dcl 1 p1(100),
|
||||
2 nom Dec Float(18) Init((100)0),
|
||||
2 denom Dec Float(18) Init((100)1);
|
||||
Dcl 1 p2(100),
|
||||
2 nom Dec Float(18) Init((100)0),
|
||||
2 denom Dec Float(18) Init((100)1);
|
||||
Dcl 1 p2low(100),
|
||||
2 nom Dec Float(18) Init((100)0),
|
||||
2 denom Dec Float(18) Init((100)1);
|
||||
Dcl 1 pwin1,
|
||||
2 nom Dec Float(18) Init(0),
|
||||
2 denom Dec Float(18) Init(1);
|
||||
Dcl 1 prod Like pwin1;
|
||||
Call pp(w1,s1,p1);
|
||||
Call pp(w2,s2,p2);
|
||||
Do x=w1 To w1*s1;
|
||||
Do y=0 To x-1;
|
||||
Call fr_add(p2low(x),p2(y),p2low(x));
|
||||
End;
|
||||
End;
|
||||
Do x=w1 To w1*s1;
|
||||
Call fr_mult(p1(x),p2low(x),prod);
|
||||
Call fr_add(pwin1,prod,pwin1);
|
||||
End;
|
||||
Put Edit('Player 1 has ',w1,' dice with ',s1,' sides each')
|
||||
(Skip,3(a,f(2)));
|
||||
Put Edit('Player 2 has ',w2,' dice with ',s2,' sides each')
|
||||
(Skip,3(a,f(2)));
|
||||
Put Edit('Probability for player 1 to win: ',
|
||||
str(pwin1.nom),'/',str(pwin1.denom))(Skip,4(a));
|
||||
Put Edit(' -> ',
|
||||
pwin1.nom/pwin1.denom)(Skip,a,f(20,18));
|
||||
Put Edit('')(Skip,a);
|
||||
End;
|
||||
|
||||
pp: Proc(w,s,p);
|
||||
/*--------------------------------------------------------------------
|
||||
* Compute and assign probabilities to get a sum x
|
||||
* when throwing w dice each having s sides (marked from 1 to s)
|
||||
*-------------------------------------------------------------------*/
|
||||
Dcl (w,s) Dec Float(18);
|
||||
Dcl 1 p(100),
|
||||
2 nom Dec Float(18),
|
||||
2 denom Dec Float(18);
|
||||
Dcl cnt(100) Dec Float(18);
|
||||
Dcl (a(12),e(12),v(12),sum,i,n) Dec Float(18);
|
||||
a=0;
|
||||
e=0;
|
||||
Do i=1 To w;
|
||||
a(i)=1;
|
||||
e(i)=s;
|
||||
End;
|
||||
n=0;
|
||||
cnt=0;
|
||||
Do v(1)=a(1) To e(1);
|
||||
Do v(2)=a(2) To e(2);
|
||||
Do v(3)=a(3) To e(3);
|
||||
Do v(4)=a(4) To e(4);
|
||||
Do v(5)=a(5) To e(5);
|
||||
Do v(6)=a(6) To e(6);
|
||||
Do v(7)=a(7) To e(7);
|
||||
Do v(8)=a(8) To e(8);
|
||||
Do v(9)=a(9) To e(9);
|
||||
Do v(10)=a(10) To e(10);
|
||||
sum=0;
|
||||
Do i=1 To 10;
|
||||
sum=sum+v(i);
|
||||
End;
|
||||
cnt(sum)+=1;
|
||||
n+=1;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
Do k=w To w*s;
|
||||
p(k).nom=cnt(k);
|
||||
p(k).denom=n;
|
||||
End;
|
||||
End;
|
||||
|
||||
fr_add: Proc(a,b,res);
|
||||
Dcl 1 a,
|
||||
2 nom Dec Float(18),
|
||||
2 denom Dec Float(18);
|
||||
Dcl 1 b Like a;
|
||||
Dcl res like a;
|
||||
/* Put Edit('fr_add',a.nom,a.denom,b.nom,b.denom)(Skip,a,4(f(15))); */
|
||||
res.nom=a.nom*b.denom+b.nom*a.denom;
|
||||
res.denom=a.denom*b.denom;
|
||||
Call fr_cancel(res,res);
|
||||
End;
|
||||
|
||||
fr_mult: Proc(a,b,res);
|
||||
Dcl 1 a,
|
||||
2 nom Dec Float(18),
|
||||
2 denom Dec Float(18);
|
||||
Dcl 1 b Like a;
|
||||
Dcl res like a;
|
||||
/* Put Edit('fr_mult',a.nom,a.denom,b.nom,b.denom)(Skip,a,4(f(15)));*/
|
||||
res.nom=a.nom*b.nom;
|
||||
res.denom=a.denom*b.denom;
|
||||
Call fr_cancel(res,res);
|
||||
End;
|
||||
|
||||
fr_cancel: Proc(a,res);
|
||||
Dcl 1 a,
|
||||
2 nom Dec Float(18),
|
||||
2 denom Dec Float(18);
|
||||
Dcl k Dec Float(18);
|
||||
Dcl 1 res like a;
|
||||
/* Put Edit('fr_cancel',a.nom,a.denom)(Skip,a,4(f(15))); */
|
||||
k=ggt(a.nom,a.denom);
|
||||
res=a/k;
|
||||
End;
|
||||
|
||||
ggt: Proc(a,b) Recursive Returns(Dec Float(18));
|
||||
/**********************************************************************
|
||||
* ggt (gcd) Greatest common Divisor
|
||||
* Recursive Proc(a,b)) as shown in PL/I
|
||||
**********************************************************************/
|
||||
Dcl (a,b) Dec Float(18);
|
||||
if b = 0 then return (abs(a));
|
||||
return (ggt(b,mod(a,b)));
|
||||
End;
|
||||
|
||||
str: Proc(x) Returns(Char(20) Var);
|
||||
Dcl x Dec Float(18);
|
||||
Dcl res Char(20) Var;
|
||||
Put String(res) Edit(x)(f(20));
|
||||
Return (trim(res));
|
||||
End;
|
||||
|
||||
End;
|
||||
35
Task/Dice-game-probabilities/Perl/dice-game-probabilities.pl
Normal file
35
Task/Dice-game-probabilities/Perl/dice-game-probabilities.pl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use List::Util qw(sum0 max);
|
||||
|
||||
sub comb {
|
||||
my ($s, $n) = @_;
|
||||
$n || return (1);
|
||||
my @r = (0) x ($n - max(@$s) + 1);
|
||||
my @c = comb($s, $n - 1);
|
||||
foreach my $i (0 .. $#c) {
|
||||
$c[$i] || next;
|
||||
foreach my $k (@$s) {
|
||||
$r[$i + $k] += $c[$i];
|
||||
}
|
||||
}
|
||||
return @r;
|
||||
}
|
||||
|
||||
sub winning {
|
||||
my ($s1, $n1, $s2, $n2) = @_;
|
||||
|
||||
my @p1 = comb($s1, $n1);
|
||||
my @p2 = comb($s2, $n2);
|
||||
|
||||
my ($win, $loss, $tie) = (0, 0, 0);
|
||||
|
||||
foreach my $i (0 .. $#p1) {
|
||||
$win += $p1[$i] * sum0(@p2[0 .. $i - 1]);
|
||||
$tie += $p1[$i] * sum0(@p2[$i .. $i ]);
|
||||
$loss += $p1[$i] * sum0(@p2[$i+1 .. $#p2 ]);
|
||||
}
|
||||
my $total = sum0(@p1) * sum0(@p2);
|
||||
map { $_ / $total } ($win, $tie, $loss);
|
||||
}
|
||||
|
||||
print '(', join(', ', winning([1 .. 4], 9, [1 .. 6], 6)), ")\n";
|
||||
print '(', join(', ', winning([1 .. 10], 5, [1 .. 7], 6)), ")\n";
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<span style="color: #008080;">else</span>
|
||||
<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>
|
||||
<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>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">counts</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">0.0</span>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">tot</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</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;">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>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from itertools import product
|
||||
|
||||
def gen_dict(n_faces, n_dice):
|
||||
counts = [0] * ((n_faces + 1) * n_dice)
|
||||
for t in product(range(1, n_faces + 1), repeat=n_dice):
|
||||
counts[sum(t)] += 1
|
||||
return counts, n_faces ** n_dice
|
||||
|
||||
def beating_probability(n_sides1, n_dice1, n_sides2, n_dice2):
|
||||
c1, p1 = gen_dict(n_sides1, n_dice1)
|
||||
c2, p2 = gen_dict(n_sides2, n_dice2)
|
||||
p12 = float(p1 * p2)
|
||||
|
||||
return sum(p[1] * q[1] / p12
|
||||
for p, q in product(enumerate(c1), enumerate(c2))
|
||||
if p[0] > q[0])
|
||||
|
||||
print beating_probability(4, 9, 6, 6)
|
||||
print beating_probability(10, 5, 7, 6)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from __future__ import print_function, division
|
||||
|
||||
def combos(sides, n):
|
||||
if not n: return [1]
|
||||
ret = [0] * (max(sides)*n + 1)
|
||||
for i,v in enumerate(combos(sides, n - 1)):
|
||||
if not v: continue
|
||||
for s in sides: ret[i + s] += v
|
||||
return ret
|
||||
|
||||
def winning(sides1, n1, sides2, n2):
|
||||
p1, p2 = combos(sides1, n1), combos(sides2, n2)
|
||||
win,loss,tie = 0,0,0 # 'win' is 1 beating 2
|
||||
for i,x1 in enumerate(p1):
|
||||
# using accumulated sum on p2 could save some time
|
||||
win += x1*sum(p2[:i])
|
||||
tie += x1*sum(p2[i:i+1])
|
||||
loss+= x1*sum(p2[i+1:])
|
||||
s = sum(p1)*sum(p2)
|
||||
return win/s, tie/s, loss/s
|
||||
|
||||
print(winning(range(1,5), 9, range(1,7), 6))
|
||||
print(winning(range(1,11), 5, range(1,8), 6)) # this seem hardly fair
|
||||
|
||||
# mountains of dice test case
|
||||
# print(winning((1, 2, 3, 5, 9), 700, (1, 2, 3, 4, 5, 6), 800))
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
from __future__ import division, print_function
|
||||
from itertools import accumulate # Python3 only
|
||||
|
||||
def combos(sides, n):
|
||||
ret = [1] + [0]*(n + 1)*sides # extra length for negative indices
|
||||
for p in range(1, n + 1):
|
||||
rolling_sum = 0
|
||||
for i in range(p*sides, p - 1, -1):
|
||||
rolling_sum += ret[i - sides] - ret[i]
|
||||
ret[i] = rolling_sum
|
||||
ret[p - 1] = 0
|
||||
return ret
|
||||
|
||||
def winning(d1, n1, d2, n2):
|
||||
c1, c2 = combos(d1, n1), combos(d2, n2)
|
||||
ac = list(accumulate(c2 + [0]*(len(c1) - len(c2))))
|
||||
|
||||
return sum(v*a for v,a in zip(c1[1:], ac)) / (ac[-1]*sum(c1))
|
||||
|
||||
|
||||
print(winning(4, 9, 6, 6))
|
||||
print(winning(5, 10, 6, 7))
|
||||
|
||||
#print(winning(6, 700, 8, 540))
|
||||
6
Task/Dice-game-probabilities/R/dice-game-probabilities.r
Normal file
6
Task/Dice-game-probabilities/R/dice-game-probabilities.r
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
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.")
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* REXX */
|
||||
Numeric Digits 30
|
||||
Call test '9 4 6 6'
|
||||
Call test '5 10 6 7'
|
||||
Exit
|
||||
test:
|
||||
Parse Arg w1 s1 w2 s2
|
||||
plist1=pp(w1,s1)
|
||||
p1.=0
|
||||
Do x=w1 To w1*s1
|
||||
Parse Var plist1 p1.x plist1
|
||||
End
|
||||
plist2=pp(w2,s2)
|
||||
p2.=0
|
||||
Do x=w2 To w2*s2
|
||||
Parse Var plist2 p2.x plist2
|
||||
End
|
||||
p2low.=0
|
||||
Do x=w1 To w1*s1
|
||||
Do y=0 To x-1
|
||||
p2low.x=p2low.x+p2.y
|
||||
End
|
||||
End
|
||||
pwin1=0
|
||||
Do x=w1 To w1*s1
|
||||
pwin1=pwin1+p1.x*p2low.x
|
||||
End
|
||||
Say 'Player 1 has' w1 'dice with' s1 'sides each'
|
||||
Say 'Player 2 has' w2 'dice with' s2 'sides each'
|
||||
Say 'Probability for player 1 to win:' pwin1
|
||||
Say ''
|
||||
Return
|
||||
|
||||
pp: Procedure
|
||||
/*---------------------------------------------------------------------
|
||||
* Compute and return the probabilities to get a sum x
|
||||
* when throwing w dice each having s sides (marked from 1 to s)
|
||||
*--------------------------------------------------------------------*/
|
||||
Parse Arg w,s
|
||||
str=''
|
||||
cnt.=0
|
||||
Do wi=1 To w
|
||||
str=str||'Do v'wi'=1 To' s';'
|
||||
End
|
||||
str=str||'sum='
|
||||
Do wi=1 To w-1
|
||||
str=str||'v'wi'+'
|
||||
End
|
||||
str=str||'v'w';'
|
||||
str=str||'cnt.'sum'=cnt.'sum'+1;'
|
||||
Do wi=1 To w
|
||||
str=str||'End;'
|
||||
End
|
||||
Interpret str
|
||||
psum=0
|
||||
Do x=0 To w*s
|
||||
p.x=cnt.x/(s**w)
|
||||
psum=psum+p.x
|
||||
End
|
||||
res=''
|
||||
Do x=w To s*w
|
||||
res=res p.x
|
||||
End
|
||||
Return res
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/* REXX */
|
||||
oid='diet.xxx'; 'erase' oid
|
||||
Call test '9 4 6 6'
|
||||
Call test '5 10 6 7'
|
||||
Exit
|
||||
test:
|
||||
Parse Arg n1 s1 n2 s2
|
||||
Call o 'Player 1:' n1 'dice with' s1 'sides each'
|
||||
Call o 'Player 2:' n2 'dice with' s2 'sides each'
|
||||
cnt1.=0
|
||||
cnt2.=0
|
||||
win.=0
|
||||
nn=10000
|
||||
Call time 'R'
|
||||
Do i=1 To nn
|
||||
sum1=sum(n1 s1) ; cnt1.sum1=cnt1.sum1+1
|
||||
sum2=sum(n2 s2) ; cnt2.sum2=cnt2.sum2+1
|
||||
Select
|
||||
When sum1>sum2 Then win.1=win.1+1
|
||||
When sum1<sum2 Then win.2=win.2+1
|
||||
Otherwise win.0=win.0+1
|
||||
End
|
||||
End
|
||||
Call o win.1/nn 'player 1 wins'
|
||||
Call o win.2/nn 'player 2 wins'
|
||||
Call o win.0/nn 'draws'
|
||||
/*
|
||||
Do i=min(n1,n2) To max(n1*s1,n2*s2)
|
||||
Call o right(i,2) format(cnt1.i,7) format(cnt2.i,7)
|
||||
End
|
||||
*/
|
||||
Call o time('E') 'seconds elapsed'
|
||||
Return
|
||||
|
||||
sum: Parse Arg n s
|
||||
sum=0
|
||||
Do k=1 To n
|
||||
sum=sum+rand(s)
|
||||
End
|
||||
Return sum
|
||||
|
||||
rand: Parse Arg n
|
||||
Return random(n-1)+1
|
||||
|
||||
o:
|
||||
Say arg(1)
|
||||
Return lineout(oid,arg(1))
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*REXX pgm computes and displays the probabilities of a two─player S─sided, N─dice game.*/
|
||||
numeric digits 100 /*increase/decrease to 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 " */
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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,,digits()%2) "%."
|
||||
say /* ↑ */
|
||||
return /*show 1/2 of 100 dec. digits────┘ */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
prob: procedure; parse arg n,s,,@ $; #.= 0; pow= s**n
|
||||
do j=1 for n; @= @'DO _'j"=1 FOR" 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.*/
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#lang racket
|
||||
|
||||
(define probs# (make-hash))
|
||||
|
||||
(define (NdD n d)
|
||||
(hash-ref!
|
||||
probs# (cons n d)
|
||||
(λ ()
|
||||
(cond
|
||||
[(= n 0) ; every chance of nothing!
|
||||
(hash 0 1)]
|
||||
[else
|
||||
(for*/fold ((hsh (hash))) (((i p) (in-hash (NdD (sub1 n) d))) (r (in-range 1 (+ d 1))))
|
||||
(hash-update hsh (+ r i) (λ (p+) (+ p+ (/ p d))) 0))]))))
|
||||
|
||||
(define (game-probs N1 D1 N2 D2)
|
||||
(define P1 (NdD N1 D1))
|
||||
(define P2 (NdD N2 D2))
|
||||
(define-values (W D L)
|
||||
(for*/fold ((win 0) (draw 0) (lose 0)) (((r1 p1) (in-hash P1)) ((r2 p2) (in-hash P2)))
|
||||
(define p (* p1 p2))
|
||||
(cond
|
||||
[(< r1 r2) (values win draw (+ lose p))]
|
||||
[(= r1 r2) (values win (+ draw p) lose)]
|
||||
[(> r1 r2) (values (+ win p) draw lose)])))
|
||||
|
||||
(printf "P(P1 win): ~a~%" (real->decimal-string W 6))
|
||||
(printf "P(draw): ~a~%" (real->decimal-string D 6))
|
||||
(printf "P(P2 win): ~a~%" (real->decimal-string L 6))
|
||||
(list W D L))
|
||||
|
||||
(printf "GAME 1 (9D4 vs 6D6)~%")
|
||||
(game-probs 9 4 6 6)
|
||||
(newline)
|
||||
|
||||
(printf "GAME 2 (5D10 vs 6D7) [what is a D7?]~%")
|
||||
(game-probs 5 10 6 7)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
sub likelihoods ($roll) {
|
||||
my ($dice, $faces) = $roll.comb(/\d+/);
|
||||
my @counts;
|
||||
@counts[$_]++ for [X+] |(1..$faces,) xx $dice;
|
||||
return [@counts[]:p], $faces ** $dice;
|
||||
}
|
||||
|
||||
sub beating-probability ([$roll1, $roll2]) {
|
||||
my (@c1, $p1) := likelihoods $roll1;
|
||||
my (@c2, $p2) := likelihoods $roll2;
|
||||
my $p12 = $p1 * $p2;
|
||||
|
||||
[+] gather for flat @c1 X @c2 -> $p, $q {
|
||||
take $p.value * $q.value / $p12 if $p.key > $q.key;
|
||||
}
|
||||
}
|
||||
|
||||
# We're using standard DnD notation for dice rolls here.
|
||||
say .gist, "\t", .raku given beating-probability < 9d4 6d6 >;
|
||||
say .gist, "\t", .raku given beating-probability < 5d10 6d7 >;
|
||||
25
Task/Dice-game-probabilities/Ruby/dice-game-probabilities.rb
Normal file
25
Task/Dice-game-probabilities/Ruby/dice-game-probabilities.rb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
def roll_dice(n_dice, n_faces)
|
||||
return [[0,1]] if n_dice.zero?
|
||||
one = [1] * n_faces
|
||||
zero = [0] * (n_faces-1)
|
||||
(1...n_dice).inject(one){|ary,_|
|
||||
(zero + ary + zero).each_cons(n_faces).map{|a| a.inject(:+)}
|
||||
}.map.with_index(n_dice){|n,sum| [sum,n]} # sum: total of the faces
|
||||
end
|
||||
|
||||
def game(dice1, faces1, dice2, faces2)
|
||||
p1 = roll_dice(dice1, faces1)
|
||||
p2 = roll_dice(dice2, faces2)
|
||||
p1.product(p2).each_with_object([0,0,0]) do |((sum1, n1), (sum2, n2)), win|
|
||||
win[sum1 <=> sum2] += n1 * n2 # [0]:draw, [1]:win, [-1]:lose
|
||||
end
|
||||
end
|
||||
|
||||
[[9, 4, 6, 6], [5, 10, 6, 7]].each do |d1, f1, d2, f2|
|
||||
puts "player 1 has #{d1} dice with #{f1} faces each"
|
||||
puts "player 2 has #{d2} dice with #{f2} faces each"
|
||||
win = game(d1, f1, d2, f2)
|
||||
sum = win.inject(:+)
|
||||
puts "Probability for player 1 to win: #{win[1]} / #{sum}",
|
||||
" -> #{win[1].fdiv(sum)}", ""
|
||||
end
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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));
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
func combos(sides, n) {
|
||||
n || return [1]
|
||||
var ret = ([0] * (n*sides.max + 1))
|
||||
combos(sides, n-1).each_kv { |i,v|
|
||||
v && for s in sides { ret[i + s] += v }
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func winning(sides1, n1, sides2, n2) {
|
||||
var (p1, p2) = (combos(sides1, n1), combos(sides2, n2))
|
||||
var (win,loss,tie) = (0,0,0)
|
||||
p1.each_kv { |i, x|
|
||||
win += x*p2.ft(0,i-1).sum
|
||||
tie += x*p2.ft(i, i).sum
|
||||
loss += x*p2.ft(i+1).sum
|
||||
}
|
||||
[win, tie, loss] »/» p1.sum*p2.sum
|
||||
}
|
||||
|
||||
func display_results(String title, Array res) {
|
||||
say "=> #{title}"
|
||||
for name, prob in (%w(p₁\ win tie p₂\ win) ~Z res) {
|
||||
say "P(#{'%6s' % name}) =~ #{prob.round(-11)} (#{prob.as_frac})"
|
||||
}
|
||||
print "\n"
|
||||
}
|
||||
|
||||
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))
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
foreach d0 {1 2 3 4 5 6} {
|
||||
foreach d1 {1 2 3 4 5 6} {
|
||||
...
|
||||
foreach dN {1 2 3 4 5 6} {
|
||||
dict incr sum [::tcl::mathop::+ $n $d0 $d1 ... $DN]
|
||||
}
|
||||
...
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
proc range {b} { ;# a common standard proc: [range 5] -> {0 1 2 3 4}
|
||||
set a 0
|
||||
set res {}
|
||||
while {$a < $b} {
|
||||
lappend res $a
|
||||
incr a
|
||||
}
|
||||
return $res
|
||||
}
|
||||
|
||||
# This proc builds up a nested foreach call, then evaluates it.
|
||||
#
|
||||
# The script is built up in $script, starting with the body using "%%" as
|
||||
# a placeholder.
|
||||
#
|
||||
# For each die, a level is wrapped around it as follows:
|
||||
# set script {foreach d0 {1 2 3 4 5 6} $script}
|
||||
# set script {foreach d1 {1 2 3 4 5 6} $script}
|
||||
#
|
||||
# .. and {$d0 $d1 ..} are collected in the variable $vars, which is used
|
||||
# to replace "%%" at the end.
|
||||
#
|
||||
# The script is evaluated with [try] - earlier Tcl's could use [catch] or [eval]
|
||||
proc NdK {n {k 6}} { ;# calculate a score histogram for $n dice of $k faces
|
||||
set sum {}
|
||||
set script {
|
||||
dict incr sum [::tcl::mathop::+ $n %%] ;# add $n because ranges are 0-based
|
||||
} ;# %% is a placeholder
|
||||
set vars ""
|
||||
for {set i 0} {$i < $n} {incr i} {
|
||||
set script [list foreach d$i [range $k] $script]
|
||||
append vars " \$d$i"
|
||||
}
|
||||
set script [string map [list %% $vars] $script]
|
||||
try $script
|
||||
return $sum
|
||||
}
|
||||
|
||||
proc win_pr {p1 p2} { ;# calculate the winning probability of player 1 given two score histograms
|
||||
set P 0
|
||||
set N 0
|
||||
dict for {d1 k1} $p1 {
|
||||
dict for {d2 k2} $p2 {
|
||||
set k [expr {$k1 * $k2}]
|
||||
incr N $k
|
||||
incr P [expr {$k * ($d1 > $d2)}]
|
||||
}
|
||||
}
|
||||
expr {$P * 1.0 / $N}
|
||||
}
|
||||
|
||||
foreach {p1 p2} {
|
||||
{9 4} {6 6}
|
||||
{5 10} {6 7}
|
||||
} {
|
||||
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]]]
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package require Tcl 8.6 ;# for [tailcall] - otherwise use [uplevel 1 $script]
|
||||
# This proc builds up a nested foreach call, then evaluates it.
|
||||
#
|
||||
# this:
|
||||
# foreach* a {1 2 3} b {4 5 6} {
|
||||
# puts "$a + $b"
|
||||
# }
|
||||
#
|
||||
# becomes:
|
||||
# foreach a {1 2 3} {
|
||||
# foreach b {4 5 6} {
|
||||
# puts "$a + $b"
|
||||
# }
|
||||
# }
|
||||
proc foreach* {args} {
|
||||
set script [lindex $args end]
|
||||
set args [lrange $args 0 end-1]
|
||||
foreach {b a} [lreverse $args] {
|
||||
set script [list foreach $a $b $script]
|
||||
}
|
||||
tailcall {*}$script
|
||||
}
|
||||
|
||||
proc NdK {n {k 6}} { ;# calculate a score histogram for $n dice of $k faces
|
||||
|
||||
set args {} ;# arguments to [foreach*]
|
||||
set vars {} ;# variables used in [foreach*] arguments that need to be added to sum
|
||||
set sum {} ;# this will be the result dictionary
|
||||
|
||||
for {set i 0} {$i < $n} {incr i} {
|
||||
lappend args d$i [range $k]
|
||||
lappend vars "\$d$i"
|
||||
}
|
||||
|
||||
set vars [join $vars +]
|
||||
|
||||
# [string map] to avoid "Quoting Hell"
|
||||
set script [string map [list %% $vars] {
|
||||
dict incr sum [expr {$n + %%}] ;# $n because [range] is 0-based
|
||||
}]
|
||||
|
||||
foreach* {*}$args $script
|
||||
return $sum
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
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))
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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))
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
fcn combos(sides, n){
|
||||
if(not n) return(T(1));
|
||||
ret:=((0).max(sides)*n + 1).pump(List(),0);
|
||||
foreach i,v in (combos(sides, n - 1).enumerate()){
|
||||
if(not v) continue;
|
||||
foreach s in (sides){ ret[i + s] += v }
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
fcn winning(sides1,n1, sides2,n2){
|
||||
p1, p2 := combos(sides1, n1), combos(sides2, n2);
|
||||
win,loss,tie := 0,0,0; # 'win' is 1 beating 2
|
||||
foreach i,x1 in (p1.enumerate()){
|
||||
# using accumulated sum on p2 could save some time
|
||||
win += x1*p2[0,i].sum(0);
|
||||
tie += x1*p2[i,1].sum(0); // i>p2.len() but p2[bigi,?]-->[]
|
||||
loss+= x1*p2[i+1,*].sum(0);
|
||||
}
|
||||
s := p1.sum(0)*p2.sum(0);
|
||||
return(win.toFloat()/s, tie.toFloat()/s, loss.toFloat()/s);
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
println(winning([1..4].walk(), 9, [1..6].walk(),6));
|
||||
println(winning([1..10].walk(),5, [1..7].walk(),6)); # this seem hardly fair
|
||||
Loading…
Add table
Add a link
Reference in a new issue