Knuth's algorithm S: Difference between revisions

added RPL
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
(added RPL)
 
(16 intermediate revisions by 12 users not shown)
Line 29:
* [[Accumulator factory]]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">T S_of_n_creator
Int n
i = 0
[Int] sample
 
F (n)
.n = n
 
F ()(item)
.i++
I .i <= .n
.sample.append(item)
E I random:(.i) < .n
.sample[random:(.n)] = item
 
V binarr = [0] * 10
V items = Array(0..9)
print(‘Single run samples for n = 3:’)
V s_of_n = S_of_n_creator(3)
L(item) items
s_of_n(item)
print(‘ Item: #. -> sample: #.’.format(item, s_of_n.sample))
 
L 100000
s_of_n = S_of_n_creator(3)
L(item) items
s_of_n(item)
L(s) s_of_n.sample
binarr[s]++
print("\nTest item frequencies for 100000 runs:\n "(enumerate(binarr).map((i, x) -> ‘#.:#.’.format(i, x)).join("\n ")))</syntaxhighlight>
 
{{out}}
<pre>
Single run samples for n = 3:
Item: 0 -> sample: [0]
Item: 1 -> sample: [0, 1]
Item: 2 -> sample: [0, 1, 2]
Item: 3 -> sample: [3, 1, 2]
Item: 4 -> sample: [3, 1, 2]
Item: 5 -> sample: [3, 1, 2]
Item: 6 -> sample: [3, 6, 2]
Item: 7 -> sample: [3, 7, 2]
Item: 8 -> sample: [3, 7, 2]
Item: 9 -> sample: [3, 7, 2]
 
Test item frequencies for 100000 runs:
0:30229
1:30182
2:29981
3:30058
4:29749
5:29952
6:30102
7:29955
8:29917
9:29875
</pre>
 
=={{header|Ada}}==
Line 34 ⟶ 95:
Instead of defining a function S_of_N_Creator, we define a generic packgage with that name. The generic parameters are N (=Sample_Size) and the type of the items to be sampled:
 
<langsyntaxhighlight Adalang="ada">generic
Sample_Size: Positive;
type Item_Type is private;
Line 45 ⟶ 106:
function Result return Item_Array;
 
end S_Of_N_Creator;</langsyntaxhighlight>
 
Here is the implementation of that package:
 
<langsyntaxhighlight Adalang="ada">with Ada.Numerics.Float_Random, Ada.Numerics.Discrete_Random;
 
package body S_Of_N_Creator is
Line 86 ⟶ 147:
D_Rnd.Reset(D_Gen); -- at package instantiation, initialize rnd-generators
F_Rnd.Reset(F_Gen);
end S_Of_N_Creator;</langsyntaxhighlight>
 
The main program:
 
<langsyntaxhighlight Adalang="ada">with S_Of_N_Creator, Ada.Text_IO;
 
procedure Test_S_Of_N is
Line 123 ⟶ 184:
& Natural'Image(Result(Dig)) & "; ");
end loop;
end Test_S_Of_N;</langsyntaxhighlight>
 
A sample output:
Line 132 ⟶ 193:
{{works with|BBC BASIC for Windows}}
At each of the 100000 repetitions not only is a new function created but also new copies of its PRIVATE variables '''index%''' and '''samples%()'''. Creating such a large number of variables at run-time impacts adversely on execution speed and isn't to be recommended, other than to meet the artificial requirements of the task.
<langsyntaxhighlight lang="bbcbasic"> HIMEM = PAGE + 20000000
PRINT "Single run samples for n = 3:"
Line 185 ⟶ 246:
a$ += STR$(a%(i%)) + ", "
NEXT
= LEFT$(LEFT$(a$)) + "]"</langsyntaxhighlight>
'''Output:'''
<pre>
Line 215 ⟶ 276:
=={{header|C}}==
Instead of returning a closure we set the environment in a structure:
<langsyntaxhighlight lang="c">#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Line 286 ⟶ 347:
puts("");
return 0;
}</langsyntaxhighlight>
 
Sample output:
Line 293 ⟶ 354:
=={{header|C++}}==
{{works with|C++11}}
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <functional>
#include <vector>
Line 328 ⟶ 389:
std::cout << x << std::endl;
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 344 ⟶ 405:
 
Class-based version:
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <vector>
#include <cstdlib>
Line 381 ⟶ 442:
std::cout << bin[i] << std::endl;
return 0;
}</langsyntaxhighlight>
 
=={{header|Clojure}}==
Line 387 ⟶ 448:
Here the accumulator state is the current sample and the number of items processed.
This function is then used in a ''reduce'' call with an initial state and a list of items.
<langsyntaxhighlight lang="clojure">(defn s-of-n-fn-creator [n]
(fn [[sample iprev] item]
(let [i (inc iprev)]
Line 406 ⟶ 467:
sort
println)
</syntaxhighlight>
</lang>
Sample output:
<syntaxhighlight lang="text">([0 29924] [1 30053] [2 30018] [3 29765] [4 29974] [5 30225] [6 30082] [7 29996] [8 30128] [9 29835])</langsyntaxhighlight>
 
If we really need a stateful (thread safe!) function for some reason, we can get it like this:
<langsyntaxhighlight lang="clojure">(defn s-of-n-creator [n]
(let [state (atom [[] 0])
s-of-n-fn (s-of-n-fn-creator n)]
(fn [item]
(first (swap! state s-of-n-fn item)))))</langsyntaxhighlight>
 
=={{header|CoffeeScript}}==
<langsyntaxhighlight lang="coffeescript">
s_of_n_creator = (n) ->
arr = []
Line 450 ⟶ 511:
for digit in range
console.log digit, counts[digit]
</syntaxhighlight>
</lang>
output
<syntaxhighlight lang="text">
> coffee knuth_sample.coffee
0 29899
Line 464 ⟶ 525:
8 29976
9 30255
</syntaxhighlight>
</lang>
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun s-n-creator (n)
(let ((sample (make-array n :initial-element nil))
(i 0))
Line 493 ⟶ 554:
 
(princ (algorithm-s))
</langsyntaxhighlight>output<syntaxhighlight lang="text">#(30026 30023 29754 30017 30267 29997 29932 29990 29965 30029)</langsyntaxhighlight>
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio, std.random;
 
auto sofN_creator(in int n) {
Line 525 ⟶ 586:
}
writefln("Item counts for %d runs:\n%s", nRuns, bin);
}</langsyntaxhighlight>
{{out}}
<pre>Item counts for 100000 runs:
Line 531 ⟶ 592:
 
===Faster Version===
<langsyntaxhighlight lang="d">import std.stdio, std.random, std.algorithm;
 
struct SOfN(size_t n) {
Line 560 ⟶ 621:
}
writefln("Item counts for %d runs:\n%s", nRuns, bin);
}</langsyntaxhighlight>
 
=={{header|Elena}}==
ELENA 56.0x :
<langsyntaxhighlight lang="elena">import system'dynamic;
import extensions;
import system'routines;
Line 580 ⟶ 641:
eval(i)
{
counter.append:(1);
 
if (__targetweak self.Length < n)
{
__targetweak self.append:(i)
}
else
{
if(randomGenerator.nextInt:(counter) < n)
{ __targetweak self[randomGenerator.nextInt:(n)] := i }
};
 
^ __targetweak self.Value
}
})
Line 600 ⟶ 661:
public program()
{
var bin := Array.allocate(10).populate::(n => new Integer());
for(int trial := 0,; trial < 10000,; trial += 1)
{
var s_of_n := 3.s_of_n();
for(int n := 0,; n < 10,; n += 1)
{
var sample := s_of_n.eval:(n);
if (n == 9)
{ sample.forEach::(i){ bin[i].append:(1) } }
}
};
console.printLine:(bin).readChar()
}</langsyntaxhighlight>
{{out}}
<pre>
3001,3052,3033,2973,2981,3060,3003,2975,2959,2963
3050,3029,3041,2931,3040,2952,2901,2984,3069,3003
</pre>
 
=={{header|Elixir}}==
<langsyntaxhighlight lang="elixir">
defmodule Knuth do
def s_of_n_creator(n), do: {n, 1, []}
Line 648 ⟶ 709:
 
IO.inspect results
</syntaxhighlight>
</lang>
Output:
<pre>%{1 => 30138, 2 => 29980, 3 => 29992, 4 => 29975, 5 => 30110, 6 => 29825,
Line 654 ⟶ 715:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
let N=System.Random 23 //Nigel Galloway: August 7th., 2018
let s_of_n_creator i = fun g->Seq.fold(fun (n:_[]) g->if N.Next()%(g+1)>i-1 then n else n.[N.Next()%i]<-g;n) (Array.ofSeq (Seq.take i g)) (Seq.skip i g)
Line 660 ⟶ 721:
printfn "using an input array -> %A" (List.init 100000 (fun _->s_of_n [|0..9|]) |> Array.concat |> Array.countBy id |> Array.sort)
printfn "using an input list -> %A" (List.init 100000 (fun _->s_of_n [0..9]) |> Array.concat |> Array.countBy id |> Array.sort)
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 668 ⟶ 729:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 705 ⟶ 766:
}
fmt.Println(freq)
}</langsyntaxhighlight>
Output:
<pre>
Line 718 ⟶ 779:
{{libheader|mtl}}
 
