#include #include #include #include #include #include std::pair getStartingPositions(const std::string &file_name) { std::ifstream file(file_name); std::pair result; std::string str; std::string tmp = ""; std::getline(file, str); std::stringstream ss(str); for(int i = 0; i < 4; i++) { ss >> tmp; } ss >> result.first; std::getline(file, str); ss = std::stringstream(str); for(int i = 0; i < 4; i++) { ss >> tmp; } ss >> result.second; return result; } int getDeterministicDieRolls(int ¤t_state) { int result = 0; for(int i = 0; i < 3; i++) { if(current_state == 100) { current_state = 1; } else { current_state++; } result += current_state; } return result; } void playerAddDieRolls(std::pair &player, int die_roll) { player.first += die_roll; player.first %= 10; if(player.first == 0) { player.first = 10; } player.second += player.first; } int part1(const std::pair &starting_positions) { std::pair player_1; player_1.first = starting_positions.first; // position player_1.second = 0; // score std::pair player_2; player_2.first = starting_positions.second; // position player_2.second = 0; // score int die = 100; int die_rolls = 0; while(player_2.second < 1000) { playerAddDieRolls(player_1, getDeterministicDieRolls(die)); die_rolls += 3; if(player_1.second >= 1000) { break; } playerAddDieRolls(player_2, getDeterministicDieRolls(die)); die_rolls += 3; } int loser_score = player_1.second < player_2.second ? player_1.second : player_2.second; return loser_score * die_rolls; } int getScore(int pos, int roll) { auto score = pos + roll; score %= 10; if(score == 0) { score = 10; } return score; } uint64_t part2(const std::pair &starting_positions) { uint64_t player_cache[21][21][10][10][2]; // [score_p1][score_p2][position_p1][position_p2] = number of wins for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { for(int k = 0; k < 21; k++) { player_cache[20][k][i][j][0] = 27; // player 1 always goes first, so with score 20 they can't lose, 3*3*3 possible dice rolls player_cache[20][k][i][j][1] = 0; } } } for(int a = 0; a <= 19; a++) { for(int b = 0; b < 21; b++) { for(int c = 0; c < 10; c++) { for(int d = 0; d < 10; d++) { player_cache[a][b][c][d][0] = 0; player_cache[a][b][c][d][1] = 0; } } } } for(int score_1 = 19; score_1 >= 0; score_1--) { for(int score_2 = 20; score_2 >= 0; score_2--) { for(int pos_1 = 1; pos_1 <= 10; pos_1++) { for(int pos_2 = 1; pos_2 <= 10; pos_2++) { for(int dice_1_1 = 1; dice_1_1 <= 3; dice_1_1++) { for(int dice_1_2 = 1; dice_1_2 <= 3; dice_1_2++) { for(int dice_1_3 = 1; dice_1_3 <= 3; dice_1_3++) { auto next_pos_1 = getScore(pos_1, dice_1_1 + dice_1_2 + dice_1_3); auto next_score_1 = score_1 + next_pos_1; if(next_score_1 >= 21) { player_cache[score_1][score_2][pos_1 - 1][pos_2 - 1][0] += 1; continue; } for(int dice_2_1 = 1; dice_2_1 <= 3; dice_2_1++) { for(int dice_2_2 = 1; dice_2_2 <= 3; dice_2_2++) { for(int dice_2_3 = 1; dice_2_3 <= 3; dice_2_3++) { auto next_pos_2 = getScore(pos_2, dice_2_1 + dice_2_2 + dice_2_3); auto next_score_2 = score_2 + next_pos_2; if(next_score_1 < 21 && next_score_2 < 21) { player_cache[score_1][score_2][pos_1 - 1][pos_2 - 1][0] += player_cache[next_score_1][next_score_2][next_pos_1 - 1][next_pos_2 - 1][0]; player_cache[score_1][score_2][pos_1 - 1][pos_2 - 1][1] += player_cache[next_score_1][next_score_2][next_pos_1 - 1][next_pos_2 - 1][1]; } else if(next_score_1 < 21 && next_score_2 >= 21) { player_cache[score_1][score_2][pos_1 - 1][pos_2 - 1][1] += 1; } } } } } } } } } } } auto player_1_wins = player_cache[0][0][starting_positions.first - 1][starting_positions.second - 1][0]; auto player_2_wins = player_cache[0][0][starting_positions.first - 1][starting_positions.second - 1][1]; return player_1_wins > player_2_wins ? player_1_wins : player_2_wins; } int main(int argc, char **argv) { if (argc < 2) { std::cerr << "You must provide input file!" << std::endl; return 1; } auto starting_positions = getStartingPositions(argv[1]); std::cout << "Result with deterministic die is \033[91;1m" << part1(starting_positions) << "\033[0m." << std::endl; std::cout << "Result with quantum die is \033[91;1m" << part2(starting_positions) << "\033[0m." << std::endl; return 0; }