mirror of
https://github.com/peter-tanner/advent-of-code-2021.git
synced 2024-11-30 11:10:20 +08:00
Day 21 solutions
This commit is contained in:
parent
de364fabff
commit
f1fedda1ac
71
21/21-1.c
Normal file
71
21/21-1.c
Normal 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
87
21/21-2.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user