<langsyntaxhighlight lang="haskell">
import Control.Monad.Random
import Control.Monad.State
Line 767 ⟶ 828:
counts <- evalRandIO $ foldM (\c _ -> sampleInc 3 c) M.empty [1 .. n]
print (fmap (/ n) counts)
</syntaxhighlight>
</lang>
 
=={{header|Icon}} and {{header|Unicon}}==
Line 778 ⟶ 839:
not a function. In Unicon, the calling syntax for this
co-expression is indistinguishable from that of a function.
<langsyntaxhighlight lang="unicon">import Utils
 
procedure main(A)
Line 801 ⟶ 862:
}
}
end</langsyntaxhighlight>
and a sample run:
<pre>->kas
Line 820 ⟶ 881:
Note that this approach introduces heavy inefficiencies, to achieve information hiding.
 
<langsyntaxhighlight lang="j">s_of_n_creator=: 1 :0
ctx=: conew&'inefficient' m
s_of_n__ctx
Line 844 ⟶ 905:
end.
)
</syntaxhighlight>
</lang>
 
Explanation: <code>create</code> is the constructor for the class named <code>inefficient</code> and it initializes three properties: <code>N</code> (our initial value), <code>ITEMS</code> (an initially empty list) and <code>K</code> (a counter which is initially 0).
Line 854 ⟶ 915:
Required example:
 
