TITLE: Using the STL - Mastermind (Newsgroups: comp.lang.c++.moderated, 24 Aug 98) AUTHOR: herbs@cntc.com (Herb Sutter) .--------------------------------------------------------------------. | Guru of the Week problems and solutions are posted regularly on | | news:comp.lang.c++.moderated. For past problems and solutions | | see the GotW archive at http://www.cntc.com. | | Is there a topic you'd like to see covered? mailto:herbs@cntc.com | `--------------------------------------------------------------------' _______________________________________________________ GotW #41: Using the Standard Library Difficulty: 9 / 10 _______________________________________________________ >Write a program that plays simplified Mastermind, using >only Standard Library containers, algorithms and >streams. The challenge is to use as few "if"s, >"while"s, "for"s and other builtin constructs as >possible, and have the program take up as few >statements as possible. The solution presented below is not the only right answer. In fact, it may not even be the cleanest, and it's relatively unimaginative. Each of the solutions that were posted to the newsgroup have aspects that I like better (such as creative use of count<> and inner_product<>) and aspects that I don't (such as randomizing the combination poorly and hardcoding the peg colours within the algorithm). All of the solutions, including this one, do insufficient error checking. This solution avoids hardcoding peg-colour and combination-size restrictions within the algorithm; peg colours can be extended simply by changing the 'colors' string, and the combination length can be changed simply by changing the '4' literal. It does use one "while," however, which can replaced (at further cost of clarity) by "find_if( istream_iterator(cin), ... );". string colors("BGR"), comb(4, '.'), l(comb), guess; typedef map M; struct Color { Color(M& cm, M& gm, int& color) : cm_(cm), gm_(gm), color_(color=0) {} void operator()( char c ) { color_ += min( cm_[c], gm_[c] ); } M &cm_, &gm_; int& color_; }; struct Count { Count(int& color, int& exact) : color_(color), exact_(exact=0) { } char operator()( char c, char g ) { return ++cm_[c], ++gm_[toupper(g)], exact_ += c==toupper(g), '.';} ~Count() { for_each( colors.begin(), colors.end(), Color(cm_,gm_,color_) ); } M cm_, gm_; int &color_, &exact_; }; char ChoosePeg() { return colors[rand() % colors.size()]; } int main() { int color, exact = 0; srand( time(0) ), generate( comb.begin(), comb.end(), ChoosePeg ); while( exact < comb.length() ) { cout << "\n\nguess--> ", cin >> guess; transform( comb.begin(), comb.end(), guess.begin(), l.begin(), Count( color, exact ) ); cout << color << ' ' << exact; } cout << " - solved!\n"; }