std::vector
of pair
s (or struct
s) of (guess
, correct
).
Increment correct
, (binary?) search for right spot, slide elements between correct guess and new spot over 1. Possibly sliding in "clumps" will be faster than sliding them one at a time, but maybe not.
std::vector< std::pair< int, std::size_t > > guess_buffer;
template<typename TryGuess>
bool Try( guess_buffer& guesses, TryGuess const& try_guess ) {
for (guess_buffer::iterator it = guesses.begin(); it != guesses.end(); ++it) {
if (try_guess( it->first)) {
it->second++;
while (it != guesses.begin()) {
--it;
if (it->second < (it+1)->second) {
std::swap( *it, *(it+1) );
} else {
return true;
}
}
return true;
}
}
return false;
}
Given that you have iterated from start to here, the search and slide will be fast enough. Locality and speed of iteration will make up for slide costs of two ints.
If you want less code, multi map from count to guess, iterate remembering iterator, if successful remove via iterator, increment count, and reinsert. Will probably be slower.
template<typename X>
struct reverse_order {
template<typename T, typename U>
bool operator()( T const& t, U const& u ) const {
return std::less<X>()( u, t );
}
};
typedef std::multi_map< std::size_t, int, reverse_order<std::size_t> > guess_map;
template<typename TryGuess>
bool Try( guess_map& guesses, TryGuess const& try_guess ) {
for( guess_map::iterator it = guesses.begin(); it != guesses.end(); ++it ) {
if( try_guess( it->second ) )
{
std::pair<std::size_t, int> modify = *it;
guesses.erase(it);
modify.first++;
guesses.insert(modify);
return true;
}
}
return false;
}