Computer Programming Tournament
Our February Winner

Milan Stanojevic
Belgrade, Yugoslavia |
Next
Month |
Rules |
Winner |
Last
Month |
Quickest |
Shortest |
Fastest |
Rankings |
| Next
Contest:
The March contest will open on Sunday 12 March at 5pm GMT
(noon Eastern, 9am Pacific). It will close one week later.
Don't forget
that we will be having a Programming Chat Session between 9pm and
11pm GMT (4pm and 6pm Eastern, 1pm and 3pm Pacific) in our Programming chat
room on the night of Sunday 12 March where you are all invited to meet up
and discuss the problem we have set, or anything else to do with the world
of programming.
In addition,
we have set up a
Discussion
List that may be used to ask questions about the programming contest.
If you have questions about the contest, we suggest you subscribe, because
we will try to send ANY answers that might give any advantage to the person
who asks the question to everyone on the list. |
To whet your
appetite, here is the challenge that faced our February entrants:
February's
Challenge and February's Rules
Our
second programming challenge ran for seven days starting at 5pm GMT on Sunday
13th February and is outlined below:
The
Challenge:
Your program
will take a list of letters, and find all possible anagrams of letters found
in a supplied dictionary. You can get the dictionary, composed of 26 files
(one for each letter) here.
Your program
must be able to accept up to 50 letters. For example, if the letters "ABN"
are supplied as input, your program could find "A", "AB", "BAN" and "NAB"
but not "BANANA" since only one "A" and one "N" is available. That would
require that "AAABNN" be in the input letters.
Test your program
on this sequence of letters: AFSGKRMEO.
This "rule" was
altered during the contest:
-
Old rule:
If you suggest a word which does not appear in words.zip then you lose one
valid word from your overall total.
-
Revised
rule: If you suggest a word which does not appear in words.zip, or if
you fail to find a valid anagram that does appear in words.zip, your entry
will be disqualified from consideration.
-
Reason for
change: Several entrants (and this editor) pointed out that the rules
and the formula, as originally stated, would have allowed a person who found
ZERO valid words to win the contest. We felt that this revised rule
better reflected the original intent of the people who created this challenge.
(more information at footnote one.)
Winning entries
must allow us to publish the source code.
You have to write
new code for the contest and can't enter any solution for the problem that
you may have produced in the past, even if you were the author.
More
rules, and reasons entries were disqualified,
can be found at the bottom of the page. .
It took us longer
than we expected, but we finally compiled all of the results. All programs
which were submitted to the evaluation team were evaluated for speed and
accuracy on the same system. Here are four tables outlining our results.
|
-
T S Lung, the
quickest programmer, submitted his entry after only 25 minutes (see
Table One for the twenty quickest programmers)
-
T S Dimitrov
submitted the shortest executable program, a mere 202 bytes (see
Table Two for the twenty shortest programs)
-
G Economou had
the fastest program, which ran in just 460 milliseconds (see
Table Three for the twenty fastest programs, and
Editor's comment about Murphy's Law as it relates to
fast programs on slow computers)
-
Milan Stanojevic
ended up with the best rating, 21.0 (see Table Four
for the top thirty ratings, biography to read more
about Milan, or source code to see his program, which
I'm sure is very similar to some of our other entrants' programs)
|
Table
1: Twenty Quickest Programmers starting with 25 minutes
(hours: minutes ... programming time rounded to the nearest
minute)
Program
Time |
Size of
Program |
Execution
Speed |
Total
Rating |
Entrant's
Name, Language, and System information |
25 |
6800 |
819 |
36.4 |
T S Lung;
T Pascal 7; PII 400 Win98 |
32 |
20480 |
9000 |
122.2 |
R Malaschitz;
V Basic 6; P133 Win98 |
33 |
3344 |
1810 |
21.8 |
L Rujia;
T Pascal 7; Celeron 300A MS-DOS 6.22 |
44 |
13476 |
875 |
70.4 |
M Vogelzang;
B c++; P2 350 windows 98 |
59 |
3872 |
603 |
22.8 |
B Esfahbod;
B Pascal 7; P 166mhz Windows95 |
1:10 |
10610 |
697 |
56.8 |
J van Dijk;
B C++ 3.1; P 100 Dos 7/Win95 |
1:11 |
3296 |
874 |
21.1 |
E Chiniforooshan;
Pascal; P2 300 Win98 |
1:14 |
3312 |
763 |
21.0 |
M Stanojevic;
B Pascal 7; P133mhz Win98/DOS |
2:11 |
3792 |
1148 |
26.5 |
S Savchuk;
B Pascal; P 90 Windows 95 |
2:28 |
13347 |
770 |
73.7 |
M Ishii;
C; Aptiva K6-166 Windows95 |
3:43 |
31957 |
1973 |
171.4 |
A E Amin;
P 200 MMX MS-DOS |
5:14 |
1871 |
8517 |
40.3 |
S Datskovsky;
MoonRock BASIC; P 233mhz MS-DOS 6.22 |
6:43 |
4656 |
770 |
40.8 |
M Rudisin;
T Pascal 7; AMD K6-166 Win98 |
9:30 |
34136 |
1370 |
194.7 |
M K Mammel;
C++; 486DX 66mhz DOS/Win3.1 |
14:01 |
3072 |
460 |
49.8 |
G Economou;
C; DEC VAX 3600 11mhz 4.3BSD UNIX |
14:24 |
3376 |
766 |
52.9 |
M Opmanis;
B Pascal; P 200mhz |
15:05 |
12884 |
13071 |
128.3 |
I Bely; Turbo
C; PIII-450 DOS |
17:01 |
3728 |
1314 |
62.1 |
W K Chung;
T Pascal 7; PII 266 DOS/Win98 |
22:19 |
3200 |
930 |
71.3 |
H B Dieste;
Pascal; Celeron 300mhz Win NT 4.0 |
22:44 |
3856 |
1758 |
77.4 |
W v d Vegt;
T Pascal 5; P2 266mhz Windows 95 |
Table 2: Twenty Shortest Programs start at 202 bytes
Program
Time |
Size of
Program |
Execution
Speed |
Total
Rating |
Entrant's
Name, Language, and System information |
115:12 |
202 |
109359 |
514.7 |
T S Dimitrov;
Assembler NASM; Cyrix 166mhz MS-DOS |
35:32 |
251 |
4719 |
96.6 |
G Hahn;
Assembler; PIII 500mhz Win98/Dos |
48:10 |
500 |
14791 |
150.0 |
W L Tai;
python; celeron 400 linux 2.2.5 |
5:14 |
1871 |
8517 |
40.3 |
S Datskovsky;
MoonRock BASIC; P 233mhz MS-DOS 6.22 |
14:01 |
3072 |
460 |
49.8 |
G Economou;
C; DEC VAX 3600 11mhz 4.3BSD UNIX |
23:09 |
3152 |
685 |
72.5 |
M Zivic;
Pascal; Celeron A 300mhz Win98 |
22:19 |
3200 |
930 |
71.3 |
H B Dieste;
Pascal; Celeron 300mhz Win NT 4.0 |
1:11 |
3296 |
874 |
21.1 |
E Chiniforooshan;
Pascal; P2 300 Win98 |
1:14 |
3312 |
763 |
21.0 |
M Stanojevic;
B Pascal 7; P133mhz Win98/DOS |
33 |
3344 |
1810 |
21.8 |
L Rujia;
T Pascal 7; Celeron 300A MS-DOS 6.22 |
14:24 |
3376 |
766 |
52.9 |
M Opmanis;
B Pascal; P 200mhz |
43:39 |
3472 |
686 |
123.2 |
A Tsiskaridze;
B Pascal 7; PII MMX 400mhz Win98 |
88:28 |
3552 |
937 |
231.5 |
K Matisons;
T Pascal 7; P 100 windows 95 |
17:01 |
3728 |
1314 |
62.1 |
W K Chung;
T Pascal 7; PII 266 DOS/Win98 |
2:11 |
3792 |
1148 |
26.5 |
S Savchuk;
B Pascal; P 90 Windows 95 |
22:44 |
3856 |
1758 |
77.4 |
W v d Vegt;
T Pascal 5; P2 266mhz Windows 95 |
59 |
3872 |
603 |
22.8 |
B Esfahbod;
B Pascal 7; P 166mhz Windows95 |
152:21 |
3972 |
1155 |
387.1 |
J Zbiciak;
C; 400mhz PII Linux 2.2 |
153:21 |
4148 |
1107 |
390.2 |
P Baylies;
C; K6/300 Linux |
6:43 |
4656 |
770 |
40.8 |
M Rudisin;
T Pascal 7; AMD K6-166 Win98 |
Table 3: Twenty Fastest Programs starting at 460
milliseconds
(note: all programs were timed on the same 450 mhz Pentium system
on the same data set)
(order not significant when two times are identical)
Program
Time |
Size of
Program |
Execution
Speed |
Total
Rating |
Entrant's
Name, Language, and System information |
14:01 |
3072 |
460 |
49.8 |
G Economou;
C; DEC VAX 3600 11mhz 4.3BSD UNIX
. . . see editor's comment about Murphy's
Law |
59 |
3872 |
603 |
22.8 |
B Esfahbod;
B Pascal 7; P 166mhz Windows95 |
104:36 |
31744 |
604 |
409.0 |
Z Nezic;
V C++ 5; P MMX 233mhz Win NT 4.0 |
23:09 |
3152 |
685 |
72.5 |
M Zivic;
Pascal; Celeron A 300mhz Win98 |
43:39 |
3472 |
686 |
123.2 |
A Tsiskaridze;
B Pascal 7; PII MMX 400mhz Win98 |
1:10 |
10610 |
697 |
56.8 |
J van Dijk;
B C++ 3.1; P 100 Dos 7/Win95 |
1:14 |
3312 |
763 |
21.0 |
M Stanojevic;
B Pascal 7; P133mhz Win98/DOS |
14:24 |
3376 |
766 |
52.9 |
M Opmanis;
B Pascal; P 200mhz |
2:28 |
13347 |
770 |
73.7 |
M Ishii;
C; Aptiva K6-166 Windows95 |
6:43 |
4656 |
770 |
40.8 |
M Rudisin;
T Pascal 7; AMD K6-166 Win98 |
25 |
6800 |
819 |
36.4 |
T S Lung;
T Pascal 7; PII 400 Win98 |
1:11 |
3296 |
874 |
21.1 |
E Chiniforooshan;
Pascal; P2 300 Win98 |
44 |
13476 |
875 |
70.4 |
M Vogelzang;
B c++; P2 350 windows 98 |
115:17 |
47104 |
920 |
511.3 |
W Teixeira;
C; P Celeron 366mhz Win98 |
22:19 |
3200 |
930 |
71.3 |
H B Dieste;
Pascal; Celeron 300mhz Win NT 4.0 |
88:28 |
3552 |
937 |
231.5 |
K Matisons;
T Pascal 7; P 100 windows 95 |
153:21 |
4148 |
1107 |
390.2 |
P Baylies;
C; K6/300 Linux |
2:11 |
3792 |
1148 |
26.5 |
S Savchuk;
B Pascal; P 90 Windows 95 |
152:21 |
3972 |
1155 |
387.1 |
J Zbiciak;
C; 400mhz PII Linux 2.2 |
58:18 |
16384 |
1260 |
223.5 |
M Mika; C++;
Intel 466mhz Win98 |
Table 4: The Best Thirty Ratings (rounded to the
nearest tenth)
Program
Time |
Size of
Program |
Execution
Speed |
Total
Rating |
Entrant's
Name, Language, and System information |
1:14 |
3312 |
763 |
21.0 |
M Stanojevic;
B Pascal 7; P133mhz Win98/DOS |
1:11 |
3296 |
874 |
21.1 |
E Chiniforooshan;
Pascal; P2 300 Win98 |
33 |
3344 |
1810 |
21.8 |
L Rujia;
T Pascal 7; Celeron 300A MS-DOS 6.22 |
59 |
3872 |
603 |
22.8 |
B Esfahbod;
B Pascal 7; P 166mhz Windows95 |
2:11 |
3792 |
1148 |
26.5 |
S Savchuk;
B Pascal; P 90 Windows 95 |
25 |
6800 |
819 |
36.4 |
T S Lung;
T Pascal 7; PII 400 Win98 |
5:14 |
1871 |
8517 |
40.3 |
S Datskovsky;
MoonRock BASIC; P 233mhz MS-DOS 6.22 |
6:43 |
4656 |
770 |
40.8 |
M Rudisin;
T Pascal 7; AMD K6-166 Win98 |
14:01 |
3072 |
460 |
49.8 |
G Economou;
C; DEC VAX 3600 11mhz 4.3BSD UNIX |
14:24 |
3376 |
766 |
52.9 |
M Opmanis;
B Pascal; P 200mhz |
1:10 |
10610 |
697 |
56.8 |
J van Dijk;
B C++ 3.1; P 100 Dos 7/Win95 |
17:01 |
3728 |
1314 |
62.1 |
W K Chung;
T Pascal 7; PII 266 DOS/Win98 |
44 |
13476 |
875 |
70.4 |
M Vogelzang;
B c++; P2 350 windows 98 |
22:19 |
3200 |
930 |
71.3 |
H B Dieste;
Pascal; Celeron 300mhz Win NT 4.0 |
23:09 |
3152 |
685 |
72.5 |
M Zivic;
Pascal; Celeron A 300mhz Win98 |
2:28 |
13347 |
770 |
73.7 |
M Ishii;
C; Aptiva K6-166 Windows95 |
22:44 |
3856 |
1758 |
77.4 |
W v d Vegt;
T Pascal 5; P2 266mhz Windows 95 |
35:32 |
251 |
4719 |
96.6 |
G Hahn;
Assembler; PIII 500mhz Win98/Dos |
32 |
20480 |
9000 |
122.2 |
R Malaschitz;
V Basic 6; P133 Win98 |
43:39 |
3472 |
686 |
123.2 |
A Tsiskaridze;
B Pascal 7; PII MMX 400mhz Win98 |
15:05 |
12884 |
13071 |
128.3 |
I Bely; Turbo
C; PIII-450 DOS |
48:10 |
500 |
14791 |
150.0 |
W L Tai;
python; celeron 400 linux 2.2.5 |
3:43 |
31957 |
1973 |
171.4 |
A E Amin;
P 200 MMX MS-DOS |
9:30 |
34136 |
1370 |
194.7 |
M K Mammel;
C++; 486DX 66mhz DOS/Win3.1 |
58:18 |
16384 |
1260 |
223.5 |
M Mika; C++;
Intel 466mhz Win98 |
88:28 |
3552 |
937 |
231.5 |
K Matisons;
T Pascal 7; P 100 windows 95 |
152:21 |
3972 |
1155 |
387.1 |
J Zbiciak;
C; 400mhz PII Linux 2.2 |
153:21 |
4148 |
1107 |
390.2 |
P Baylies;
C; K6/300 Linux |
104:36 |
31744 |
604 |
409.0 |
Z Nezic;
V C++ 5; P MMX 233mhz Win NT 4.0 |
115:17 |
47104 |
920 |
511.3 |
W Teixeira;
C; P Celeron 366mhz Win98 |

