21
This commit is contained in:
parent
7e5b3cf6cf
commit
571d2a9530
22
21/CMakeLists.txt
Normal file
22
21/CMakeLists.txt
Normal file
@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
enable_language(CXX)
|
||||
|
||||
project(AoC21)
|
||||
|
||||
if(APPLE)
|
||||
include_directories(/usr/local/include)
|
||||
link_directories(/usr/local/lib)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_executable(${CMAKE_PROJECT_NAME} WIN32)
|
||||
else()
|
||||
add_executable(${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
target_sources(${CMAKE_PROJECT_NAME}
|
||||
PRIVATE main.cpp
|
||||
)
|
2
21/input
Normal file
2
21/input
Normal file
@ -0,0 +1,2 @@
|
||||
Player 1 starting position: 7
|
||||
Player 2 starting position: 1
|
152
21/main.cpp
Normal file
152
21/main.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
std::pair<int, int> getStartingPositions(const std::string &file_name) {
|
||||
std::ifstream file(file_name);
|
||||
std::pair<int, int> 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<short, uint64_t> &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<int, int> &starting_positions) {
|
||||
std::pair<short, uint64_t> player_1;
|
||||
player_1.first = starting_positions.first; // position
|
||||
player_1.second = 0; // score
|
||||
std::pair<short, uint64_t> 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<int, int> &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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user