2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,2 +1,45 @@
Implement the [[wp:Knuth shuffle|Knuth shuffle]] (a.k.a. the Fisher-Yates shuffle) for an integer array (or, if possible, an array of any type).
The Knuth shuffle is used to create a random permutation of an array.
The   [[wp:Knuth shuffle|Knuth shuffle]]   (a.k.a. the Fisher-Yates shuffle)   is an algorithm for randomly shuffling the elements of an array.
{{task heading}}
Implement the Knuth shuffle for an integer array (or, if possible, an array of any type).
{{task heading|Specification}}
Given an array '''''items''''' with indices ranging from ''0'' to '''''last''''', the algorithm can be defined as follows (pseudo-code):
'''for''' ''i'' '''from''' ''last'' '''downto''' 1 '''do''':
'''let''' ''j'' = random integer in range ''0'' <math>\leq</math> ''j'' <math>\leq</math> ''i''
'''swap''' ''items''[''i''] '''with''' ''items''[''j'']
Notes:
* It modifies the input array in-place. If that is unreasonable in your programming language, you may amend the algorithm to return the shuffled items as a new array instead.
* The algorithm can also be amended to iterate from left to right, if that is more convenient.
{{task heading|Test cases}}
{| class="wikitable"
|-
! Input array
! Possible output arrays
|-
| <tt>[]</tt>
| <tt>[]</tt>
|-
| <tt>[10]</tt>
| <tt>[10]</tt>
|-
| <tt>[10, 20]</tt>
| <tt>[10, 20]</tt><br><tt>[20, 10]</tt>
|-
| <tt>[10, 20, 30]</tt>
| <tt>[10, 20, 30]</tt><br><tt>[10, 30, 20]</tt><br><tt>[20, 10, 30]</tt><br><tt>[20, 30, 10]</tt><br><tt>[30, 10, 20]</tt><br><tt>[30, 20, 10]</tt>
|}
(These are listed here just for your convenience; no need to demonstrate them on the page.)
{{task heading|Related tasks}}
* [[Sattolo cycle]]
<hr>

View file

