language-Modula2-0.1: examples/Modula-2_Libraries/andrea-m2/lib/generic/shuffle.mod
IMPLEMENTATION MODULE Shuffle;
(* See the definition module for details *)
(* V1.1, John Andrea, Jun.22/93 -add Copy and Duplicate *)
(* V1.0, John Andrea, Apr.5/92 *)
(* This code may be freely used and distributed, it may not be sold *)
IMPORT LargeSets;
FROM Storage IMPORT ALLOCATE;
FROM Randomly IMPORT Choose_1_To_N;
TYPE
Deck = POINTER TO RECORD
min, max :CARDINAL;
size :CARDINAL;
n_left :CARDINAL;
set :LargeSets.LargeSet;
END;
(* ------------------------------------------- *)
PROCEDURE Create( VAR d :Deck; min, max :CARDINAL );
VAR
i :CARDINAL;
BEGIN
NEW( d );
IF min > max THEN
i := min;
min := max;
max := i;
END;
d^.min := min;
d^.max := max;
d^.size := max - min + 1;
LargeSets.Build( d^.set, min, max );
Reset( d );
END Create;
(* ------------------------------------------- *)
PROCEDURE Reset( d :Deck );
BEGIN
d^.n_left := d^.size;
LargeSets.Fill( d^.set );
END Reset;
(* ------------------------------------------- *)
PROCEDURE Next( d :Deck ) :CARDINAL;
VAR
i, n, count :CARDINAL;
BEGIN
IF d^.n_left = 0 THEN Reset( d ); END;
n := Choose_1_To_N( d^.n_left );
(* find the n'th non-zero number in the list *)
i := d^.min;
count := 0;
WHILE count # n DO
IF LargeSets.In( d^.set, i ) THEN count := count + 1 END;
i := i + 1;
END;
i := i - 1;
LargeSets.Excl( d^.set, i ); (* make this number un-available *)
d^.n_left := d^.n_left - 1; (* now the list is smaller by one *)
RETURN i;
END Next;
(* ------------------------------------------- *)
PROCEDURE Copy( d, e :Deck );
BEGIN
IF ( d^.min = e^.min ) & ( d^.max = e^.max ) THEN
LargeSets.Copy( d^.set, e^.set );
e^.n_left := d^.n_left;
END;
END Copy;
(* ------------------------------------------- *)
PROCEDURE Duplicate( d :Deck; VAR e :Deck );
BEGIN
Create( e, d^.min, d^.max );
Copy( d, e );
END Duplicate;
BEGIN
END Shuffle.