Milan Stanojevic
Yugoslavia
19 year old freshman
University of Belgrade
Electrical Engineering
More data on right |
The winner of the $500 First Prize awarded in the second contest is
Milan Stanojevic, who commented to me that the "sheer nature of
the contest meant that a simple program, that can be coded fast, would win.
"
Well, Milan, you were certainly right. You wrote, tested, and submitted your
program in just over an hour. A more complicated program MIGHT have run faster,
but I don't think it would have made a significant difference in this contest.
(Besides, the more complicated program I wrote bombed in the final
evaluation).
Milan wrote his
program on a 133 mhz Windows/DOS Pentium system in just over seventy-four
minutes, using Borland Pascal 7.0. His compiled program was only 3312
bytes long, ran in 763 milliseconds (on our 450 mhz test system),
and received a final rating of 21.0 after we applied our formula to
all of the entries that successfully passed our final challenge, finding
64,738 anagrams in the string
AABBDDEEFFGGHHIIJJKKLLMMNNOOPPRRSSTTUUVVWWXXYYZZ.
Here's what Milan
told me about himself.
"I'm 19 years
old. I am a freshman at the University of Belgrade, Faculty of Electrical
Engineering. I spend most of the time at faculty and studying as probably
all the university students do.
"I've finished
Mathematical High School in Belgrade, a school specialized in mathematics,
physics informatics, and similar sciences. During that four-year period I
was a member of the Yugoslav team that participated in a number of international
programming contests for high school students including International
Olympiad in Informatics (IOI), Balkan Olympiad in Informatics
(BOI) and Central European Olympiad in Informatics (CEOI). I won several
medals with a Silver at IOI'98 in Portugal being the most
important. I have also competed in a ACM regional programming contest
as part of my faculty team. I've enjoyed these contests because I visited
many interesting countries and met many interesting people.
"I am very interested
in such programming competitions. I am now too old for IOIs but I'm still
involved in high school contests as a member of team that organizes Yugoslav
competitions, selects and prepares Yugoslav team for IOIs, BOIs, CEOIs. I
am also a associate member of Electronics staff at Petnica
Science Center (one of the leading science centers for young people in this part
of the world, not just Yugoslavia).
"My main interests
are in computer science especially in algorithms. I am also interested in
mathematics and physics. Beside this I am pretty much ordinary young man.
I enjoy playing basketball and spending time with friends.
"I am from a
small town, a spa actually, in eastern Serbia called Sokobanja. My parents
live there. The last five years I've lived in Belgrade where I attend university
and where I was in high school. And of course my country is Yugoslavia,
unfortunately the most famous country of 1999. I hope that better times will
come for my country. |
----- Milan's source code -----
{
Program is fairly simple and I belive that others came up with very
similar solutions.
I've first observed that there are less than 100,000 words in dictionary.
It ment that I could just browse through dictionary. (100,000 cycles is
not very much for today's computers). I just speed it up a bit by skipping
dictionary files with words that start with unavailable letters.
I read given letters from first line of 'input.txt' and write found
valid words to 'output.txt'.
}
var
{ these arrays hold how many of each letter we have available }
brpoj, trbrpoj: array['A'..'Z'] of integer;
inputlen: integer; {number of available letters (not necessary different)}
rec: string; {current word in checking}
fout: text;
procedure getinput;
var
fin: text;
st: string;
i: integer;
begin
assign(fin, 'input.txt');
reset(fin);
readln(fin, st);
close(fin);
inputlen := length(st);
fillchar(brpoj, sizeof(brpoj), 0);
for i:=1 to length(st) do {compute number of each}
inc(brpoj[ upcase(st[i]) ]); {letter's occurences }
end;
{ procedure checks if REC holds a word that can be made of given letters }
procedure probaj;
var
i, len: integer;
ch: char;
begin
move(brpoj, trbrpoj, sizeof(brpoj)); {store available letters in
temporary variable }
len := length(rec);
if len > inputlen then exit; {not enough letters}
{ go trough the word and use one by one letter. if we don't run out of
letters then it is a valid word }
for i:=1 to len do
begin
ch := rec[i];
dec(trbrpoj[ch]); {use letter}
if trbrpoj[ch] < 0 then exit; {ran out of letters. not a valid word}
end;
writeln(fout, rec); {found a valid word}
end;
procedure nadjireci;
var
ch: char;
fin: text;
begin
assign(fout, 'output.txt');
rewrite(fout);
{ check dictionary files exept those that contain words that start with
anavailable letters }
for ch:='A' to 'Z' do
if brpoj[ch] > 0 then
begin
assign(fin, ch + '.WRD');
reset(fin);
while not eof(fin) do
begin
readln(fin, rec); {read word into REC}
probaj; {check REC}
end;
close(fin);
end;
close(fout);
end;
begin
getinput;
nadjireci;
end.
Do you think
you could do better? March's contest will be bigger and better and has
another $500 prize. A new set of rules for March's contest will be
released in advance of the contest, which will start at 5pm GMT (noon
Eastern, 9am Pacific) on Sunday, March 12.
January's contest
results here.
An
Outline of the February Programming Contest
Rules:
The contest will
set out a specific computing task. Programmers will create a program to perform
this function using test data supplied by MSO. Once you have completed your
program, you must
run
it on the test
data,
note the elapsed time for the program run, and enter this information on
a form above. If your program appears to be a winner, you may be required
to verify this on other sample data we supply.
To prevent cheating
and possible later program modifications or enhancements, all entries must
run the final executable version of their program though an industry standard
checksum program. MSO will supply this program in both "C" language and compiled
form for MS-DOS computers
HERE.
Entries must
be received by the time noted in the contest. Late entries will not be accepted.
After receiving
all entries, judges will decide on a possible winner, then require the possible
winning entries to send in the source and compiled code so that it can be
verified against an internal set of inputs. Full instructions must be supplied
at this point if data entry is not immediately obvious. Judges will use their
best means to verify the program is as described and performs correctly.
If the judges require it, the programmer must be willing to run sample test
data through the program on his or her machine. Any winning entry must supply
the full source code and allow MSO Worldwide to display the source code on
the web site. All source code must be original, new and written by the submitting
author(s).
Winners will
be based on the entries which get the best score (lowest number) using this
formula:
Your programming
time / fastest programming time
+ Your execution time / fastest execution time
+ Your program size / smallest program size ***
Program size
is of the object code (executable code). Only entries which calculate the
right answers will be judged. Programming time is the time between when the
contest is begun and the time you submit your entry.
Only one entry
is allowed per programmer per contest. Each programmer can only win the cash
prize once every six months, but feel free to enter and get credit anyway.
Program checksum must match the submitted checksum, or your entry will be
disqualified
Reasons
entries were disqualified:
-
Multiple entries
(rules stated
"Only
one entry is allowed")
-
Entrant did not
submit 293 words with his entry
-
Entrant did not
e-mail executable program for verification by March 4
-
Program did not
find 12 words in "BANANA" when tested on official computer
-
Program did not
find 64,738 words during the "timing evaluation"
"AABBDDEEFFGGHHIIJJKKLLMMNNOOPPRRSSTTUUVVWWXXYYZZ"
-
Program would
have required recompilation in order to change the input.
-
Program did not
run on computer used for official evaluation.
-
A few programmers
used a shortcut to save execution time that is not valid on all computers,
or imposed limits on their program that required recompiling to handle long
output files.
-
Some programmers
renamed the input files causing execution errors when their program could
not find the originally named input files on our official system.
-
We tried to make
every effort to make sure that we were fair.
-
We did not use
C in our final speed tests, because two entrants told us there was a mistake
in C.WRD (there was no CR/LF after the last word in the file), and we did
not want to hurt any entrants whose program might not find CZARS
-
We accepted one
entry that missed DA, because he concatenated the dictionary files, causing
CZARSDA to become a word. (This won't happen in future contests because we
will require using the input files as supplied).
-
We tried to
anticipate every method of INPUT that might be used by a programmer. We even
tried to hex-edit programs that appeared to be hard-coded.
-
We did our best
to run all submitted programs on our evaluation system, under Windows, under
DOS, and under Linux.
-
We tried to contact
entrants whose programs did not work on our computer, especially if there
appeared to be a chance a program might have won in its category. Note that
we do NOT plan to contact programmers during future contests.
-
Changes that
will be made to future rules based on problems during this contest
-
Standard INPUT
methods will be required
-
command line
entry
-
input during
execution
-
a designated
input file
-
All files to
be in the same directory as the executable.
-
All programs
must work with supplied files as given
-
no content
changes
-
no renaming of
files
-
no file
concatenation
-
all programs
must include all input and output time in calculation of execution
times.
-
Programmers may
not use aliases to bypass the one entry per programmer limit (it can cause
loss of prize when names don't match, especially if you later get invited
to compete in person).
(footnote
one *** By the way, astute observers will notice a change in our formula
from that which was posted on February 13. Due to an error in that formula,
an error which several entrants pointed out to us during the Programming
Chat Session, a program which found ZERO answers could have won. The judges
chose to ONLY consider programs which found all 293 possible words for the
next stage of the judging, and to only rank entrant programs which found
12 words in BANANA and 64,738 words in the final string. This was the original
intent of the revision in the rules. The formula above is the one that was
posted, and used, for the January contest.)
Editor's
comment about program execution on old computers
(Table Three):
When I realized
that G Economou's program, written on an 11 mhz computer (possibly the slowest
computer used in this competition), outperformed programs written on faster
computers, I immediately thought about
Murphy's Law
and some of
its corralaries,
especially "Any program will expand to fill available memory." I mention
that here because it is certainly possible that the old compilers from SMALL
computers may have created more efficient programs because they didn't have
all the bells and whistles of today's computers. The earliest programmers
had to do everything in less memory!! Just my idea why a programmer on a
very slow computer could end up in first position according to speed. I remember
when I was programming in 16K of memory that I developed MANY shortcuts and
tricks to fill a program with options that others said wouldn't fit. Anyone
who remembers a 16K Star Trek written for the TRS-80 Model One might have
seen some of those tricks ... comment added by John Knoderer.
[
Back to
Top
]
|