Day 21 solutions

This commit is contained in:
Peter 2021-12-21 18:22:11 +08:00
parent de364fabff
commit f1fedda1ac
2 changed files with 158 additions and 0 deletions

71
21/21-1.c Normal file
View File

@ -0,0 +1,71 @@
#include <stdlib.h>
#include <stdio.h>
#include "../check_alloc.h"
#define P1_START 4
#define P2_START 8
#define MIN(x, y) ((x) < (y) ? (x) : (y))
typedef struct
{
int position;
int score;
} PLAYER;
PLAYER *new_player(int initial_position)
{
PLAYER *p_player = calloc(1, sizeof(PLAYER));
CHECK_ALLOC(p_player);
p_player->position = initial_position;
return p_player;
}
void move_position(PLAYER *player, int move)
{
int next_pos = (player->position + move) % 10;
player->position = next_pos == 0 ? 10 : next_pos;
player->score += player->position;
}
typedef struct
{
int value;
int rolls;
} DICE;
#define NEW_DICE() calloc(1, sizeof(DICE))
int roll_dice(DICE *dice)
{
dice->value = dice->value % 100 + 1;
dice->rolls++;
return dice->value;
}
int roll_3(DICE *dice)
{
int value = roll_dice(dice);
value += roll_dice(dice);
value += roll_dice(dice);
return value;
}
int main(int argc, char const *argv[])
{
DICE *p_dice = NEW_DICE();
PLAYER *p_p1 = new_player(P1_START);
PLAYER *p_p2 = new_player(P2_START);
while (1)
{
int value = roll_3(p_dice);
move_position(p_p1, value);
if (p_p1->score >= 1000)
break;
value = roll_3(p_dice);
move_position(p_p2, value);
if (p_p2->score >= 1000)
break;
}
printf("END RESULT %d\n", p_dice->rolls * MIN(p_p1->score, p_p2->score));
return 0;
}

87
21/21-2.c Normal file
View File

@ -0,0 +1,87 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// I needed some help for this one. Couldn't be bothered to implement a cache etc.
// I calculated the DICE array, but struggled getting the total wins. Instead of
// multiplying as I went up, I tried to multiply when a result occurred but
// obviously this was the wrong way to think about it.
#define P1_START 6
#define P2_START 1
typedef struct
{
int position;
int score;
} PLAYER;
PLAYER clone_player(PLAYER player)
{
PLAYER new_player = {player.position, player.score};
return new_player;
}
void move_position(PLAYER *player, int move)
{
int next_pos = (player->position + move) % 10;
player->position = next_pos == 0 ? 10 : next_pos;
player->score += player->position;
}
typedef unsigned long long NUMBER;
typedef enum
{
P1,
P2
} TURN;
typedef struct
{
NUMBER p1_wins;
NUMBER p2_wins;
} SCORE;
// PRE-CALCULATED OCCURRENCES OF TOTALS FOR ROLLING 3 DICE
int DICE[] = {1, 3, 6, 7, 6, 3, 1};
// repeat TRACKS THE AMOUNT OF POSSIBLE COMBINATIONS LEADING TO A WIN,
// THIS REDUCES THE SEARCH AREA GREATLY BY IGNORING PATHS TO THE SAME WIN.
void iter_rolls(PLAYER p1, PLAYER p2, TURN turn, NUMBER repeat, SCORE *score)
{
for (int i = 0; i < 7; i++)
{
int value = i + 3;
PLAYER tmp;
if (turn == P1)
tmp = clone_player(p1);
else
tmp = clone_player(p2);
move_position(&tmp, value);
if (tmp.score < 21)
{
if (turn == P1)
iter_rolls(tmp, p2, P2, repeat * DICE[i], score);
else
iter_rolls(p1, tmp, P1, repeat * DICE[i], score);
}
else
{
if (turn == P1)
score->p1_wins += repeat * DICE[i];
else
score->p2_wins += repeat * DICE[i];
}
}
}
int main(int argc, char const *argv[])
{
PLAYER p1 = {P1_START, 0};
PLAYER p2 = {P2_START, 0};
SCORE *p_score = malloc(sizeof(SCORE));
iter_rolls(p1, p2, P1, 1, p_score);
printf("WINNER SCORE %llu\n", p_score->p1_wins > p_score->p2_wins ? p_score->p1_wins : p_score->p2_wins);
return 0;
}