<langsyntaxhighlight lang="j">run=:3 :0
nl=. conl 1
s3_of_n=. 3 s_of_n_creator
Line 872 ⟶ 933:
7 36416
8 33172
9 29868</langsyntaxhighlight>
 
Here, we have each of our digits along with how many times each appeared in a result from <code>run</code>.
Line 890 ⟶ 951:
=={{header|Java}}==
A class-based solution:
<langsyntaxhighlight lang="java">import java.util.*;
class SOfN<T> {
Line 924 ⟶ 985:
System.out.println(Arrays.toString(bin));
}
}</langsyntaxhighlight>
 
Sample output:
Line 931 ⟶ 992:
 
Alternative solution without using an explicitly named type; instead using an anonymous class implementing a generic "function" interface:
<langsyntaxhighlight lang="java">import java.util.*;
interface Function<S, T> {
Line 963 ⟶ 1,024:
System.out.println(Arrays.toString(bin));
}
}</langsyntaxhighlight>
 
Sample output:
 
<pre>[29965, 30178, 29956, 29957, 30016, 30114, 29977, 29996, 29982, 29859]</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren]]'''
{{works with|jq}}
 
'''Also works with gojq, the Go implementation of jq'''.
 
jq does not support functions that return functions,
so we adopt the approach taken for example by the [[#C|C]] entry.
Specifically, following the [[#Wren|Wren]] model, the closure variables
are encapsulated in a JSON object of the form {n, s, next, m},
which is initially
<pre>
{n: $n, s: [range(0;$n)|0], next: 0, m: $n}
</pre>
where $n is the maximum sample size.
 
In the following, /dev/random is used as a source of entropy.
In a bash or bash-like environment, a suitable invocation would
be as follows:
<pre>
< /dev/random tr -cd '0-9' | fold -w 1 | jq -Mcnr algorithm-s.jq
</pre>
 
'''algorithm-s.jq'''
<syntaxhighlight lang=jq>
# Output: a PRN in range(0; .)
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;
 
# Input and output: {n, s, next, m}
# The initial input should be
# {n: $n, s: [range(0;$n)|0], next: 0, m: $n}
# where $n is the maximum sample size.
def sOfN(items):
if (.next < .n)
then .s[.next] = items
| .next += 1
else .m += 1
| if ((.m | prn) < .n)
then (.n | prn) as $t
| .s[$t] = items
| if .next <= $t
then .next = $t + 1
else .
end
else .
end
end;
 
def task($iterations):
def dim($n): [range(0;$n)|0];
def init($n): {n: $n, s: dim($n), next: 0, m: $n };
 
reduce range(0; $iterations) as $r ( {freq: dim(10) };
reduce range(48; 57) as $d (. + init(3); sOfN($d) )
| reduce sOfN(57).s[] as $d (.;
.freq[$d - 48] += 1) )
| .freq ;
 
task(1e5)
</syntaxhighlight>
{{output}}
<pre>
[30008,29988,29827,30101,30308,30005,29808,29851,30218,29886]
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">using Printf
 
function makesofn(n::Integer)
Line 997 ⟶ 1,129:
for (i, c) in enumerate(nhist)
@printf("%5d → %5d\n", i-1, c)
end</langsyntaxhighlight>
 
{{out}}
Line 1,015 ⟶ 1,147:
{{trans|Java}}
Class based solution:
<langsyntaxhighlight lang="scala">// version 1.2.51
 
import java.util.Random
Line 1,042 ⟶ 1,174:
}
println(bin.contentToString())
}</langsyntaxhighlight>
Sample output:
<pre>
Line 1,049 ⟶ 1,181:
 
Alternative function based solution:
<langsyntaxhighlight lang="scala">// version 1.2.51
 
import java.util.Random
Line 1,075 ⟶ 1,207:
}
println(bin.contentToString())
}</langsyntaxhighlight>
 
Sample output:
Line 1,081 ⟶ 1,213:
[30172, 29856, 30132, 29884, 29818, 30220, 29900, 30069, 29869, 30080]
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[sofncreator]
sofncreator[n_] := Module[{sample, i},
sample = {};
i = 0;
Return[
Function[{item},
i++;
If[i <= n,
AppendTo[sample, item]
,
If[RandomInteger[{1, i}] <= n,
sample[[RandomInteger[{1, n}]]] = item
]
];
sample
]
]
]
bin = ConstantArray[0, 10];
items = Range[10];
sofn = sofncreator[3];
Do[
sample = sofn[item];
Print[" Item: ", item, " -> sample: " , sample]
,
{item, items}
]
Do[
sofn = sofncreator[3];
Do[
sample = sofn[item]
,
{item, items}
];
Do[
bin[[s]] += 1
,
{s, sample}
]
,
{trial, 100000}
];
{Range[Length[bin]], bin} // Transpose // Grid</syntaxhighlight>
{{out}}
<pre> Item: 1 -> sample: {1}
Item: 2 -> sample: {1,2}
Item: 3 -> sample: {1,2,3}
Item: 4 -> sample: {4,2,3}
Item: 5 -> sample: {5,2,3}
Item: 6 -> sample: {5,6,3}
Item: 7 -> sample: {7,6,3}
Item: 8 -> sample: {7,6,3}
Item: 9 -> sample: {7,6,3}
Item: 10 -> sample: {7,10,3}
 
1 29732
2 30055
3 30059
4 29787
5 30067
6 30123
7 30136
8 30056
9 29949
10 30036</pre>
 
=={{header|Nim}}==
 
<syntaxhighlight lang="nim">import random
 
func sOfNCreator[T](n: Positive): proc(item: T): seq[T] =
var sample = newSeqOfCap[T](n)
var i = 0
 
result = proc(item: T): seq[T] =
inc i
if i <= n:
sample.add(item)
elif rand(1..i) <= n:
sample[rand(n - 1)] = item
sample
 
when isMainModule:
 
randomize()
 
echo "Digits counts for 100_000 runs:"
var hist: array[10, Natural]
for _ in 1..100_000:
let sOfN = sOfNCreator[Natural](3)
for i in 0..8:
discard sOfN(i)
for val in sOfN(9):
inc hist[val]
 
for n, count in hist:
echo n, ": ", count</syntaxhighlight>
 
{{out}}
<pre>Digits counts for 100_000 runs:
0: 30092
1: 29906
2: 29956
3: 29896
4: 30151
5: 30000
6: 30267
7: 29853
8: 30186
9: 29693</pre>
 
=={{header|Objective-C}}==
{{works with|Mac OS X|10.6+}}
Uses blocks
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
 
typedef NSArray *(^SOfN)(id);
Line 1,118 ⟶ 1,362:
}
return 0;
}</langsyntaxhighlight>
 
Log:
Line 1,128 ⟶ 1,372:
=={{header|OCaml}}==
 
<langsyntaxhighlight lang="ocaml">let s_of_n_creator n =
let i = ref 0
and sample = ref [| |] in
Line 1,142 ⟶ 1,386:
 
let () =
Random.self_init ();
let n = 3 in
let num_items = 10 in
let items_set = Array.init num_items (fun i -> i) in
let results = Array.createmake num_items 0 in
for i = 1 to 100_000 do
let res = test n items_set in
Line 1,152 ⟶ 1,396:
done;
Array.iter (Printf.printf " %d") results;
print_newline ()</langsyntaxhighlight>
 
Output:
Line 1,160 ⟶ 1,404:
=={{header|PARI/GP}}==
{{improve|PARI/GP|Does not return a function.}}
<langsyntaxhighlight lang="parigp">KnuthS(v,n)={
my(u=vector(n,i,i));
for(i=n+1,#v,
Line 1,174 ⟶ 1,418:
);
v
};</langsyntaxhighlight>
 
Output:
Line 1,180 ⟶ 1,424:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
 
sub s_of_n_creator {
Line 1,214 ⟶ 1,458:
}
print "@bin\n";
</syntaxhighlight>
</lang>
 
;Sample output:
Line 1,225 ⟶ 1,469:
of course an s_of_n() that operated directly on local vars rather than elements of env, would be faster still.<br>
Not that a mere 100,000 samples takes any method more than a tiny fraction of a second, you understand.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>enum RID, I, SAMPLE
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
<span style="color: #008080;">enum</span> <span style="color: #000000;">RID</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">I</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SAMPLE</span>
function s_of_n(sequence env, integer item)
integer i = env[I] + 1,
<span style="color: #008080;">function</span> <span style="color: #000000;">s_of_n</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">env</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">item</span><span style="color: #0000FF;">)</span>
n = length(env[SAMPLE])
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">env</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;">1</span><span style="color: #0000FF;">,</span>
env[I] = i
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">env</span><span style="color: #0000FF;">[</span><span style="color: #000000;">SAMPLE</span><span style="color: #0000FF;">])</span>
if i<=n then
<span style="color: #000000;">env</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">env</span><span style="color: #0000FF;">)</span>
env[SAMPLE][i] = item
<span style="color: #000000;">env</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;">i</span>
elsif n/i>rnd() then
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">n</span> <span style="color: #008080;">then</span>
env[SAMPLE][rand(n)] = item
<span style="color: #000000;">env</span><span style="color: #0000FF;">[</span><span style="color: #000000;">SAMPLE</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;">item</span>
end if
<span style="color: #008080;">elsif</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()</span> <span style="color: #008080;">then</span>
return env
<span style="color: #000000;">env</span><span style="color: #0000FF;">[</span><span style="color: #000000;">SAMPLE</span><span style="color: #0000FF;">][</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">item</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #008080;">return</span> <span style="color: #000000;">env</span>
function s_of_n_creator(int n)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
return {routine_id("s_of_n"),0,repeat(0,n)}
end function
<span style="color: #008080;">function</span> <span style="color: #000000;">s_of_n_creator</span><span style="color: #0000FF;">(</span><span style="color: #004080;">int</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
 
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">s_of_n</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;">n</span><span style="color: #0000FF;">)}</span>
function invoke(sequence env, args)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
env = call_func(env[RID],prepend(args,env))
return env
<span style="color: #008080;">function</span> <span style="color: #000000;">invoke</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">env</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">args</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #000000;">env</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">call_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">env</span><span style="color: #0000FF;">[</span><span style="color: #000000;">RID</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">prepend</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">args</span><span style="color: #0000FF;">),</span><span style="color: #000000;">env</span><span style="color: #0000FF;">))</span>
 
<span style="color: #008080;">return</span> <span style="color: #000000;">env</span>
function test(integer n, sequence items)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence env = s_of_n_creator(n)
for i=1 to length(items) do
<span style="color: #008080;">function</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">items</span><span style="color: #0000FF;">)</span>
-- env = s_of_n(env,items[i])
<span style="color: #004080;">sequence</span> <span style="color: #000000;">env</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s_of_n_creator</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
env = invoke(env, {items[i]})
<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: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">items</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000080;font-style:italic;">-- env = s_of_n(env,items[i])</span>
return env[SAMPLE]
<span style="color: #000000;">env</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">invoke</span><span style="color: #0000FF;">(</span><span style="color: #000000;">env</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">items</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]})</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">env</span><span style="color: #0000FF;">[</span><span style="color: #000000;">SAMPLE</span><span style="color: #0000FF;">]</span>
procedure main()
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence items_set = tagset(9,0)
sequence frequencies = repeat(0,length(items_set))
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
for i=1 to 100000 do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">items_set</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
sequence res = test(3, items_set)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">frequencies</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: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">items_set</span><span style="color: #0000FF;">))</span>
for j=1 to length(res) do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">100000</span> <span style="color: #008080;">do</span>
frequencies[res[j]+1] += 1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">items_set</span><span style="color: #0000FF;">)</span>
end for
<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;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">integer</span> <span style="color: #000000;">fdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
?frequencies
<span style="color: #000000;">frequencies</span><span style="color: #0000FF;">[</span><span style="color: #000000;">fdx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
main()</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">frequencies</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,274 ⟶ 1,523:
</pre>
Note that s_of_n_creator() must match {RID, I, SAMPLE}. You might instead prefer (taking the appropriate care not to miss any!):
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>enum RID, I, SAMPLE, CLOSURE_LEN=$
<span style="color: #008080;">enum</span> <span style="color: #000000;">RID</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">I</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SAMPLE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CLOSURE_LEN</span><span style="color: #0000FF;">=$</span>
...
<span style="color: #0000FF;">...</span>
function s_of_n_creator(int n)
<span style="color: #008080;">function</span> <span style="color: #000000;">s_of_n_creator</span><span style="color: #0000FF;">(</span><span style="color: #004080;">int</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
sequence closure = repeat(0,CLOSURE_LEN)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">closure</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;">CLOSURE_LEN</span><span style="color: #0000FF;">)</span>
closure[RID] = routine_id("s_of_n")
<span style="color: #000000;">closure</span><span style="color: #0000FF;">[</span><span style="color: #000000;">RID</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"s_of_n"</span><span style="color: #0000FF;">)</span>
closure[I] = 0
<span style="color: #000000;">closure</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;">0</span>
closure[SAMPLE] = repeat(0,n)
<span style="color: #000000;">closure</span><span style="color: #0000FF;">[</span><span style="color: #000000;">SAMPLE</span><span style="color: #0000FF;">]</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;">n</span><span style="color: #0000FF;">)</span>
return closure
<span style="color: #008080;">return</span> <span style="color: #000000;">closure</span>
end function</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<!--</syntaxhighlight>-->
 
=={{header|PHP}}==
{{works with|PHP|5.3+}}
<langsyntaxhighlight lang="php"><?php
function s_of_n_creator($n) {
$sample = array();
Line 1,313 ⟶ 1,564:
}
print_r($bin);
?></langsyntaxhighlight>
 
;Sample output:
Line 1,331 ⟶ 1,582:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de s_of_n_creator (@N)
(curry (@N (I . 0) (Res)) (Item)
(cond
Line 1,343 ⟶ 1,594:
(for I (mapc S_of_n (0 1 2 3 4 5 6 7 8 9))
(inc (nth Freq (inc I))) ) ) )
Freq )</langsyntaxhighlight>
Output:
<pre>-> (30003 29941 29918 30255 29848 29875 30056 29839 30174 30091)</pre>
Line 1,349 ⟶ 1,600:
=={{header|Python}}==
{{works with|Python|3.x}}
<langsyntaxhighlight lang="python">from random import randrange
 
def s_of_n_creator(n):
Line 1,382 ⟶ 1,633:
bin[s] += 1
print("\nTest item frequencies for 100000 runs:\n ",
'\n '.join("%i:%i" % x for x in enumerate(bin)))</langsyntaxhighlight>
 
;Sample output:
Line 1,411 ⟶ 1,662:
===Python Class based version===
Only a slight change creates the following class-based implementation:
<langsyntaxhighlight lang="python">class S_of_n_creator():
def __init__(self, n):
self.n = n
Line 1,426 ⟶ 1,677:
# Keep item
sample[randrange(n)] = item
return sample</langsyntaxhighlight>
The above can be instantiated as follows after which <code>s_of_n</code> can be called in the same way as it is in the first example where it is a function instead of an instance.
<langsyntaxhighlight lang="python">s_of_n = S_of_n_creator(3)</langsyntaxhighlight>
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket/base
 
(define (s-of-n-creator n)
Line 1,451 ⟶ 1,702:
(for ([d sample]) (vector-set! counts d (add1 (vector-ref counts d)))))
 
(for ([d 10]) (printf "~a ~a\n" d (vector-ref counts d)))</langsyntaxhighlight>
Output:
<pre>0 30117
Line 1,466 ⟶ 1,717:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line>sub s_of_n_creator($n) {
my (@sample, $i);
my $i = 0;
-> $item {
if ++$i <= $n { @sample.push: $item }
elsif $i.rand < push$n { @sample,[$n.rand] = $item; }
}@sample
elsif $i.rand < $n {
@sample[$n.rand] = $item;
}
@sample;
}
}
 
my @items = 0..9;
my @bin;
 
for ^100000 {
my &s_of_n = s_of_n_creator( 3);
mysink @sample.&s_of_n for ^9;
for @itemsbin[$_]++ ->for $items_of_n {9;
@sample = s_of_n($item);
}
for @sample -> $s {
@bin[$s]++;
}
}
 
say @bin;</lang>
say @bin;</syntaxhighlight>
Output:
<pre>29975 30028 30246 30056 30004 29983 29836 29967 29924 29981</pre>
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program using Knuth's algorithm S (a random sampling N of M items). */
parse arg trials size . /*obtain optional arguments from the CL*/
if trials=='' | trials=="," then trials= 100000 /*Not specified? Then use the default.*/
Line 1,533 ⟶ 1,773:
!.k= random(0, 9) /*set the Kth item with random digit.*/
end /*k*/
return /*the piddly stuff is done (for now). */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input of: &nbsp; &nbsp; <tt> 100000 &nbsp; 2 </tt>}}
<pre>
Line 1,548 ⟶ 1,788:
frequency of the 8 digit is: 29,976
frequency of the 9 digit is: 29,871
</pre>
 
=={{header|RPL}}==
This is an idiomatic adaptation of the algorithm: SCREA initializes 2 persistent variables: S contains the sample and SPAR the algorithm parameters (n and i)
{{works with|RPL|HP49-C}}
« 0 2 →LIST '<span style="color:green">SPAR</span>' STO { } '<span style="color:green">S</span>' STO
» '<span style="color:blue">SCREA</span>' STO
« <span style="color:green">SPAR</span> EVAL
'''CASE'''
DUP2 > '''THEN''' DROP2 '<span style="color:green">S</span>' STO+ '''END'''
/ →NUM RAND ≥ '''THEN''' <span style="color:green">S</span> DUP SIZE RAND * CEIL ROT PUT '<span style="color:green">S</span>' STO '''END'''
DROP '''END'''
'<span style="color:green">SPAR</span>' 2 DUP2 GET 1 + PUT <span style="color:green">S</span>
» '<span style="color:blue">SOFN</span>' STO
« { } → sample
« { 10 } 0 CON
1 1000 '''START'''
3 <span style="color:blue">SCREA</span>
0
0 9 '''FOR''' k
DROP k <span style="color:blue">SOFN</span>
'''NEXT'''
'sample' STO
« sample k POS » 'k' 0 9 1 SEQ
NOT NOT AXL +
'''NEXT'''
» » '<span style="color:blue">TASK</span>' STO
{{out}}
<pre>
1: [ 206. 218. 235. 309. 359. 329. 327. 324. 359. 334. ]
</pre>
 
=={{header|Ruby}}==
Using a closure
<langsyntaxhighlight lang="ruby">def s_of_n_creator(n)
sample = []
i = 0
Line 1,574 ⟶ 1,846:
end
 
(0..9).each {|digit| puts "#{digit}\t#{frequency[digit]}"}</langsyntaxhighlight>
Example
<pre>0 29850
Line 1,591 ⟶ 1,863:
{{libheader|rand 0.3}}
 
<langsyntaxhighlight lang="rust">use rand::{Rng,weak_rng};
 
struct SofN<R: Rng+Sized, T> {
Line 1,636 ⟶ 1,908:
println!("frequency of {}: {}", i, x);
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,655 ⟶ 1,927:
===Imperative (Ugly and side effects)===
{{trans|Java}}
<langsyntaxhighlight Scalalang="scala">import java.util
import scala.util.Random
 
Line 1,675 ⟶ 1,947:
 
println(bin.mkString("[", ", ", "]"))
}</langsyntaxhighlight>
{{Out}}See it running in your browser by [https://scalafiddle.io/sf/nlldfXD/0 ScalaFiddle (JavaScript, non JVM)] or by [https://scastie.scala-lang.org/WLaee5H9T72cximqK9gECA Scastie (JVM)].
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">func s_of_n_creator(n) {
var i = 0
var sample = []
Line 1,708 ⟶ 1,980:
}
 
say bin;</langsyntaxhighlight>
{{out}}
<pre>
Line 1,715 ⟶ 1,987:
 
=={{header|Swift}}==
<langsyntaxhighlight lang="swift">import Darwin
 
func s_of_n_creator<T>(n: Int) -> T -> [T] {
Line 1,742 ⟶ 2,014:
}
}
println(bin)</langsyntaxhighlight>
{{out}}
<pre>
Line 1,749 ⟶ 2,021:
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
 
oo::class create SofN {
Line 1,777 ⟶ 2,049:
}
}
parray freq</langsyntaxhighlight>
Sample output:<pre>
freq(0) = 29812
Line 1,789 ⟶ 2,061:
freq(8) = 30060
freq(9) = 29824
</pre>
 
=={{header|V (Vlang)}}==
{{trans|go}}
<syntaxhighlight lang="v (vlang)">import rand
import rand.seed
fn s_of_ncreator(n int) fn(u8) []u8 {
mut s := []u8{len: 0, cap:n}
mut m := n
return fn[mut s, mut m, n](item u8) []u8 {
if s.len < n {
s << item
} else {
m++
if rand.intn(m) or {0} < n {
s[rand.intn(n) or {0}] = item
}
}
return s
}
}
fn main() {
rand.seed(seed.time_seed_array(2))
mut freq := [10]int{}
for _ in 0..int(1e5) {
s_of_n := s_of_ncreator(3)
for d := '0'[0]; d < '9'[0]; d++ {
s_of_n(d)
}
for d in s_of_n('9'[0]) {
freq[d-'0'[0]]++
}
}
println(freq)
}</syntaxhighlight>
Output:
<pre>
[30131, 30045, 29880, 30178, 29745, 29890, 30150, 30014, 30068, 29899]
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang="wren">import "random" for Random
 
var r = Random.new()
 
var sOfNCreator = Fn.new { |n|
var s = List.filled(n, 0)
var next = 0
var m = n
return Fn.new { |item|
if (next < n) {
s[next] = item
next = next + 1
} else {
m = m + 1
if (r.int(m) < n) {
var t = r.int(n)
s[t] = item
if (next <= t) next = t + 1
}
}
return s
}
}
 
var freq = List.filled(10, 0)
for (r in 0...1e5) {
var sOfN = sOfNCreator.call(3)
for (d in 48...57) sOfN.call(d)
for (d in sOfN.call(57)) {
freq[d - 48] = freq[d - 48] + 1
}
}
System.print(freq)</syntaxhighlight>
 
{{out}}
Sample run:
<pre>
[29842, 30051, 29878, 30178, 29731, 30089, 30070, 29939, 30058, 30164]
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn s_of_n_creator(n){
fcn(item,ri,N,samples){
i:=ri.inc(); // 1,2,3,4,...
Line 1,799 ⟶ 2,152:
samples
}.fp1(Ref(1),n,L())
}</langsyntaxhighlight>
One run:
<langsyntaxhighlight lang="zkl">s3:=s_of_n_creator(3);
[0..9].pump(List,s3,"copy").println();</langsyntaxhighlight>
{{out}}
<pre>
Line 1,808 ⟶ 2,161:
</pre>
100,000 runs:
<langsyntaxhighlight lang="zkl">dist:=L(0,0,0,0,0,0,0,0,0,0);
do(0d100_000){
(0).pump(10,Void,s_of_n_creator(3)).apply2('wrap(n){dist[n]=dist[n]+1})
}
N:=dist.sum();
dist.apply('wrap(n){"%.2f%%".fmt(n.toFloat()/N*100)}).println();</langsyntaxhighlight>
{{out}}
<pre>L("10.00%","9.98%","10.00%","9.99%","10.00%","9.98%","10.01%","10.04%","9.98%","10.02%")</pre>
1,150

edits