summaryrefslogtreecommitdiff
path: root/02.c
diff options
context:
space:
mode:
Diffstat (limited to '02.c')
-rw-r--r--02.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/02.c b/02.c
new file mode 100644
index 0000000..8ca0423
--- /dev/null
+++ b/02.c
@@ -0,0 +1,165 @@
+#include "input.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <err.h>
+
+#define INPUT "input/02.txt"
+#define EXPECTED1 13221L
+#define EXPECTED2 13131L
+
+enum draw {
+ rock = 1,
+ paper = 2,
+ scissors = 3,
+};
+
+struct round_p1 {
+ enum draw opponent;
+ enum draw me;
+};
+
+int compute_round_score_p1(struct round_p1* round) {
+ int score = (int) round->me;
+ enum draw opponent = round->opponent;
+ enum draw me = round->me;
+ if((opponent == rock && me == paper) || (opponent == paper && me == scissors) || (opponent == scissors && me == rock))
+ score += 6; // win
+ else if(opponent == me)
+ score += 3; // draw
+ // loss is 0
+ return score;
+}
+
+void parse_round_p1(struct round_p1* round, char* round_str) {
+ switch(round_str[0]) {
+ case 'A':
+ round->opponent = rock;
+ break;
+ case 'B':
+ round->opponent = paper;
+ break;
+ case 'C':
+ round->opponent = scissors;
+ break;
+ default:
+ err(2, "unknown opponent choice %c", round_str[0]);
+ }
+ switch(round_str[2]) {
+ case 'X':
+ round->me = rock;
+ break;
+ case 'Y':
+ round->me = paper;
+ break;
+ case 'Z':
+ round->me = scissors;
+ break;
+ default:
+ err(2, "unknown me choice %c", round_str[2]);
+ }
+}
+
+void part1(struct input_str* input) {
+ // compute max calories
+ long score = 0;
+ struct round_p1 r;
+ for(size_t i = 0; i < input->line_count; i++) {
+ parse_round_p1(&r, input->lines[i]);
+ int round_score = compute_round_score_p1(&r);
+ score += round_score;
+ }
+
+ CHECK(score, EXPECTED1)
+}
+
+enum round_result {
+ loss = 0,
+ draw = 3,
+ win = 6,
+};
+
+struct round_p2 {
+ enum draw opponent;
+ enum round_result result;
+};
+
+int compute_round_score_p2(struct round_p2* round) {
+ enum draw opponent = round->opponent;
+ enum round_result result = round->result;
+ enum draw me;
+ switch(result) {
+ case loss:
+ if(opponent == rock)
+ me = scissors;
+ else
+ me = (enum draw) ((int) opponent - 1);
+ break;
+ case draw:
+ me = opponent;
+ break;
+ case win:
+ if(opponent == scissors)
+ me = rock;
+ else
+ me = (enum draw) ((int) opponent + 1);
+ break;
+ }
+ return (int) me + (int) result;
+}
+
+void parse_round_p2(struct round_p2* round, char* round_str) {
+ switch(round_str[0]) {
+ case 'A':
+ round->opponent = rock;
+ break;
+ case 'B':
+ round->opponent = paper;
+ break;
+ case 'C':
+ round->opponent = scissors;
+ break;
+ default:
+ err(2, "unknown opponent choice %c", round_str[0]);
+ }
+ switch(round_str[2]) {
+ case 'X':
+ round->result = loss;
+ break;
+ case 'Y':
+ round->result = draw;
+ break;
+ case 'Z':
+ round->result = win;
+ break;
+ default:
+ err(2, "unknown expected result %c", round_str[2]);
+ }
+}
+
+void part2(struct input_str* input) {
+ // compute max calories
+ long score = 0;
+ struct round_p2 r;
+ for(size_t i = 0; i < input->line_count; i++) {
+ parse_round_p2(&r, input->lines[i]);
+ int round_score = compute_round_score_p2(&r);
+ score += round_score;
+ }
+
+ CHECK(score, EXPECTED2)
+}
+
+int main() {
+ // read input
+ struct input_str input;
+ input_str_read(&input, INPUT);
+
+ // do stuff
+ part1(&input);
+ part2(&input);
+
+ // cleanup & exit
+ input_str_free(&input);
+ return 0;
+}