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<string>(cin),
... );".
string colors("BGR"), comb(4, '.'), l(comb), guess;
typedef map<int,int> 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";
}
---
Herb Sutter (mailto:he...@cntc.com)
Current Network Technologies Corp 2695 North Sheridan Way, Suite 150
www.cntc.com www.peerdirect.com Mississauga Ontario Canada L5K 2N6
[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]