Dear DDJ,
In his article "Programming Language Guessing Games" (DDJ, October 1993), P.J. Plauger expresses confusion over the popularity of C++ since it is so complex and presents an exceedingly complex algorithm for pairing teams in a round-robin tournament.
Yes, C++ is a complex language. Plauger is right in suggesting we choose and stick with a subset of the language. C++ is like English. You can use it to state something in a very complex fashion, or very simply. The latter is usually the stronger statement. The round-robin tournament problem illustrates this very well.
The physical-education community has developed a simple algorithm for pairing teams. First, list the teams on pieces of paper. Leave one piece blank, if necessary, to ensure an even number of teams. Lay out the papers in two rows; that's day #1. Hold the upper-left piece in place, and rotate all the other pieces of paper; you then have day #2. Repeat the process for each succeeding day until you are back at your original positions. For six teams, the rotation would be as in Figure 1.
The C++ program implementing this algorithm is equally straightforward. Note the simple, elegant power of the for statement controlling the inner print loop, which I show in Figure 2.
Jay Frederick Ransom
Oxnard, California
Dear DDJ,
I was glad to read Michael Swaine's "Programming Paradigms" (DDJ, November 1993), which gives Forth a plug, even in a lighthearted way. It's a far cry, though, from the good old days of a decade ago when DDJ annually had an entire issue devoted to Forth.
Part of the Forth Standards efforts are confounded because the creator of Forth, Charles Moore, doesn't believe in standards for Forth. Moore considers Forth to be a program-development environment that increases productivity by speeding up the programming cycle. To keep it simple, small, and speedy (KISSS), certain design decisions resulted in using postfix notation, threaded code for compiling, a dictionary to hold functions, separate stacks for data and return addresses, and a (usually emulated) stack-based processor. As a result, the Forth language is an outgrowth of the Forth system, rather than a construct in its own right.
Moore works mostly with embedded systems, and varies the basic Forth to match the hardware and program-design requirements. Forth then behaves like assembler. A few primitive words (functions, opcodes) are used to extend Forth to develop the data types and structures that particular program requires.
On the other hand, a large group of programmers want to use Forth in symbolic programs: word processors, spreadsheets, graphics programs. They believe a Forth language without a standard is Forth in chaos. Many come from a traditional-language background--Fortran, Pascal, C, and the like. They want Forth to look more like the language they are familiar with, so they push for CASE statements, local variables, more stacks, string functions, floating-point numbers, graphics functions, and so on, as part of the standard Forth. It comes to this: Do you want Forth on a floppy or a CD-ROM?
Walter J. Rottenkolber
Mariposa, California
Dear DDJ,
I wish that you had published Walter Oney's article, "Examining the Windows Setup Toolkit" (DDJ, February 1994) a few months earlier. Last November, I had the pleasure of building a setup program for an in-house software package using the setup toolkit from the Microsoft SDK. I heartily agree with Walter: The setup toolkit is a credible toolkit (and free for SDK owners), but its documentation leaves you wishing for more.
There is one point in Walter's article which I can simplify. He recommends hand-modifying the .INF file produced by the DSKLAYT program. DSKLAYT is used to lay out the files to best fit on the setup disks. This program requires that you specify all of the files that will reside on the setup disks. This includes not only your applications files but the files that control the setup process. The .INF file, which is generated by the DSKLAYT program, controls the copying of the files from the setup disks to the user's hard disk. Normally, all of the setup files will also be listed in the .INF file and copied to the user's hard disk. Walter suggests removing these files from the .INF file by hand.
A better approach is to specify that the setup files be placed in a different section of the .INF file. This is controlled by the DSKLAYT program by filling in the "Put In Section" entry for each of the setup files. When this field is left blank, the files are put into the default section named "Files." I specify that all the setup files be placed into the section SetupFiles. When your setup script runs, it calls the function AddSectionFilesToCopyList and specifies the section name to add. For simple installation, only one call specifies the section "Files."
This is also the procedure to use when you want to allow the user to selectively setup portions of your application. You group your files in sections and allow the user to select which sections to setup. It is then a simple matter to call AddSectionFilesToCopyList for each section that is to be setup.
Gene Psoter
Atascadero, California
Dear DDJ,
Tom Swan's "Algorithm Alley" column (DDJ, December 1993) correctly points out that a group of numbers, which are alleged to be random, must satisfy a lot of tests. But the highlighted example--the stock market--is not a good random sequence. The market is somewhat unpredictable. But successive prices are very strongly correlated. The distribution of the first differences (daily changes) is very uneven with far too many very small changes. You'd quickly scrap a random-number generator that created numbers like that. The other example, lottery numbers, is fine.
Donald Kenney
CompuServe 72630,3560
Tom replies: Thanks for your letter, Donald. You're right that successive stock-market prices are very strongly correlated, but so are the sequences produced by common random-number generators. In fact, so-called "random numbers" are completely predictable to produce the same sequence--just rerun the program using any value in the sequence as the starting seed! Stock market prices are more random because they are truly unpredictable. If that were not so, as I stated in the article, everyone would be wealthy.
I understand your point that stock-market prices themselves would not be suitable as direct substitutes for common random-function output, but I never said they were. If you use the Dow Jones Industrial Average to program a lunar-lander simulator, the landing module may crash. (Let's hope the stock market doesn't.) Seriously, I am not suggesting using stock prices as random numbers; only that the behavior of the stock market is an example of true randomness. Random-number generators are misnamed because their output is predictable, and therefore, not actually random. A generator's output may appear to satisfy some conditions of randomness, but only real-world events are truly chaotic.
Dear DDJ,
In Maxwell T. Sanford II's letter (DDJ, November 1993) about my sidebar, "Putting Colors in Order" (DDJ, July 1993), Maxwell was too restrictive in assigning Cmax=min(V, 1--V). It is true that R, G, and B must be in the range (0.0, 1.0), but the Chroma C can be as large as 2/3. This is true, for example, when V=2/3 and H=0. My new paradigm for representing a color is a color bubble, not a color cone. Given values for H and V, the max C is given by the procedure GetMaxC in Figure 3.
Harry J. Smith
Saratoga, California
Processor Scenarios
Dear DDJ,
Even after many months, I found Nick Tredennick's article, "Computer Science and the Microprocessor" (DDJ, June 1993) very interesting. His market model and definitions make a lot of (common) sense. During the course of the article, there is a recurrent theme of RISC vs. CISC and PC software vs. workstation software, and it becomes apparent that Nick feels that the two will never mix.
However, emerging software technology is providing the inevitability that the two worlds will mix. Without going into its relative merits, Microsoft's Windows NT is one of the first to desegregate hardware systems. NT is already on several microprocessors, and the list is likely to grow. This can only serve to help the microprocessor market waters find their own level. It should mean that the largest market share (CISC) will drop some, and the lowest market share (RISC) will rise.
The ultimate scenario is that any microprocessor house can provide a microkernel driver for their product and "Intel Inside" will have no more meaning than "GE Inside" for toaster-heating elements (although I've heard GE is considering using the Pentium in its toasters as heater elements). Then we can all pick our own favorite processor for the job at hand. Aaron Goldberg, in the September 27, 1993 PC Week, called this the "Esperanto of Tomorrow" (and showed why a multiplatform operating system has value, whereas Esperanto failed for lack of interest).
Jonathan Platt
Pipersville, Pennsylvania
Day 1: 1 2 3
6 5 4
Day 2: 1 6 2
5 4 3
Day 3: 1 5 6
4 3 2
Day 4: 1 4 5
3 2 6
Day 5: 1 3 4
2 6 5
Day 6: Repeats Day 1
#include <iostream.h>
#include <string.h>
char teams [100] [50], // 100 teams ought to cover the field
// long names not allowed
temp [50];
int n_teams = 0,
first_half,
second_half,
day,
rotate;
char last_name;
main ()
{
// Read in team names
do
{
cin >> teams [n_teams];
last_name = teams [n_teams] [0];
n_teams++;
} while (last_name != '*'); //Delete the * team:
n_teams -= n_teams % 2; //Another simple, yet strong, expression
// print out playing schedule
for (day = 1; day < n_teams; day++)
{
cout << "\n\nDay " << day << "\n\n";
for (first_half = 0, second_half = n_teams - 1;
first_half < second_half;
first_half++, second_half--) //What you can do with a for loop!
cout << " "
<< teams [first_half]
<< " vs "
<< teams [second_half]
<< "\n";
// Rotate teams for next day
strcpy (temp, teams [1]);
for (rotate = 2; rotate < n_teams; rotate++)
strcpy (teams [rotate - 1], teams [rotate]);
strcpy (teams [n_teams - 1], temp);
}
return 0;
}
procedure GetMaxC(H, V : Double;
var C : Double);
{ Get Max C for given H and V }
const
Pi = 3.14159265358979324;
Pi2o3 = 2.0 * Pi / 3.0;
DpR = 180.0 / Pi; { Degrees per
Radian }
var
HRad : Double;
C1, C2, C3 : Double;
begin
HRad:= H / DpR;
C1:= Cos( HRad + Pi2o3);
C2:= Cos( HRad);
C3:= Cos( HRad - Pi2o3);
if (C1 > 0.0) then
C1:= V / C1
else
if (C1 < 0.0) then
C1:= (V - 1.0) / C1
else
C1:= 1.0;
if (C2 > 0.0) then
C2:= V / C2
else
if (C2 < 0.0) then
C2:= (V - 1.0) / C2
else
C2:= 1.0;
if (C3 > 0.0) then
C3:= V / C3
else
if (C3 < 0.0) then
C3:= (V - 1.0) / C3
else
C3:= 1.0;
C:= C1;
if (C2 < C) then C:= C2;
if (C3 < C) then C:= C3;
if ((V <= 0.0) or (V >= 1.0))
then C:= 0.0;
end; { GetMaxC }
Copyright © 1994, Dr. Dobb's Journal