/* PPP5
12. Implement a little guessing game called (for some obscure 
reason) “Bulls and Cows.” The program has a vector of four 
different integers in the range 0 to 9 (e.g., 1234 but not 1122) 
and it is the user’s task to discover those numbers by repeated 
guesses. Say the number to be guessed is 1234 and the user 
guesses 1359; the response should be “1 bull and 1 cow” because
the user got one digit (1) right and in the right position (a 
bull) and one digit (3) right but in the wrong position (a cow). 
The guessing continues until the user gets four bulls, that is, 
has the four digits correct and in the correct order.
*/

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <utility>
using namespace std;

constexpr int rackSize = 4;

vector<int> initialize();
bool in(vector<int> v, int candidate);
vector<int> getGuess();
pair<int, int> scoreGuess(vector<int>, vector<int>);

int main() {
	srand(time(0));
	char ans{ 'y' };
	
	//for (int i : secretCode) cout << i;
	// score.first == number correct and in the right place
	// score.second == number correct in the wrong place
	pair<int, int> score = make_pair(0, 0);
	do {
		score = make_pair(0, 0);
		vector<int> secretCode = initialize();
		int guesses = 0;
		vector<int> guess(rackSize);
		while (score.first != rackSize) {
			guess = getGuess();
			++guesses;
			//cout << "You guessed ";
			//for (int i : guess) cout << i;
			//cout << endl;
			score = scoreGuess(guess, secretCode);
			cout << "bulls: " << score.first << " cows: "
				<< score.second << "\n";
		}
		cout << "CONGRATULATIONS!! You guessed correctly in "
			<< guesses << " guesses.\n";
		cout << "Do you want to play again?(y/n): ";
		cin >> ans;
	} while (ans == 'y');
}

bool in(vector<int> v, int candidate) {
	for (int k = 0; k < v.size(); ++k)
		if (v[k] == candidate) return true;
	return false;
}

vector<int> initialize() {
	vector<int> v;
	v.push_back(rand() % 10);
	int candidate;
	for (int i = 1; i < rackSize; ++i) {
		do {
			candidate = rand() % 10;
		} while (in(v, candidate));
		v.push_back(candidate);
	}
	return v;
}

vector<int> getGuess() {
	cout << "Enter your guess (4 digits): ";
	int g{ 0 };
	vector<int> guess;
	for (int i = 0; i < rackSize; ++i) {
		do {
			cin >> g;
			if (g < 0 || g > 9)
				cout << "Enter single digits, please.  Try again.\n";
		} while (!(g > -1 && g < 10));
		guess.push_back(g);
	}
	return guess;
}

pair<int, int> scoreGuess(vector<int> g, vector<int> s) {
	pair<int, int> score(0,0);
	for (int i = 0; i < rackSize; ++i) {
		if (g[i] == s[i]) ++score.first;
		for (int j = 0; j < rackSize; ++j)
			if (g[i] == s[j] && i != j)
				++score.second;
	}
	return score;
}