Yes, it's time for a mini coding comp, and for this one there is a prize! I have an unopened copy of Full Spectrum Warrior for the Xbox (you can trade it if you don't have an Xbox), which will go to the winner. Watch this space for more details!
Ok, here's the challenge: Demonstrate the best use of the STL. This will be in the form of a simple program that does a small task while taking advantage of the STL. Here is an example that reads white-space delimed input into a vector:
[code]
#include
#include
#include
#include 
using namespace std;
int main(int argc, char** argv)
{
  // variables used
  vector output;
  // push back strings from cin, splits on whitespace
  copy(istream_iterator(cin), istream_iterator(), back_inserter(output));
  // output to screen
  copy(output.begin(), output.end(), ostream_iterator(cout, "
"));
  // wait for user to hit enter before closing
  cin.clear(); cin.get();
}
[/code]
Programs will be judged on code size (smaller is better), code elegance (keep it clean), and functionality (more bang for your buck). Entries close midnight 31st of December. You may have up to 2 entries. At this point, it will just be me judging. What I say goes.
I put a thread up in the competition section for entries.
http://www.sumea.com.au/forum/topic.asp?TOPIC_ID=2575
It was mentioned that it's not actually a programmer challenge,
but I don't know how to delete the thread. Oops!
Here's a quick one to get the ball rolling, a simple replacement for the standard STL sort algorithm:
[code]#include
#include
#include
#include 
using namespace std;
template void merge_sort(T &data, P predicate)
{
    T::size_type size = data.size();
    if(size == 2)
    {
        // A single pair, put them in order
        T::iterator a = data.begin();
        T::iterator b = data.begin() + 1;
        if(predicate(*b, *a)) swap(*a, *b);
    }
    else if(size > 2)
    {
        T::size_type mid = size / 2;
        // Split the data into two halves
        T a(data.begin(), data.begin() + mid);
        T b(data.begin() + mid, data.end());
        // Sort each half individually
        merge_sort(a, predicate);
        merge_sort(b, predicate);
        // Combine the two sorted halves
        merge(a.begin(), a.end(), b.begin(), b.end(), data.begin(), predicate);
    }
}
int get_random_int()
{
    return rand() % 100;
}
int main(int argc, char **argv)
{
    static const int size = 20;
    // Generate a random unordered data set
    vector data(size);
    generate_n(data.begin(), size, get_random_int);
    // Test our Merge Sort
    merge_sort(data, less());
    // Display
    copy(data.begin(), data.end(), ostream_iterator(cout, " "));
    cout << endl;
    return 0;
}[/code]
To me the best thing about STL is that it gives you a reliable base on which you can easily experiment with different ideas.  It abstracts you just enough that you can concentrate on optimising what's really important, the algorithms rather than individual lines of code.  I went for easy to read but my first performance modification would be to make it sort in place to reduce the amount of array copying going on in each recursion.  After that I suggest changing to a different algorithm, haha!
- Clean easy to read code.
- All trivial tasks covered by standard STL components.
- Works with any container providing random access iterators.
- Works with any type your predicate can compare.
I tested this briefly on VC++ .Net, apologies for any bugs or incompatibilites.
quote:Originally posted by kalin
I put a thread up in the competition section for entries.
http://www.sumea.com.au/forum/topic.asp?TOPIC_ID=2575
It was mentioned that it's not actually a programmer challenge,
but I don't know how to delete the thread. Oops!
BALETED!
Here is an example that reads words from a file into a set (which is sorted) and outputs them to the screen.
[code]
#include
#include
#include
#include
#include
#include 
using namespace std;
class Word
{
private:
  string chars;
public:
  friend istream& operator>> (istream& is, Word& ch );
  operator const string& ()
  {
    return chars;
  }
  bool operator < (const Word& rhs) const
  {
    return chars < rhs.chars;
  }
};
istream& operator>> (istream& is, Word& w )
{
  w.chars.clear();
  // dump non-alpha chars at the begining
  while (is.good() && !isalpha(is.peek()))
  {
    is.get();
  }
  // get all the alpha chars
  while (is.good() && isalpha(is.peek()))
  {
    w.chars += is.get();
  }
  return is;
}
int main(int argc, char** argv)
{
  // variables used
  set output;
  ifstream fin((argc > 1) ? argv[1] : "input.txt");
  // insert Words from file stream
  copy(istream_iterator(fin), istream_iterator(), inserter(output, output.begin()));
  // output to screen
  copy(output.begin(), output.end(), ostream_iterator(cout, "
"));
  // wait for user to hit enter before closing
  cin.clear(); cin.get();
}
[/code]
edited:
BALETED!
...I mean fixed closing code tag
Here is a simple file copying program.
Usage: "copy output.ext input.ext"
I'll probably try and think up something more complicated later,
but this is a nice simple example of how nice STL is to work with. :)
[code]
#include
#include 
int main(int argc, char** argv)
{
  if (argc >= 3)
    std::ofstream(argv[2]) << std::ios::binary << (std::ifstream(argv[1]));
  return 0;
}
[/code]
Okay, here's one. It does a search and replace on a given text file:
[code]
#include
#include
#include
#include
#include 
using namespace std;
/*
    redwyre's mini coding contest
    Usage:
    replace   
    Replaces all occurances of  with  in
*/
ofstream fout;
void putwords(string s)
{
    // Put words into file
    fout << s + " ";
}
int main(int argc, char **argv)
{
    list words;
    ifstream	 fin;
    string       s;
    if (argc < 4)
    {
        cout << "Usage: replace   " << endl;
        return -1;
    }
    //	Open file
    fin.open(argv[1]);
    if(!fin)
    {
        cout << "Couldn't open file " << argv[1] << endl;
        return -1;
    }
    //	Read all words into list
    while(!fin.eof())
    {
        getline(fin, s, ' ');
        words.push_back(s);
    }
    // Close input file stream and open output file stream
    fin.close();
    fout.open(argv[1]);
    if (!fout)
    {
        cout << "Couldn't open file " << argv[1] << endl;
        return -1;
    }
    //	Replace oldstring with newstring
    replace_copy(words.begin(), words.end(), words.begin(), string(argv[2]), string(argv[3]));
    for_each(words.begin(), words.end(), putwords);
fout.close();
    return 0;
}
[/code]
To submit your entries, feel…
To submit your entries, feel free to post them here, but make sure you send them to me via email: xxx with the subject starting with "[Sumea]" I'll try and get everything sorted and announce the winner before the end of January.
[code]
//cache invert sqrt class and testbed
#include
#include
#include
#include 
typedef float          real;
typedef signed   int   s32;
typedef unsigned char  u8;
struct TCommonCache_InverseSqrt
{
  bool operator()(const float lhs, const float rhs) const
  {
    return (lhs < rhs);
  }
};
class CCommonCache_InverseSqrt
{
	public:
		~CCommonCache_InverseSqrt(void);
		bool Clear(void);
		bool GetInverseSqrt( const real in_square, real & out_root);
	private:
		typedef std::map< real, real, TCommonCache_InverseSqrt> TRealRootMap;
	private:
		TRealRootMap m_root_map;
};
CCommonCache_InverseSqrt::~CCommonCache_InverseSqrt(void)
{
	Clear();
	return;
}
bool CCommonCache_InverseSqrt::Clear(void)
{
	m_root_map.clear();
	return true;
}
bool CCommonCache_InverseSqrt::GetInverseSqrt(const real in_square, real & out_invert_root)
{
	TRealRootMap::const_iterator iterate;
	real root;
	bool ok;
ok = true;
	if (ok)
	{
		ok = (0.0F <= in_square);
	}
	if (ok)
	{
		iterate = m_root_map.find(in_square);
		if (iterate == m_root_map.end())
		{
			if (in_square == 0.0F)
			{
				root = 0.0F;
			}
			else
			{
				root = sqrt(in_square);
			}
			if (root != 0.0F)
			{
				out_invert_root = (real)(1.0F / root);
			}
			else
			{
				out_invert_root = 0.0F;
			}
			m_root_map[in_square] = out_invert_root;
		}
		else
		{
			out_invert_root = iterate->second;
		}
	}
assert(ok);
	return ok;
}
s32 main(s32 argc, u8 ** argv)
{
	CCommonCache_InverseSqrt invert_sqrt_cache;
	real input_number;
	real invert_sqrt;
	bool loop;
	printf("CCommonCache_InverseSqrt testbed: David Coen 041230
");
	loop = true;
	while (loop == true)
	{
		input_number = 0.0F;
		printf(" please input a number (zero to exit)
");
		scanf("%f", &input_number);
		if (input_number != 0.0F)
		{
			invert_sqrt_cache.GetInverseSqrt(input_number, invert_sqrt);
			printf(" invert square root is %f
", invert_sqrt);
		}
		else
		{
			loop = false;
		}
	}
	return 0;
}
[/code]
quote:Originally posted by davidcoen
[code]
bool CCommonCache_InverseSqrt::GetInverseSqrt(const real in_square, real & out_invert_root)
{
	TRealRootMap::const_iterator iterate;
	real root;
	bool ok;
ok = true;
	if (ok)
	{
		ok = (0.0F <= in_square);
	}
	if (ok)
	{
		iterate = m_root_map.find(in_square);
		if (iterate == m_root_map.end())
		{
			if (in_square == 0.0F)
			{
				root = 0.0F;
			}
			else
			{
				root = sqrt(in_square);
			}
			if (root != 0.0F)
			{
				out_invert_root = (real)(1.0F / root);
			}
			else
			{
				out_invert_root = 0.0F;
			}
			m_root_map[in_square] = out_invert_root;
		}
		else
		{
			out_invert_root = iterate->second;
		}
	}
assert(ok);
	return ok;
}
[/code]
A little constructive criticism. There are a few ways that I think you can improve your code.[;)]
After performing the following steps:
- remove unnecessary variables and redundant checks
- use ternary operators where appropriate
- use a tolerance value (EPSILON) when comparing floating point numbers to avoid precision errors
- a little re-ordering
- recognise that it always returns true and make the function void
- add comments!!!
The code above appears to reduce to:
[code]
void CCommonCache_InverseSqrt::GetInverseSqrt(const real in_square, real & out_invert_root)
{
    TRealRootMap::const_iterator iterate;
    // assert that a real root exists
    assert(in_square > EPSILON);
    // some comment
    iterate = m_root_map.find(in_square);
    // some comment
    if (iterate != m_root_map.end())
    {
	// some comment
	out_invert_root = iterate->second;
    }
    else // some comment
    {
	// output inverse of root
	out_invert_root = (real)(1.0F / sqrt(in_square)));
	// set inverse value of root in map
	m_root_map[in_square] = out_invert_root;
    }
}
[/code]
The EPSILON checks may be unnecessary if the "real" class (template?) handles precision checks (I wasn't sure, I usually code in C).
Update: I got rid of a ternary operator and the check that the root is valid. If in_square is greater than a well-conditioned threshold (EPSILON), the root should be valid... I think that this is a reasonable assumption...
sick...count me in! [:D]