Seven-sided dice from five-sided dice: Difference between revisions
Seven-sided dice from five-sided dice (view source)
Revision as of 22:56, 13 February 2024
, 3 months ago→{{header|EasyLang}}
(22 intermediate revisions by 9 users not shown) | |||
Line 19:
{{trans|Python}}
<
R random:(1..5)
Line 36:
distcheck(dice5, 1000000, 1)
distcheck(dice7, 1000000, 1)</
{{out}}
Line 46:
=={{header|Ada}}==
The specification of a package Random_57:
<
type Mod_7 is mod 7;
Line 55:
-- a simple implementation
end Random_57;</
Implementation of Random_57:
<
package body Random_57 is
Line 113:
begin
Rand_5.Reset(Gen);
end Random_57;</
A main program, using the Random_57 package:
<
procedure R57 is
Line 165:
Test( 1_000_000, Rand'Access, 0.02);
Test(10_000_000, Rand'Access, 0.01);
end R57;</
{{out}}
<pre>
Line 198:
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d]}}
C's version using no multiplications, divisions, or mod operators:
<
1 + ENTIER (5*random);
Line 232:
distcheck(dice5, 1000000, 5);
distcheck(dice7, 1000000, 7)
)</
{{out}}
<pre>
Line 240:
=={{header|AutoHotkey}}==
<
{ Random, v, 1, 5
Return, v
Line 250:
IfLess v, 21, Return, (v // 3) + 1
}
}</
<pre>Distribution check:
Line 267:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<
FOR r% = 2 TO 5
check% = FNdistcheck(FNdice7, 10^r%, 0.1)
Line 297:
IF bins%(i%)/(repet%/m%) < 1-delta s% += 1
NEXT
= s%</
{{out}}
<pre>
Line 307:
=={{header|C}}==
<
{
int r, rand_max = RAND_MAX - (RAND_MAX % 5);
Line 326:
printf(check(rand7, 7, 1000000, .05) ? "flat\n" : "not flat\n");
return 0;
}</
{{out}}
<pre>
Line 335:
=={{header|C sharp}}==
{{trans|Java}}
<
using System;
Line 361:
return 1 + random.Next(5);
}
}</
=={{header|C++}}==
This solution tries to minimize calls to the underlying d5 by reusing information from earlier calls.
<
{
public:
Line 413:
test_distribution(d5, 1000000, 0.001);
test_distribution(d7, 1000000, 0.001);
}</
=={{header|Clojure}}==
Uses the verify function defined in [[Verify distribution uniformity/Naive#Clojure]]
<
(defn dice7 []
Line 431:
(doseq [n [100 1000 10000] [num count okay?] (verify dice7 n)]
(println "Saw" num count "times:"
(if okay? "that's" " not") "acceptable"))</
<pre>Saw 0 10 times: not acceptable
Line 457:
=={{header|Common Lisp}}==
{{trans|C}}
<
(1+ (random 5)))
Line 463:
(loop for d55 = (+ (* 5 (d5)) (d5) -6)
until (< d55 21)
finally (return (1+ (mod d55 7)))))</
<pre>> (check-distribution 'd7 1000)
Line 479:
=={{header|D}}==
{{trans|C++}}
<
import verify_distribution_uniformity_naive: distCheck;
Line 525:
distCheck(&fiveToSevenNaive, N, 1);
distCheck(&fiveToSevenSmart, N, 1);
}</
{{out}}
<pre>1 80365
Line 552:
{{trans|Common Lisp}}
{{improve|E|Write dice7 in a prettier fashion and use the distribution checker once it's been written.}}
<
return entropy.nextInt(5) + 1
}
Line 560:
while ((d55 := 5 * dice5() + dice5() - 6) >= 21) {}
return d55 %% 7 + 1
}</
<
for x in 1..1000 {
bins[dice7() - 1] += 1
}
println(bins.snapshot())</
=={{header|EasyLang}}==
<syntaxhighlight>
func dice5 .
return randint 5
.
func dice25 .
return (dice5 - 1) * 5 + dice5
.
func dice7a .
return dice25 mod1 7
.
func dice7b .
repeat
h = dice25
until h <= 21
.
return h mod1 7
.
numfmt 3 0
n = 1000000
len dist[] 7
#
proc checkdist . .
for i to len dist[]
h = dist[i] / n * 7
if abs (h - 1) > 0.01
bad = 1
.
dist[i] = 0
print h
.
if bad = 1
print "-> not uniform"
else
print "-> uniform"
.
.
#
for i to n
dist[dice7a] += 1
.
checkdist
#
print ""
for i to n
dist[dice7b] += 1
.
checkdist
</syntaxhighlight>
{{out}}
<pre>
1.122
1.118
1.121
1.117
0.840
0.842
0.840
-> not uniform
0.996
1.003
1.001
0.997
1.004
0.998
1.001
-> uniform
</pre>
=={{header|Elixir}}==
<
def dice5, do: :rand.uniform( 5 )
Line 585 ⟶ 656:
IO.inspect VerifyDistribution.naive( fun5, 1000000, 3 )
fun7 = fn -> Dice.dice7 end
IO.inspect VerifyDistribution.naive( fun7, 1000000, 3 )</
{{out}}
Line 594 ⟶ 665:
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
-module( dice ).
Line 611 ⟶ 682:
dice7_small_enough( N ) when N < 21 -> N div 3 + 1;
dice7_small_enough( _N ) -> dice7().
</syntaxhighlight>
{{out}}
Line 620 ⟶ 691:
=={{header|Factor}}==
<
math math.functions math.statistics math.vectors math.ranges ;
IN: rosetta-code.dice7
Line 676 ⟶ 747:
{ 1 10 100 1000 10000 100000 1000000 }
[| times | 0.02 7 [ dice7 ] times verify ] each
;</
{{out}}
Line 697 ⟶ 768:
=={{header|Forth}}==
{{works with|GNU Forth}}
<
: d5 5 random 1+ ;
Line 703 ⟶ 774:
: d7
begin d5 d5 2dup discard? while 2drop repeat
1- 5 * + 1- 7 mod 1+ ;</
{{out}}
<pre>cr ' d7 1000000 7 1 check-distribution .
Line 718 ⟶ 789:
=={{header|Fortran}}==
{{works with|Fortran|95 and later}}
<
implicit none
Line 754 ⟶ 825:
call distcheck(rand7, samples, 0.001)
end program</
{{out}}
<pre>Distribution Uniform
Line 769 ⟶ 840:
=={{header|FreeBASIC}}==
{{trans|Liberty BASIC}}
<
Function dice5() As Integer
Return Int(Rnd * 5) + 1
Line 786 ⟶ 857:
If Not(distCheck(n, 0.05)) Then Print "Test failed" Else Print "Test passed"
Sleep
</syntaxhighlight>
{{out}}
<pre>
Line 793 ⟶ 864:
=={{header|Go}}==
<
import (
Line 848 ⟶ 919:
max, flatEnough = distCheck(dice7, 7, calls, 500)
fmt.Println("Max delta:", max, "Flat enough:", flatEnough)
}</
{{out}}
<pre>
Line 856 ⟶ 927:
=={{header|Groovy}}==
<
int rand5() {
Line 868 ⟶ 939:
}
(raw % 7) + 1
}</
Test:
<
(1..6). each {
def counts = [0g, 0g, 0g, 0g, 0g, 0g, 0g]
Line 895 ⟶ 966:
=============="""
test(it)
}</
{{out}}
<pre style="height:30ex;overflow:scroll;">TRIAL #1
Line 1,005 ⟶ 1,076:
=={{header|Haskell}}==
<
import Data.List
Line 1,013 ⟶ 1,084:
let d7 = 5*d51+d52-6
if d7 > 20 then sevenFrom5Dice
else return $ 1 + d7 `mod` 7</
{{out}}
<
[2,3,1,1,6,2,5,6,5,3]</
Test:
<
(1,(142759,True))
(2,(143078,True))
Line 1,025 ⟶ 1,096:
(5,(142896,True))
(6,(143028,True))
(7,(143130,True))</
=={{header|Icon}} and {{header|Unicon}}==
{{trans|Ruby}}
Uses <code>verify_uniform</code> from [[Simple_Random_Distribution_Checker#Icon_and_Unicon|here]].
<syntaxhighlight lang="icon">
$include "distribution-checker.icn"
Line 1,046 ⟶ 1,117:
else write ("skewed")
end
</syntaxhighlight>
{{out}}
Line 1,062 ⟶ 1,133:
=={{header|J}}==
The first step is to create 7-sided dice rolls from 5-sided dice rolls (<code>rollD5</code>):
<
roll2xD5=: [: rollD5 2 ,~ */ NB. rolls D5 twice for each desired D7 roll (y rows, 2 cols)
toBase10=: 5 #. <: NB. decrements and converts rows from base 5 to 10
Line 1,068 ⟶ 1,139:
groupin3s=: [: >. >: % 3: NB. increments, divides by 3 and takes ceiling
getD7=: groupin3s@keepGood@toBase10@roll2xD5</
Here are a couple of variations on the theme that achieve the same result:
<
getD7c=: [: (#~ 7&>:) 3 >.@%~ [: 5&#.&.:<:@rollD5 ] , 2:</
The trouble is that we probably don't have enough D7 rolls yet because we compressed out any double D5 rolls that evaluated to 21 or more. So we need to accumulate some more D7 rolls until we have enough. J has two types of verb definition - tacit (arguments not referenced) and explicit (more conventional function definitions) illustrated below:
Here's an explicit definition that accumulates rolls from <code>getD7</code>:
<
n=. */y NB. product of vector y is total number of D7 rolls required
rolls=. '' NB. initialize empty noun rolls
Line 1,082 ⟶ 1,153:
end.
y $ rolls NB. shape the result according to the vector y
)</
Here's a tacit definition that does the same thing:
<
accumD7Rolls=: ] , getD7@getNumRolls NB. accumulates getD7 rolls
isNotEnough=: */@[ > #@] NB. checks if enough D7 rolls accumulated
rollD7t=: ] $ (accumD7Rolls ^: isNotEnough ^:_)&''</
The <code>verb1 ^: verb2 ^:_</code> construct repeats <code>x verb1 y</code> while <code>x verb2 y</code> is true. It is like saying "Repeat accumD7Rolls while isNotEnough".
Example usage:
<
6 4 5 1 4 2 4 5 2 5
rollD7t 2 5 NB. 2 by 5 array of D7 rolls
Line 1,110 ⟶ 1,181:
1
($@rollD7x -: $@rollD7t) 2 3 5
1</
=={{header|Java}}==
{{trans|Python}}
<
public class SevenSidedDice
{
Line 1,134 ⟶ 1,205:
return 1+rnd.nextInt(5);
}
}</
=={{header|JavaScript}}==
{{trans|Ruby}}
<
{
return 1 + Math.floor(5 * Math.random());
Line 1,155 ⟶ 1,226:
distcheck(dice5, 1000000);
print();
distcheck(dice7, 1000000);</
{{out}}
<pre>1 199792
Line 1,170 ⟶ 1,241:
6 142648
7 142619 </pre>
=={{header|jq}}==
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq.'''
In this entry, the results for both a low-entropy and a
high-entropy 5-sided die are shown. The former uses the computer's
clock as a not-very-good PRNG, and the latter uses /dev/random in accordance
with the following invocation:
<syntaxhighlight lang=sh>
#!/bin/bash
< /dev/random tr -cd '0-9' | fold -w 1 | jq -Mcnr -f dice.jq
</syntaxhighlight>
The results employ a two-tailed χ2-test at the 95% confidence level
according to which we are entitled to reject the null hypothesis of
uniform randomness if the χ2 statistic is less than 1.69 or greater
than 16.013, assuming the number of trials is large enough.
See https://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm
'''dice.jq'''
<syntaxhighlight lang=jq>
# Output: a PRN in range(0;$n) where $n is .
def prn:
if . == 1 then 0
else . as $n
| (($n-1)|tostring|length) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then . else ($n | prn) end
end;
# Emit a stream of [value, frequency] pairs
def histogram(stream):
reduce stream as $s ({};
($s|type) as $t
| (if $t == "string" then $s else ($s|tojson) end) as $y
| .[$t][$y][0] = $s
| .[$t][$y][1] += 1 )
| .[][] ;
# sum of squares
def ss(s): reduce s as $x (0; . + ($x * $x));
def chiSquared($expected):
debug # show the actual frequencies
| ss( .[] - $expected ) / $expected;
# The high-entropy 5-sided die
def dice5: 1 + (5|prn);
# The low-entropy 5-sided die
def pseudo_dice5:
def r: (now * 100000 | floor) % 10;
null | until(. and (. < 5); r) | 1 + . ;
# The formal argument dice5 should behave like a 5-sided dice:
def dice7(dice5):
1 + ([limit(7; repeat(dice5))]|add % 7) ;
# Issue a report on the results of a sequence of $n trials using the specified dice
def report(dice; $n):
1.69 as $lower
| 16.013 as $upper
| [histogram( limit($n; repeat(dice)) ) | last]
| chiSquared($n/7) as $x2
| "The χ2 statistic for a trial of \($n) virtual tosses is \($x2).",
"Using a two-sided χ2-test with seven degrees of freedom (\($lower), \($upper)), it is reasonable to conclude that",
(if $x2 < $lower then "this is lower than would be expected for a fair die."
elif $x2 > $upper then "this is higher than would be expected for a fair die."
else "this is consistent with the die being fair."
end) ;
def report($n):
"Low-entropy die results:",
report(dice7(pseudo_dice5); $n),
"",
"High-entropy die results:",
report(dice7(dice5); $n) ;
report(70)
</syntaxhighlight>
{{output}}
<pre>
Low-entropy die results:
["DEBUG:",[19,14,6,18,7,5,1]]
The χ2 statistic for a trial of 70 virtual tosses is 29.2.
Using a two-sided χ2-test with seven degrees of freedom (1.69, 16.013), it is reasonable to conclude that
this is higher than would be expected for a fair die.
High-entropy die results:
["DEBUG:",[9,11,9,10,15,11,5]]
The χ2 statistic for a trial of 70 virtual tosses is 5.4.
Using a two-sided χ2-test with seven degrees of freedom (1.69, 16.013), it is reasonable to conclude that
this is consistent with the die being fair.
</pre>
'''Results for 1,000,000 trials:'''
<pre>
Low-entropy die results:
["DEBUG:",[41440,57949,15946,44821,117168,339337,383339]]
The χ2 statistic for a trial of 1000000 virtual tosses is 982157.0011039999.
Using a two-sided χ2-test with seven degrees of freedom (1.69, 16.013), it is reasonable to conclude that
this is higher than would be expected for a fair die.
High-entropy die results:
["DEBUG:",[142860,143087,142213,142065,143359,143494,142922]]
The χ2 statistic for a trial of 1000000 virtual tosses is 12.298347999999999.
Using a two-sided χ2-test with seven degrees of freedom (1.69, 16.013), it is reasonable to conclude that
this is consistent with the die being fair.
</pre>
=={{header|Julia}}==
<syntaxhighlight lang="julia">
using Random: seed!
seed!(1234) # for reproducibility
dice5() = rand(1:5)
function dice7()
while true
b = dice5()
c = a + 5(b - 1)
if c <= 21
return mod1(c, 7)
end
end
end
roll_counts = Dict{Int,Int}()
for roll in rolls
roll_counts[roll] = get(roll_counts, roll, 0) + 1
end
foreach(println, sort(roll_counts))
</syntaxhighlight>
Output:
<pre>
1 => 14530
2 => 13872
3 => 14422
4 => 14425
5 => 14323
6 => 14315
7 => 14113
</pre>
=={{header|Kotlin}}==
<
import java.util.Random
Line 1,229 ⟶ 1,433:
fun main(args: Array<String>) {
checkDist(::dice7, 1_400_000)
}</
Sample output:
Line 1,249 ⟶ 1,453:
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
n=1000000 '1000000 would take several minutes
print "Testing ";n;" times"
Line 1,273 ⟶ 1,477:
dice5=1+int(rnd(0)*5) '1..5: dice5
end function
</syntaxhighlight>
{{Out}}
<pre>
Line 1,291 ⟶ 1,495:
=={{header|Lua}}==
<
function dice7()
Line 1,297 ⟶ 1,501:
if x > 20 then return dice7() end
return x%7 + 1
end</
=={{header|M2000 Interpreter}}==
Line 1,303 ⟶ 1,507:
We check for uniform numbers using +-5% from expected value.
<syntaxhighlight lang="m2000 interpreter">
Module CheckIt {
Def long i, calls, max, min
Line 1,339 ⟶ 1,543:
}
CheckIt
</syntaxhighlight>
{{out}}
Line 1,366 ⟶ 1,570:
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
If [tmp$ < 21, 1 + Mod[tmp$ , 7], sevenFrom5Dice])</
<pre>CheckDistribution[sevenFrom5Dice, 1000000, 5]
->Expected: 142857., Generated :{142206,142590,142650,142693,142730,143475,143656}
Line 1,374 ⟶ 1,578:
=={{header|Nim}}==
We use the distribution checker from task [[Simple Random Distribution Checker#Nim|Simple Random Distribution Checker]].
<
Line 1,409 ⟶ 1,613:
import random
randomize()
checkDist(dice7, 1_000_000, 0.5)</
{{out}}
Line 1,417 ⟶ 1,621:
=={{header|OCaml}}==
<
let dice7 =
Line 1,433 ⟶ 1,637:
in
aux
;;</
=={{header|PARI/GP}}==
<
dice7()={
Line 1,442 ⟶ 1,646:
while((t=dice5()*5+dice5()) > 21,);
(t+2)\3
};</
=={{header|Pascal}}==
A console application in Free Pascal, created with the Lazarus IDE.
The algorithm suggested in the task description requires on average 50/21 (about 2.38) calls to Dice5 for each call to Dice7. See the link in the VBA solution for a discussion on how to reduce this ratio. It cannot be made less than log_5(7) = 1.209062. The algorithm below is based on Rex Kerr's solution, and requires about 1.2185 calls to Dice5 per call to Dice7. Runtime is about 60% of that for the suggested simple algorithm.
A chi-squared test can be carried out with the help of statistical tables, and is preferred here to an arbitrary "naive" test.
<syntaxhighlight lang="pascal">
unit UConverter;
(*
Defines a converter object to output uniformly distributed random integers 1..7,
given a source of uniformly distributed random integers 1..5.
*)
interface
type
TFace5 = 1..5;
TFace7 = 1..7;
TDice5 = function() : TFace5;
type TConverter = class( TObject)
private
fDigitBuf: array [0..19] of integer; // holds digits in base 7
fBufCount, fBufPtr : integer;
fDice5 : TDice5; // passed-in generator for integers 1..5
fNrDice5 : int64; // diagnostics, counts calls to fDice5
public
constructor Create( aDice5 : TDice5);
procedure Reset();
function Dice7() : TFace7;
property NrDice5 : int64 read fNrDice5;
end;
implementation
constructor TConverter.Create( aDice5 : TDice5);
begin
inherited Create();
fDice5 := aDice5;
self.Reset();
end;
procedure TConverter.Reset();
begin
fBufCount := 0;
fBufPtr := 0;
fNrDice5 := 0;
end;
function TConverter.Dice7() : TFace7;
var
digit_holder, temp : int64;
j : integer;
begin
if fBufPtr = fBufCount then begin // if no more in buffer
fBufCount := 0;
fBufPtr := 0;
repeat // first time through will usually be enough
// Use supplied fDice5 to generate random 23-digit integer in base 5.
digit_holder := 0;
for j := 0 to 22 do begin
digit_holder := 5*digit_holder + fDice5() - 1;
inc( fNrDice5);
end;
// Convert to 20-digit number in base 7. (A simultaneous DivMod
// procedure would be neater, but isn't available for int64.)
for j := 0 to 19 do begin
temp := digit_holder div 7;
fDigitBuf[j] := digit_holder - 7*temp;
digit_holder := temp;
end;
// Maximum possible is 5^23 - 1, which is 10214646460315315132 in base 7.
// If leading digit in base 7 is 0 then low 19 digits are random.
// Else number begins with 100, 101, or 102; and if with
// 100 or 101 then low 17 digits are random. And so on.
if fDigitBuf[19] = 0 then fBufCount := 19
else if fDigitBuf[17] < 2 then fBufCount := 17
else if fDigitBuf[16] = 0 then fBufCount := 16;
// We could go on but that will do.
until fBufCount > 0;
end; // if no more in buffer
result := fDigitBuf[fBufPtr] + 1;
inc( fBufPtr);
end;
end.
program Dice_SevenFromFive;
(*
Demonstrates use of the UConverter unit.
*)
{$mode objfpc}{$H+}
uses
SysUtils, UConverter;
function Dice5() : UConverter.TFace5;
begin
result := Random(5) + 1; // Random(5) returns 0..4
end;
// Percentage points of the chi-squared distribution, 6 degrees of freedom.
// From New Cambridge Statistical Tables, 2nd edn, pp. 40-41.
const
CHI_SQ_6df_95pc = 1.635;
CHI_SQ_6df_05pc = 12.59;
// Main routine
var
nrThrows, j, k : integer;
nrFaces : array [1..7] of integer;
X2, expected, diff : double;
conv : UConverter.TConverter;
begin
conv := UConverter.TConverter.Create( @Dice5);
WriteLn( 'Enter 0 throws to quit');
repeat
WriteLn(''); Write( 'Number of throws (0 to quit): ');
ReadLn( nrThrows);
if nrThrows = 0 then begin
conv.Free();
exit;
end;
conv.Reset(); // clears count of calls to Dice5
for k := 1 to 7 do nrFaces[k] := 0;
for j := 1 to nrThrows do begin
k := conv.Dice7();
inc( nrFaces[k]);
end;
WriteLn('');
WriteLn( SysUtils.Format( 'Number of throws = %10d', [nrThrows]));
WriteLn( SysUtils.Format( 'Calls to Dice5 = %10d', [conv.NrDice5]));
for k := 1 to 7 do
WriteLn( SysUtils.Format( ' Number of %d''s = %10d', [k, nrFaces[k]]));
// Calculation of chi-squared
expected := nrThrows/7.0;
X2 := 0.0;
for k := 1 to 7 do begin
diff := nrFaces[k] - expected;
X2 := X2 + diff*diff/expected;
end;
WriteLn( SysUtils.Format( 'X^2 = %0.3f on 6 degrees of freedom', [X2]));
if X2 < CHI_SQ_6df_95pc then WriteLn( 'Too regular at 5% level')
else if X2 > CHI_SQ_6df_05pc then WriteLn( 'Too irregular at 5% level')
else WriteLn( 'Satisfactory at 5% level')
until false;
end.
</syntaxhighlight>
{{out}}
<pre>
Number of throws = 100000000
Calls to Dice5 = 121846341
Number of 1's = 14282807
Number of 2's = 14282277
Number of 3's = 14288393
Number of 4's = 14285486
Number of 5's = 14289379
Number of 6's = 14291053
Number of 7's = 14280605
X^2 = 6.687 on 6 degrees of freedom
Satisfactory at 5% level
</pre>
=={{header|Perl}}==
Using dice5 twice to generate numbers in the range 0 to 24. If we consider these modulo 8 and re-call if we get zero, we have eliminated 4 cases and created the necessary number in the range from 1 to 7.
<
sub dice7 {
Line 1,459 ⟶ 1,824:
$count7{dice7()}++ for 1..$n;
printf "%s: %5.2f%%\n", $_, 100*($count7{$_}/$n*7-1) for sort keys %count7;
</syntaxhighlight>
{{out}}
<pre>
Line 1,473 ⟶ 1,838:
=={{header|Phix}}==
replace rand7() in [[Verify_distribution_uniformity/Naive#Phix]] with:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">dice5</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">dice7</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dice5</span><span style="color: #0000FF;">()*</span><span style="color: #000000;">5</span><span style="color: #0000FF;">+</span><span style="color: #000000;">dice5</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">3</span> <span style="color: #000080;font-style:italic;">-- ( ie 3..27, but )</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">r</span><span style="color: #0000FF;"><</span><span style="color: #000000;">24</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (only 3..23 useful)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,489 ⟶ 1,856:
=={{header|PicoLisp}}==
<
(rand 1 5) )
Line 1,495 ⟶ 1,862:
(use R
(until (> 21 (setq R (+ (* 5 (dice5)) (dice5) -6))))
(inc (% R 7)) ) )</
{{out}}
<pre>: (let R NIL
Line 1,504 ⟶ 1,871:
=={{header|PureBasic}}==
{{trans|Lua}}
<
ProcedureReturn Random(4) + 1
EndProcedure
Line 1,517 ⟶ 1,884:
ProcedureReturn x % 7 + 1
EndProcedure</
=={{header|Python}}==
<
def dice5():
Line 1,527 ⟶ 1,894:
def dice7():
r = dice5() + dice5() * 5 - 6
return (r % 7) + 1 if r < 21 else dice7()</
Distribution check using [[Simple Random Distribution Checker#Python|Simple Random Distribution Checker]]:
<pre>>>> distcheck(dice5, 1000000, 1)
Line 1,534 ⟶ 1,901:
{1: 142853, 2: 142576, 3: 143067, 4: 142149, 5: 143189, 6: 143285, 7: 142881}
</pre>
=={{header|Quackery}}==
<syntaxhighlight lang="quackery"> [ 5 random 1+ ] is dice5 ( --> n )
[ dice5 5 *
dice5 + 6 -
[ table
0 0 0 0 1
1 1 2 2 2
3 3 3 4 4
4 5 5 5 6
6 6 7 7 7 ]
dup 0 = iff
drop again ] is dice7 ( --> n )</syntaxhighlight>
{{out}}
<code>distribution</code> is defined at [[Verify distribution uniformity/Naive#Quackery]].
<pre>/O> ' dice7 1000000 666 distribution
...
[ 143196 142815 143451 142716 142964 142300 142558 ]
Stack empty.</pre>
=={{header|R}}==
5-sided die.
<
Simple but slow 7-sided die, using a while loop.
<
{
score <- numeric()
Line 1,549 ⟶ 1,940:
score
}
system.time(dice7.while(1e6)) # longer than 4 minutes</
More complex, but much faster vectorised version.
<
{
morethan2n <- 3 * n + 10 + (n %% 2) #need more than 2*n samples, because some are discarded
Line 1,568 ⟶ 1,959:
} else score
}
system.time(dice7.vec(1e6)) # ~1 sec</
=={{header|Racket}}==
<syntaxhighlight lang="racket">
#lang racket
(define (dice5) (add1 (random 5)))
Line 1,578 ⟶ 1,969:
(define res (+ (* 5 (dice5)) (dice5) -6))
(if (< res 21) (+ 1 (modulo res 7)) (dice7)))
</syntaxhighlight>
Checking the uniformity using math library:
<
-> (require math/statistics)
-> (samples->hash (for/list ([i 700000]) (dice7)))
Line 1,592 ⟶ 1,983:
(2 . 99927)
(1 . 99622))
</syntaxhighlight>
=={{header|Raku}}==
Line 1,598 ⟶ 1,989:
{{works with|Rakudo|2018.03}}
<syntaxhighlight lang="raku"
sub d5() { $d5.roll; } # 1d5
Line 1,617 ⟶ 2,008:
for @dist.kv -> $i, $v {
say "$i\t$v\t" ~ (($v - $expect)/$expect*100).fmt("%+.2f%%") if $v;
}</
{{out}}
<pre>Expect 142857.143
Line 1,630 ⟶ 2,021:
=={{header|REXX}}==
<
parse arg trials sample seed . /*obtain optional arguments from the CL*/
if trials=='' | trials="," then trials= 1 /*Not specified? Then use the default.*/
Line 1,651 ⟶ 2,042:
' difference from expected:'right(die.j - expect, length(sample) )
end /*j*/
end /*#*/ /*stick a fork in it, we're all done. */</
{{out|output|text= when using the input of: <tt> 11 </tt>}}
Line 1,758 ⟶ 2,149:
=={{header|Ring}}==
<
# Project : Seven-sided dice from five-sided dice
Line 1,778 ⟶ 2,169:
rnd = random(4) + 1
return rnd
</syntaxhighlight>
Output:
<pre>
7 6 3 5 2 2 7 1 2 7 3 7 4 4 4 2 3 2 6 1
</pre>
=={{header|RPL}}==
<code>UNIF?</code> is defined at [[Verify distribution uniformity/Naive#RPL|Verify distribution uniformity/Naive]]
{{works with|Halcyon Calc|4.2.7}}
≪ ≪ RAND 5 * CEIL ≫ → dice5
≪ '''WHILE'''
dice5 EVAL 5 *
dice5 EVAL 6 - +
DUP 21 ≥
'''REPEAT''' DROP '''END'''
7 MOD 1 +
≫ ≫ '<span style="color:blue">DICE7</span>' STO
≪ <span style="color:blue">DICE7</span> ≫ 100000 .1 <span style="color:blue">UNIF?</span>
{{out}}
<pre>
1: [ 14557 14245 14255 14400 14224 14151 14168 ]
</pre>
Watchdog timer limits the loop to 100,000 items.
=={{header|Ruby}}==
{{trans|Tcl}}
Uses <code>distcheck</code> from [[Simple_Random_Distribution_Checker#Ruby|here]].
<
def d5
Line 1,801 ⟶ 2,211:
distcheck(1_000_000) {d5}
distcheck(1_000_000) {d7}</
{{out}}
Line 1,819 ⟶ 2,229:
=={{header|Scala}}==
{{Out}}Best seen running in your browser either by [https://scalafiddle.io/sf/3RNtNEC/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/Y5qSeW52QiC40l5vJCUMRA Scastie (remote JVM)].
<
object SevenSidedDice extends App {
Line 1,835 ⟶ 2,245:
println("Random number from 1 to 7: " + seven)
}</
=={{header|Sidef}}==
{{trans|Perl}}
<
func dice7 {
Line 1,854 ⟶ 2,264:
count7.keys.sort.each { |k|
printf("%s: %5.2f%%\n", k, 100*(count7{k}/n * 7 - 1));
}</
{{out}}
<pre>1: -0.00%
Line 1,866 ⟶ 2,276:
=={{header|Tcl}}==
Any old D&D hand will know these as a D5 and a D7...
<
proc D7 {} {
Line 1,875 ⟶ 2,285:
}
}
}</
Checking:
<span class="sy0">%</span> distcheck D5 <span class="nu0">1000000</span>
Line 1,884 ⟶ 2,294:
=={{header|VBA}}==
The original StackOverflow page doesn't exist any longer. Luckily [https://web.archive.org/web/20100730055051/http://stackoverflow.com:80/questions/137783/given-a-function-which-produces-a-random-integer-in-the-range-1-to-5-write-a-fun archive.org] exists.
<
'Returns true if the observed frequencies pass the Pearson Chi-squared test at the required significance level.
Dim Total As Long, Ei As Long, i As Integer
Line 1,925 ⟶ 2,335:
Next i
Debug.Print "[1] ""Uniform? "; Test4DiscreteUniformDistribution(Bins, 0.05); """"
End Sub</
{{out}}<pre>[1] "Data set:" 142418 142898 142940 142573 143030 143139 143002
Chi-squared test for given frequencies
Line 1,933 ⟶ 2,343:
=={{header|VBScript}}==
<
function dice5
Line 1,945 ⟶ 2,355:
loop until j < 21
dice7 = j mod 7 + 1
end function</
=={{header|Verilog}}==
<
///////////////////////////////////////////////////////////////////////////////
Line 2,072 ⟶ 2,482:
end
endmodule
</syntaxhighlight>
Compiling with Icarus Verilog
Line 2,100 ⟶ 2,510:
{{libheader|Wren-sort}}
{{libheader|Wren-fmt}}
<
import "./sort" for Sort
import "./fmt" for Fmt
var r = Random.new()
Line 2,142 ⟶ 2,552:
}
checkDist.call(dice7, 1400000, 0.5)</
{{out}}
Line 2,162 ⟶ 2,572:
=={{header|zkl}}==
<
fcn die7{ while((r:=5*die5() + die5())>=27){} r/3-1 }
Line 2,173 ⟶ 2,583:
println("Looking for ",100.0/7,"%");
rtest(0d1_000_000);</
{{out}}
<pre>
|