Novmber 1999 Programmer's Challenge
PuttingGreen
Mail solutions to:
progchallenge@mactech.com
Due Date: 11:59pm ET, Sunday, 7 November 1999
I’ll confess. While I’m as much of a sports fan as the next guy, I’ve never been able to get excited about golf. Not playing it, except maybe a round of miniature golf while on vacation each summer. Not watching it, which is the closest thing to watching grass grow that I can imagine. In fact, I have a hard time even thinking of golf as a sport. Real sports involve perspiration. Real sports involve being exhausted. Golf doesn’t have either, as near as I have been able to tell, and therefore couldn’t be worth getting involved in. Or so I thought.
Feeling this way, I didn’t pay very much attention to the news that the 1999 Ryder Cup was going to be held relatively close by. And when a ticket to the first day of matches came my way, I thought about passing it on to someone else. For a few days, that is. Until I started reading some of the growing volume of newspaper coverage and got an appreciation for what a really big deal people were making of this. It seemed even bigger than the baseball All Star game, also held in Boston this year. Baseball, also not the most intense sport, involves some amount of running and perspiration. So if the Ryder Cup was as big as the All Star game, it must be worth watching. So I decided to attend.
What, you must be asking, does any of this have to do with the Programmer’s Challenge? Did someone substitute an issue of Sports Illustrated under the cover? No, it’s just that the Ryder Cup provided the inspiration for this month’s Challenge. Watching Tiger Woods make a birdie putt on the 10th, watching three teams miss essentially the same putt on the 14th, my mind turned to — why, physics, of course. How did they read (or misread) those breaks? Your Challenge will be to figure it out.
The Challenge this month is going to be to put some simulated balls into simulated holes on simulated greens. The greens will be provided to you as an array of three dimensional points, divided into an array of adjoining triangles. You will "putt" the ball by imparting a velocity. The ball will move according to a black box propagation model that incorporates the effects of gravity and drag. How are you supposed to know how the ball will move if you don’t have the propagation code? The same way Tiger and Monty do it, of course — practice!
The prototype for the code you should write is:
#if defined(__cplusplus)
extern "C" {
#endif
#include <MacTypes.h>
typedef struct Point3DDouble {
double x;
double y;
double z;
} Point3DDouble;
typedef struct Velocity2DDouble {
double x;
double y;
} Velocity2DDouble;
typedef struct MyTriangle {
long pointIndices[3]; /* index of points comprising the triangle */
} MyTriangle;
typedef struct BallPosition {
double time;
Point3DDouble pt;
} BallPosition;
void InitGreen(
Point3DDouble points[], /* green terrain description */
long numPoints, /* number of points */
MyTriangle triangles[], /* triangles comprising the green */
int numTriangles, /* number of triangles */
long pinTriangle, /* index in triangles[] of the pin on this green */
long numPracticeHoles,
/* number of unscored (but timed) holes to practice on this green */
long numScoredHoles /* number of holes to be scored on this green */
);
void StartHole( /* called to start play on this hole */
Point3DDouble ballPosition, /* initial ball position on the green */
Boolean practice /* TRUE if this hole is practice */
);
Boolean /* quit */ MakePutt(
Velocity2DDouble *xyVelocity /* return initial ball velocity in the z==0 plane */
);
void BallMovement(
BallPosition ballPositions[], /* provides ball movement in response to MakePutt */
int numBallPositions, /* number of ballPositions provided */
Boolean inHole /* true if the ball went into the hole */
);
#if defined(__cplusplus)
}
#endif
For each green you play on, your InitGreen routine will be called. It will be provided with the coordinates of numPoints points and with the numTriangles triangles that describe the topography of the green. One of the triangles (triangles[pinTriangle]) will represent the pin position on this hole - you need to move the ball from the starting ballPosition so that it enters this triangle in order to complete the hole. InitGreen will also be given the number of practice holes and the number of scored holes to be played on this green, each with a different initial ballPosition. The practice holes will all be played before any of the nonpractice holes, and the number of practice holes will always be at least as great as the number of nonpractice holes.
For each hole, your StartHole routine will be called with the initial ballPosition for that hole. The practice indicator will be set to TRUE if this is a practice hole. Next, your MakePutt and BallMovement routines will be called repeatedly until you put the ball in the hole (inHole==TRUE) or until you quit (MakePutt returns TRUE). You might quit on a practice hole if you decide you don’t need any more practice (saving execution time). You might quit on a nonpractice hole if you decide that the cost of completing the hole exceeds the benefit (see the notes on scoring below).
MakePutt returns the velocity vector you want to impart for this shot. It is important to remember that your stroke velocity is specified in the x-y plane. That velocity will be increased (by 1/cos(slope)) to compensate for terrain angle. As the ball moves, the velocity will accelerated due to the effect of gravity, and decelerated due to the effect of drag.
BallMovement provides you with the results of your shot as a sequence of numBallPositions BallPositions. Each BallPosition has a three-dimensional position and a time tag (in seconds relative to the start of this shot). The inHole flag will tell you whether the ball went into the hole, indicating that the hole is over.
Solutions will be scored based on the number of holes successfully completed, the number of strokes required to complete those holes, and the amount of execution time expended. Each completed nonpractice hole earns 100 points. Each nonpractice stroke reduces the score by 10 points, and each second of execution time (including practice time) costs 10 points. The winner will be the solution that earns the greatest number of total points.
This will be a native PowerPC Challenge, using the latest CodeWarrior environment. Solutions may be coded in C, C++, or Pascal. Solutions in Java will also be accepted this month. Java entries must be accompanied by a test driver that uses the interface provided in the problem statement.
Test code for this Challenge is available.
You can get a head start on the Challenge by reading the
Programmer's Challenge mailing list. It will be posted to the list on
or before the 12th of the preceding month. To join, send an email to
listserv@listmail.xplain.com
with the subject "subscribe challenge-A". You can also join the
discussion list by sending a message with the subject "subscribe
challenge-D".
|