diff --git a/solver.cpp b/solver.cpp index 1d50b2d..7499145 100644 --- a/solver.cpp +++ b/solver.cpp @@ -131,9 +131,9 @@ void Game::all_are_here(vector guess) { // For remembering guesses with their responses -Historic_guess::Historic_guess(vector p_guess, vector p_response) { - guess = p_guess; - response = p_response; +Historic_guess::Historic_guess(vector _guess, Response _response) { + guess = _guess; + response = _response; } @@ -144,7 +144,7 @@ Solver::Solver(int p_N, int p_M) : N(p_N), M(p_M), known({p_N, p_M}) {} bool Solver::all_are_consistent(vector supposed_sequence) { for(auto hist : history) { auto response = validate(supposed_sequence, hist.guess); - if(response[0] != hist.response[0] || response[1] != hist.response[1]) + if(response.somewhere != hist.response.somewhere || response.correct != hist.response.correct) return false; } return true; @@ -167,10 +167,33 @@ vector Solver::brute_force(vector> *possibilities, vector } return r; } + +int Solver::get_weight(vector guess) { + if(!all_are_consistent(guess)) + return -1; + + // Get weight + for(auto hist : history) { + // TODO get worst-case weight + } + + return 1; +} // Now featuring: minimax pick -vector Solver::minimax(vector> *possibilities, vector *chosen, int index) { - // TODO - return vector(N, -1); +Weighed_guess Solver::minimax(vector> *possibilities, vector *chosen, int index) { + // If complete guess, get weight and return + if(index == N) + return {get_weight(*chosen), *chosen}; + // Get max-weighted child + Weighed_guess r = {-2, {}}; + for(int col : (*possibilities)[index]) { + chosen->push_back(col); + Weighed_guess r2 = minimax(possibilities, chosen, index+1); + if(r2.weight > r.weight || r.weight == -2) + r = r2; + chosen->pop_back(); + } + return r; } // Guessing @@ -201,7 +224,7 @@ Historic_guess Solver::clean(Historic_guess hist) { continue; if(known.final_color(n) == hist.guess[n]) { hist.guess[n] = -1; - hist.response[1] -= 1; + hist.response.correct -= 1; already_used_in_cleaning[n] = 1; } } @@ -215,7 +238,7 @@ Historic_guess Solver::clean(Historic_guess hist) { continue; if(known.final_color(i) == hist.guess[n]) { hist.guess[n] = -1; - hist.response[0] -= 1; + hist.response.somewhere -= 1; already_used_in_cleaning[i] = 1; break; } @@ -250,14 +273,14 @@ vector Solver::extract_info(Historic_guess hist) { possible_count++; // None of these colors are there - if(hist.response[0] == 0 && hist.response[1] == 0) { + if(hist.response.somewhere == 0 && hist.response.correct == 0) { known.empty(hist.guess); something_to_learn = false; learned_something = true; } // None at the right spot - else if(response[1] == 0) { + else if(response.correct == 0) { if(possible_count > 0) { known.not_here(guess); learned_something = true; @@ -265,14 +288,14 @@ vector Solver::extract_info(Historic_guess hist) { } // At least only on the right spot - else if(response[0] == 0) { + else if(response.somewhere == 0) { // Only colors that can be on these positions are left - if(response[1] == possible_count) { + if(response.correct == possible_count) { known.here(guess); something_to_learn = false; learned_something = true; } - else if(hist.response[0] == 0){ + else if(hist.response.somewhere == 0){ if(known.if_not_here_then_nowhere(hist.guess)) { learned_something = true; } @@ -282,7 +305,7 @@ vector Solver::extract_info(Historic_guess hist) { // Nonzero / nonzero else { // Only colors that can be on these positions are left - if(response[1] == possible_count) { + if(response.correct == possible_count) { known.here(guess); learned_something = true; } @@ -290,16 +313,16 @@ vector Solver::extract_info(Historic_guess hist) { return {something_to_learn, learned_something}; } -void Solver::learn(vector p_guess, vector p_response) { +void Solver::learn(vector _guess, Response _response) { // All guessed colors are in the sequence - if(p_response[0] + p_response[1] == N) - known.all_are_here(p_guess); + if(_response.somewhere + _response.correct == N) + known.all_are_here(_guess); - if(p_guess[0] == -1) + if(_guess[0] == -1) return; // Write to history - history.push_back({p_guess, p_response}); + history.push_back({_guess, _response}); // Repeat multiple times, if new information turned out bool learned_something = true; diff --git a/solver.hpp b/solver.hpp index 78f6cd2..f422e66 100644 --- a/solver.hpp +++ b/solver.hpp @@ -38,8 +38,17 @@ public: // For remembering guesses with their responses struct Historic_guess { - vector guess, response; - Historic_guess(vector p_guess, vector p_response); + vector guess; + Response response; + Historic_guess(vector _guess, Response _response); +}; + +// For deciding the best guess +struct Weighed_guess { + int weight; + vector guess; + Weighed_guess(int pw, vector pg) : weight(pw), guess(pg) {} + Weighed_guess() {} }; // Solving the game @@ -52,7 +61,7 @@ public: vector guess(); void print(); - void learn(vector guess, vector response); + void learn(vector guess, Response response); private: Historic_guess clean(Historic_guess hist); @@ -60,5 +69,7 @@ private: bool all_are_consistent(vector supposed_sequence); vector brute_force(vector> *possibilities, vector *chosen, int index); - vector minimax(vector> *possibilities, vector *chosen, int index); + + int get_weight(vector guess); + Weighed_guess minimax(vector> *possibilities, vector *chosen, int index); };