/*H************************************************************************************************/
/*!
\File main.cpp
\Description
Hacker's Delight #7 - Nearest Neighbor
Search
Given a point cloud of 65535 points or
less, your challenge is to return the DISTANCE between
the two closest
points in the cloud. In the example below, we have limited the cloud size
to 4095 elements.
\Notes
Please read the RULE and NOTE comments
below. Entries that violate RULE(s) will be rejected.
*/
/************************************************************************************************H*/
/* $$RULE:
Adding includes is not allowed for this challenge. All submitted code must be
within
the START
and END tokens (see below).
*/
#include <iostream>
#include <math.h>
#include <time.h>
#include <float.h>
// $$RULE: The
preprocessor directive "#define" is not allowed. Use
"const" or inline functions.
// $$NOTE: Your
entry will be tested on cloud sizes up to 0xffff
const long CLOUD_ELEMENTS = 0xfff;
// $$NOTE: The
extents of the data set is for this test-harness only. Actual data may vary.
const float
CLOUD_SIZE = 2000.0f;
// $$NOTE: A
constant random seed is used here so you may test your answer against the reference
solution.
const unsigned
long gRandomSeed =
1024;
// Point class.
$$RULE: Do not modify.
class PointC
{
public:
float
x, y, z;
void
Set(float a, float b, float c) { x=a; y=b; z=c; }
void
Scale(float s)
{ x *= s;
y *= s; z *= s; }
void Offset(float
o) { x
+= o; y += o; z += o; }
static void Sub(PointC *pOut, PointC *pA, PointC *pB)
{
pOut->x = pA->x - pB->x;
pOut->y = pA->y - pB->y;
pOut->z = pA->z - pB->z;
}
};
// Cloud class.
$$RULE: Do not modify.
class CloudC
{
public:
CloudC() { m_pCloud=0; }
~CloudC() { delete [] m_pCloud;
m_pCloud = 0; }
PointC
* Create(unsigned long uiNumPoints);
inline
PointC * GetPointBuffer() { return m_pCloud; }
inline
unsigned long GetNumPoints() { return m_numPoints; }
protected:
PointC
* m_pCloud;
unsigned
long m_numPoints;
};
//
//
----------------- START -----------------
//
/* $$RULE:
Replace "Author_Institute" with your full
name and institution (company or school)
EXAMPLE: JonDoe_ElectronicArtsTiburon
*/
namespace Author_Institute
{
/******************************************************************************/
/*! GetMinDist
\brief Returns the
distance between the two "Nearest Neighbors" in the Cloud.
\param pCloud - CloudC pointer
\return - float.
Please provide a
written (English) description of your implementation here.
The more detail,
the better!!!
Your submission
is the code between the "START" and "END" markers. Please
do not
submit the
test-harness functions, or the class definitions. You can add 'helper'
functions between the
"START" and "END" markers (like the Dot example below).
Your code must
compile in MS Visual Studio and run on a standard P4.
Inline asm, SSE,
MMX are allowed.
*/
/******************************************************************************/
// Example
helper function
static float
Dot(PointC *pA,
PointC *pB)
{
return
( pA->x * pB->x + pA->y * pB->y + pA->z * pB->z );
}
// Brute force!
(You can do better than this)
float GetMinDist(CloudC *pCloud)
{
PointC
* pBuffer = pCloud->GetPointBuffer();
unsigned
long uiNumPoints = pCloud->GetNumPoints();
float
minDist = FLT_MAX;
for
(unsigned long i = 0; i < uiNumPoints; i++)
{
for (unsigned long j = i+1; j < uiNumPoints; j++)
{
PointC* ptA = &pBuffer[i];
PointC* ptB = &pBuffer[j];
PointC diff;
PointC::Sub(&diff,ptA,ptB);
float dist = sqrtf(Dot(&diff,&diff));
minDist = (dist < minDist) ? dist
: minDist;
}
}
// return the
distance between the two closest points
return
minDist;
}
} //
end namespace
//
//
----------------- END -----------------
//
PointC * CloudC::Create(unsigned long uiNumPoints)
{
PointC *pPt;
srand ( gRandomSeed );
/*
$$NOTE: This example point cloud data
is for the Test Harness. You should not assume that
the
Grading Harness will be a random distribution, like below. In fact, we plan
on
using "real-world" model data (EX: the Stanford Bunny).
http://www.gvu.gatech.edu/people/faculty/greg.turk/bunny/bunny.html
*/
m_pCloud
= new PointC[uiNumPoints];
m_numPoints
= uiNumPoints;
// Just make a quick cloud of test data
for
(pPt = m_pCloud; pPt < (m_pCloud+uiNumPoints);
pPt++)
{
pPt->Set(
(float)rand(),
(float)rand(),
(float)rand());
//[0-RAND_MAX]
pPt->Scale(1/(float)RAND_MAX); //[0.0, 1.0]
pPt->Scale(CLOUD_SIZE); //[0.0, CLOUD_SIZE]
pPt->Offset(-CLOUD_SIZE*0.5f); //[-HALF_CLOUD_SIZE, HALF_CLOUD_SIZE]
pPt->Scale(2.0f); //[-CLOUD_SIZE, CLOUD_SIZE]
}
return
m_pCloud;
}
int main (int argc, char * const argv[])
{
CloudC
*pCloud = new CloudC();
pCloud->Create(CLOUD_ELEMENTS);
printf("Min
distance between any two points is %f\n",Author_Institute::GetMinDist(pCloud));
return
0;
}