@ -0,0 +1,73 @@
-- knuthShuffle :: [a] -> [a]
on knuthShuffle(lst)
-- randomSwap :: [Int] -> Int -> [Int]
script randomSwap
on lambda(a, i)
if i > 1 then
set iRand to random number from 1 to i
tell a
set tmp to item iRand
set item iRand to item i
set item i to tmp
it
end tell
else
a
end if
end lambda
end script
foldr(randomSwap, lst, range(1, length of lst))
end knuthShuffle
-- TEST
on run
knuthShuffle(["alpha", "beta", "gamma", "delta", "epsilon", ¬
"zeta", "eta", "theta", "iota", "kappa", "lambda", "mu"])
end run
-- GENERIC LIBRARY FUNCTIONS
-- foldr :: (a -> b -> a) -> a -> [b] -> a
on foldr(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from lng to 1 by -1
set v to lambda(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldr
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property lambda : f
end script
end if
end mReturn
-- range :: Int -> Int -> [Int]
on range(m, n)
if n < m then
set d to -1
else
set d to 1
end if
set lst to {}
repeat with i from m to n by d
set end of lst to i
end repeat
return lst
end range

View file

@ -0,0 +1,2 @@
{"mu", "theta", "alpha", "delta", "zeta", "gamma",
"iota", "kappa", "lambda", "epsilon", "beta", "eta"}

View file

@ -0,0 +1,29 @@
#import system.
#import system'routines.
#import extensions.
#symbol(const)MAX = 10.
#class(extension) randomOp
{
#method randomize
[
#var max := self length.
0 till:max &doEach: i
[
#var j := randomGenerator eval:i:max.
self exchange:i:j.
].
^ self.
]
}
#symbol program =
[
#var a := Array new:MAX set &every:(&index:i) [ i ].
console writeLine:(a randomize).
].

View file

@ -6,18 +6,17 @@ defmodule Knuth do
end
defp random_move( n, {inputs, acc} ) do
item = Enum.at( inputs, :random.uniform(n)-1 )
item = Enum.at( inputs, :rand.uniform(n)-1 )
{List.delete( inputs, item ), [item | acc]}
end
end
:random.seed( :os.timestamp )
seq = Enum.to_list( 0..19 )
IO.inspect Knuth.shuffle( seq )
seq = [1,2,3]
Enum.reduce(1..100000, Map.new, fn _,acc ->
k = Knuth.shuffle(seq)
Dict.update(acc, k, 1, &(&1+1))
Map.update(acc, k, 1, &(&1+1))
end)
|> Enum.each(fn {k,v} -> IO.inspect {k,v} end)

View file

@ -0,0 +1,38 @@
(lst => {
// knuthShuffle :: [a] -> [a]
let knuthShuffle = lst =>
range(0, lst.length - 1)
.reduceRight((a, i) => {
let iRand = i ? randomInteger(0, i) : 0,
tmp = a[iRand];
return iRand !== i ? (
a[iRand] = a[i],
a[i] = tmp,
a
) : a;
}, lst),
// randomInteger :: Int -> Int -> Int
randomInteger = (low, high) =>
low + Math.floor(
(Math.random() * ((high - low) + 1))
),
// range :: Int -> Int -> Maybe Int -> [Int]
range = (m, n, step) => {
let d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
};
return knuthShuffle(lst);
})(
'alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu'
.split(' ')
);

View file

@ -0,0 +1,2 @@
["iota", "epsilon", "kappa", "theta", "gamma", "delta",
"lambda", "eta", "zeta", "beta", "mu", "alpha"]

View file

@ -0,0 +1,56 @@
(lst => {
// knuthShuffle :: [a] -> [a]
function knuthShuffle(lst) {
let lng = lst.length;
return lng ? range(0, lng - 1)
.reduceRight((a, i) => {
let iRand = i > 0 ? randomInteger(0, i) : 0;
return i !== iRand ? swapped(a, i, iRand) : a;
}, lst) : [];
};
// A non-mutating variant of swapped():
// swapped :: [a] -> Int -> Int -> [a]
let swapped = (lst, iFrom, iTo) => {
let [iLow, iHigh] = iTo > iFrom ? (
[iFrom, iTo]
) : [iTo, iFrom];
return iLow !== iHigh ? (
[].concat(
(iLow > 0 ? lst.slice(0, iLow) : []), // pre
lst[iHigh], // DOWN
lst.slice(iLow + 1, iHigh), // mid
lst[iLow], // UP
lst.slice(iHigh + 1) // post
)
) : lst.slice(0) // (unchanged copy)
},
// randomInteger :: Int -> Int -> Int
randomInteger = (low, high) =>
low + Math.floor(
(Math.random() * ((high - low) + 1))
),
// range :: Int -> Int -> Maybe Int -> [Int]
range = (m, n, step) => {
let d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
};
return knuthShuffle(lst);
})(
'alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu'
.split(' ')
);

View file

@ -0,0 +1,2 @@
["mu", "theta", "beta", "eta", "delta", "epsilon",
"kappa", "alpha", "gamma", "lambda", "zeta", "iota"]

View file

@ -0,0 +1,31 @@
object Knuth {
internal val gen = java.util.Random()
}
fun <T> Array<T>.shuffle(): Array<T> {
val a = clone()
var n = a.size
while (n > 1) {
val k = Knuth.gen.nextInt(n--)
val t = a[n]
a[n] = a[k]
a[k] = t
}
return a
}
fun main(args: Array<String>) {
val str = "abcdefghijklmnopqrstuvwxyz".toCharArray()
(1..10).forEach {
val s = str.toTypedArray().shuffle().toCharArray()
println(s)
require(s.toSortedSet() == str.toSortedSet())
}
val ia = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
(1..10).forEach {
val s = ia.shuffle()
println(s.distinct())
require(s.toSortedSet() == ia.toSet())
}
}

View file

@ -1,13 +1,12 @@
function table.shuffle(t)
local n = #t
while n > 1 do
for n = #t, 1, -1 do
local k = math.random(n)
t[n], t[k] = t[k], t[n]
n = n - 1
end
return t
end
math.randomseed( os.time() )
a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
table.shuffle(a)

View file

@ -1,33 +1,52 @@
program Knuth;
const
max = 10;
startIdx = -5;
max = 11;
type
list = array [1..max] of integer;
tmyData = string[9];
tmylist = array [startIdx..startIdx+max-1] of tmyData;
procedure shuffle(var a: list);
procedure InitList(var a: tmylist);
var
i,k,tmp: integer;
i: integer;
Begin
for i := Low(a) to High(a) do
str(i:3,a[i])
end;
procedure shuffleList(var a: tmylist);
var
i,k : integer;
tmp: tmyData;
begin
randomize;
for i := max downto 2 do begin
k := random(i) + 1;
if (a[i] <> a[k]) then begin
tmp := a[i]; a[i] := a[k]; a[k] := tmp
end
for i := High(a)-low(a) downto 1 do begin
k := random(i+1) + low(a);
tmp := a[i+low(a)]; a[i+low(a)] := a[k]; a[k] := tmp
end
end;
procedure DisplayList(const a: tmylist);
var
i : integer;
Begin
for i := Low(a) to High(a) do
write(a[i]);
writeln
end;
{ Test and display }
var
a: list;
a: tmylist;
i: integer;
begin
for i := 1 to max do
a[i] := i;
shuffle(a);
for i := 1 to max do
write(a[i], ' ');
writeln
randomize;
InitList(a);
DisplayList(a);
writeln;
For i := 0 to 4 do
Begin
shuffleList(a);
DisplayList(a);
end;
end.

View file

@ -1,23 +1,23 @@
/*REXX program shuffles a deck of playing cards using the Knuth shuffle.*/
rank='A 2 3 4 5 6 7 8 9 10 J Q K' /*pips of the playing cards. */
suit='' /*suit " " " " */
parse arg seed .; if seed\=='' then call random ,,seed /*repeatability?*/
say ' getting a new deck out of the box ···'
deck.1='highJoker' /*good decks have a color joker, */
deck.2='lowJoker' /*··· and a black & white joker. */
cards=2 /*now, two cards are in the deck.*/
/*REXX program shuffles a deck of playing cards (with jokers) using the Knuth shuffle.*/
rank= 'A 2 3 4 5 6 7 8 9 10 J Q K' /*pips of the various playing cards. */
suit= '' /*suit " " " " " */
parse arg seed . /*obtain optional argument from the CL.*/
if datatype(seed,'W') then call random ,,seed /*maybe use for RANDOM repeatability.*/
say ' getting a new deck out of the box ···'
@.1= 'highJoker' /*good decks have a color joker, and a */
@.2= 'lowJoker' /* ··· black & white joker. */
cards=2 /*now, there're 2 cards are in the deck*/
do j =1 for length(suit)
do k=1 for words(rank); cards=cards+1
deck.cards=substr(suit,j,1)word(rank,k)
do k=1 for words(rank); cards=cards + 1
@.cards=substr(suit, j, 1)word(rank, k)
end /*k*/
end /*j*/
call showDeck
say ' shuffling' cards "cards ···"
do s=cards by -1 to 2; rand=random(1,s)
parse value deck.rand deck.s with deck.s deck.rand
/* [↑] swap two cards in the deck*/
call show
say; say ' shuffling' cards "cards ···"
do s=cards by -1 to 2; ?=random(1,s); parse value @.? @.s with @.s @.?
/* [↑] swap two cards in the deck. */
end /*s*/
call showDeck
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────SHOWDECK subroutine─────────────────*/
showDeck: _=; do m=1 for cards; _=_ deck.m; end /*m*/; say _; say; return
call show
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: _=; do m=1 for cards; _=_ @.m; end /*m*/; say _; return

View file

@ -1,30 +1,27 @@
/*REXX program shuffles a deck of playing cards using the Knuth shuffle.*/
rank = 'ace deuce trey 4 5 6 7 8 9 10 jack queen king' /*use pip names.*/
suit = 'club spade diamond heart' /* " suit " */
say ' getting a new deck out of the box ···'
deck.1 = ' color joker' /*good decks have a color joker, */
deck.2 = ' b&w joker' /*··· and a black & white joker. */
cards=2 /*now, two cards are in the deck.*/
/*REXX program shuffles a deck of playing cards (with jokers) using the Knuth shuffle.*/
rank = 'ace deuce trey 4 5 6 7 8 9 10 jack queen king' /*use pip names for cards*/
suit = 'club spade diamond heart' /* " suit " " " */
say ' getting a new deck out of the box ···'
@.1= ' color joker' /*good decks have a color joker, and a */
@.2= ' b&w joker' /* ··· black & white joker. */
cards=2 /*now, there're 2 cards are in the deck*/
do j =1 for words(suit)
do k=1 for words(rank); cards=cards+1 /*bump counter.*/
deck.cards=right(word(suit,j),7) word(rank,k) /*assign.*/
do k=1 for words(rank); cards=cards+1 /*bump the card counter. */
@.cards=right(word(suit,j),7) word(rank,k) /*assign a card name. */
end /*k*/
end /*j*/
call showDeck 'ace' /*inserts blank when ACE is found*/
say ' shuffling' cards "cards ···"
call show 'ace' /*inserts blank when an ACE is found.*/
say; say ' shuffling' cards "cards ···"
do s=cards by -1 to 2; rand=random(1,s) /*get random number for swap*/
_=deck.rand; deck.rand=deck.s; deck.s=_ /*swap 2 cards in card deck.*/
end /*s*/
call showDeck
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────SHOWDECK subroutine─────────────────*/
showDeck: parse arg break; say /*get sep card, shows blank line*/
do m=1 for cards /*traipse through the deck. */
if pos(break,deck.m)\==0 then say /*a blank: easier to read cards.*/
say 'card' right(m,2) '' deck.m /*display a particular card. */
end /*m*/
say /*show a trailing blank line. */
do s=cards by -1 to 2; ?=random(1,s); _=@.?; @.?=@.s; @.s=_
end /*s*/ /* [↑] swap two cards in the deck. */
call show
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
show: parse arg break; say /*get separator card, show blank line. */
do m=1 for cards /* [↓] traipse through the card deck. */
if pos(break,@.m)\==0 then say /*show a blank to read cards easier. */
say 'card' right(m, 2) '' @.m /*display a particular card from deck. */
end /*m*/
return