Last changed 9 September 2010
Finnish lottery: pick 7 numbers out of 37.
See also Raiding the Lost Average.
It’s a bit silly to write this task in AWK. The whole body of a normal
AWK program is left empty and only the “BEGIN” and
“END” sections, intended for pre- and postformatting
respectively, remain. But it works―as soon as you give the end-of-file
character from the keyboard
# Drawing the lottery line in AWK
BEGIN {
while (chosen < 7) {
lot = int(rand() * 37) + 1
if (!lottery[lot]) {
lottery[lot] = 1
chosen ++
}
}
}
END {
for (i in lottery)
print i " "
print "\n"
}
This solution is in very primitive BASIC just to give the feel of the language as it once was. Those days are far gone―and we are no poorer for that!
First define a table of 37 cells; this automatically sets the value of the cells to 0. Next we get a random number. If the cell in the table whose index is this number is still 0, the number can be used; otherwise we try another number. When 7 numbers are chosen, we can print the results and quit.
100 REM Drawing the lottery line in BASIC 110 REM 120 DIM L(37) 130 A=INT(RND(1)*37)+1 140 IF L(A)=1 THEN GOTO 130 150 L(A)=1 160 N=N+1 170 IF N<7 THEN GOTO 130 180 FOR I=1 TO 37 190 IF L(I)=1 THEN PRINT I; 200 NEXT I 210 PRINT 220 END
Follows the lines of the BASIC example above; the control structures are just a bit more advanced.
/* Drawing the lottery line in C */
#include <stdio.h>
#include <stdlib.h>
#define RAND_MAX 36
void main(void)
{
char lottery[37];
int lot, chosen = 0, i;
while (chosen < 7) {
lot = rand();
if (!lottery[lot]) {
lottery[lot] = 1;
chosen ++;
}
}
for (i = 0; i < 37; i ++) {
if (lottery[i])
printf("%n ", i + 1);
printf("\n");
}
}
No object-orientedness here: follows the C solution closely but utilises the new features of C++ (as compared to C).
/* Drawing the lottery line in C++ */
#include <iostream.h>
void main(void) {
while (chosen < 7) {
lot = rand();
if (!lottery[lot]) {
lottery[lot] = 1;
chosen ++;
}
}
for (int i = 0; i < 37; i ++) {
if (lottery[i])
cout << i;
cout << endl;
}
}
These examples are intended to illustrate the peculiarities―and the power!―of Icon.
In the first example we first create a list of 37
elements. Then we set the elements to consecutive numerical values
from 1 to 37. Next, we randomize the whole list. Note some operators:
the asterisk “*” returns the length of a list; the
exclamation mark “!” returns the elements from the
list one by one (or generates the list); the question mark
“?” returns a random element. Icon also allows reversal
assignment (e.g., “a :=: b” swaps the values of
the variables). Finally, we just print out the first seven numbers of
the now randomized list.
# Drawing the lottery line in Icon
link random
procedure main()
randomize()
lottery := list(37)
every !lottery := 1 to 37
every i := *lottery to 2 by -1 do
lottery[?i] :=: lottery[i]
every write(lottery[1 to 7])
end
Our second example uses sets, one of the sequential data types in Icon: it is like a list but the elements are unique. In a way this approximates the working of a real lottery machine
# Drawing the lottery line in Icon
link random
procedure main()
randomize()
lottery := set(1 to 37)
chosen := set()
every i := 1 to 7 do {
lot := ?lottery
insert(chosen, lot)
delete(lottery, lot)
}
every i := !chosen do write(i)
end
Here each chosen number goes to a list. When drawing the lots again, we just test whether the number already is a member of the list.
; Drawing the lottery line in Lisp
(defun lottery ()
(do ((chosen nil)) ((= (length chosen) 7))
(setq lot (random 37))
(if (not (member lot chosen)) (push lot chosen))))
This piece of code follows the “BASIC strategy”.
{ Drawing the lottery line in Pascal }
program DrawLottery;
var
lottery : array[1..37] of boolean;
lot, chosen, i : integer;
begin
randomize;
chosen := 0;
for i := 1 to 37 do
lottery[i] := false;
while chosen <= 7 do begin
lot := random(38) + 1;
if lottery[lot] = false then begin
lottery[lot] := true;
chosen := chosen + 1
end
end;
for i := 1 to 37 do begin
if lottery[i] = true then write(i : 3)
end;
writeln
end.
Though Perl has lists like Lisp and Python, there
seems to be no easy way of checking the existence of an element in the
list (Lisp has the “member” function, Python the
“in” operator); so this sample uses the same strategy
as the BASIC sample above.
The syntactic tricks in this sample are partly
intentional. For instance, there is no need for the
“if” and “unless” clauses to be
tailing the statements they control, and more often than not it would
be best if they didn’t, but used that way you save an extra brace
pair.
# Drawing the lottery line in Perl
while ($chosen < 7) {
$lot = int(rand(36)) + 1;
$lottery[$lot] = 1, $chosen ++ unless ($lottery[$lot]);
}
for ($i = 1; $i < 37; $i ++) {
print $i + 1 . " " if ($lottery[$i]);
}
print "\n";
Since Python implemented sets, this exercise became a lot easier: there’s no need to check whether a drawn lottery number is already used, since elements in sets are unique.
# Drawing the lottery line in Python
import random
chosen = set()
while len(chosen) < 7:
chosen.add(random.randint(1, 37))
print(', '.join(str(num) for num in chosen.sorted()))
Standard REXX does not have tables. The so-called “stem
variables” can sometimes do the trick, as in here, but beware! Even
though “lottery.1” is pretty much equivalent to
“lottery[1]” in some other programming languages (as in
Pascal or C), in REXX it is no error for the “index” (it is not really
an index in REXX) to be an arbitrary name―such as an erroneously
uninitialized variable.
/* Drawing the lottery line in REXX */
chosen = 0
lottery. = 0
do until chosen = 7
lot = random(36) + 1
if lottery.lot = 0 then do
lottery.lot = 1
chosen = chosen + 1
end
end
do i = 1 to 37
if lottery.i = 1 then
say i
end
Tcl is a silly language. You can do almost anything with it, but for a non-adherent it sure requires some keen studying with the manual. Shell-like syntax makes some simple things―like setting a variable to a nonliteral value―needlessly complicated.
# Drawing the lottery line in TCL
package require math
while { [ llength $chosen ] < 7 } {
set lot [ ::math::random 1 37 ]
if { [ lsearch chosen $lot ] == -1 } { lappend chosen $lot }
}
foreach i $chosen { puts $i }