advent-of-code/2022/5.c

220 lines
4.8 KiB
C

#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 512
#define NUM_LINES 512
#define NUM_STACKS 9
struct Stack {
int top;
char items[MAX_LINE];
};
typedef struct Stack stack;
// Push onto a stack
void push(stack *st, char crate) {
if (st->top == MAX_LINE) {
fprintf(stderr, "Stack is full\n");
} else {
st->top++;
st->items[st->top] = crate;
}
}
// Pop from a stack
char pop(stack *st) {
char c = '\0';
if (st->top == -1) {
fprintf(stderr, "Stack is empty\n");
return -1;
} else {
c = st->items[st->top];
st->items[st->top] = '\0';
st->top--;
return c;
}
}
// Prints top index, top item, and each stack
void print_crates(stack **crates) {
for (size_t i = 0; i < NUM_STACKS; i++) {
printf("\nStack %lu - Top: %d"
"\n Top Crate: %c"
"\n Crates: %s\n",
i + 1, crates[i]->top, crates[i]->items[crates[i]->top],
crates[i]->items);
fflush(stdout);
}
}
// Allocate memeory and initialize stacks of crates with their initial order
stack **crates_init() {
stack **crates = calloc(NUM_STACKS, sizeof(stack *));
if (crates == NULL) {
return NULL;
}
for (int i = 0; i < NUM_STACKS; i++) {
crates[i] = (stack *)malloc(sizeof(stack));
if (crates[i] == NULL) {
return NULL;
}
crates[i]->top = -1;
memset(crates[i]->items, 0, MAX_LINE);
}
crates[0]->top = 7;
strcpy(crates[0]->items, "PFMQWGRT");
crates[1]->top = 2;
strcpy(crates[1]->items, "HFR");
crates[2]->top = 7;
strcpy(crates[2]->items, "PZRVGHSD");
crates[3]->top = 6;
strcpy(crates[3]->items, "QHPBFWG");
crates[4]->top = 4;
strcpy(crates[4]->items, "PSMJH");
crates[5]->top = 7;
strcpy(crates[5]->items, "MZTHSRPL");
crates[6]->top = 5;
strcpy(crates[6]->items, "PTHNML");
crates[7]->top = 3;
strcpy(crates[7]->items, "FDQR");
crates[8]->top = 6;
strcpy(crates[8]->items, "DSCNLPH");
return crates;
}
// Parses moves from input file and stores in an array
void parse_moves(FILE *file, int moves[NUM_LINES][3], size_t *line_num) {
int idx = 0;
char line[MAX_LINE] = {0};
while (fgets(line, MAX_LINE, file) != NULL) {
if (line[0] != 'm') {
memset(line, 0, MAX_LINE);
continue;
}
for (size_t i = 0; i < strlen(line); i++) {
if (isdigit(line[i])) {
if (isdigit(line[i + 1])) {
char temp[2];
temp[0] = line[i];
temp[1] = line[i + 1];
moves[*line_num][idx] = atoi(temp);
i++;
} else {
moves[*line_num][idx] = atoi(&line[i]);
}
idx++;
if (idx > 2) {
*line_num += 1;
idx = 0;
}
}
}
memset(line, 0, MAX_LINE);
}
}
// Part 1 - Processes each move stored in the moves array one crate at a time
void part1_moves(stack **crates, int moves[NUM_LINES][3], size_t move_count) {
size_t idx = 0;
while (idx <= move_count) {
for (int i = 0; i < moves[idx][0]; i++) {
char c = pop(crates[moves[idx][1] - 1]);
if (c == -1) {
fprintf(stderr, "part1_moves: move num: %lu", idx);
continue;
}
push(crates[moves[idx][2] - 1], c);
}
idx++;
}
}
void crates_free(stack **crates) {
for (size_t i = 0; i < NUM_STACKS; i++) {
free(crates[i]);
}
free(crates);
}
// Part 2 - Processes the moves array multiple crates at a time
void part2_moves(stack **crates, int moves[NUM_LINES][3], size_t move_count) {
size_t idx = 0;
while (idx <= move_count) {
char c_arr[moves[idx][0]];
memset(c_arr, 0, moves[idx][0]);
for (int i = 0; i < moves[idx][0]; i++) {
c_arr[i] = pop(crates[moves[idx][1] - 1]);
if (c_arr[i] == -1) {
fprintf(stderr, "part2_moves: move num: %lu", idx);
continue;
}
}
for (int j = moves[idx][0] - 1; j >= 0; j--) {
push(crates[moves[idx][2] - 1], c_arr[j]);
}
idx++;
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "USAGE: %s input_file\n", argv[0]);
return 1;
}
FILE *file = fopen(argv[1], "r");
if (!file) {
perror("fopen");
return 1;
}
size_t move_count = 0;
int moves[NUM_LINES][3] = {0};
stack **crates = crates_init();
if (crates == NULL) {
fprintf(stderr, "Part 2: unable to allocate memory for crates\n");
fclose(file);
return 1;
}
printf("\n--- PART 1 ---\n");
parse_moves(file, moves, &move_count);
part1_moves(crates, moves, move_count);
print_crates(crates);
printf("\n--- PART 2 ---\n");
crates_free(crates);
crates = crates_init();
if (crates == NULL) {
fprintf(stderr, "Part 2: unable to allocate memory for crates\n");
fclose(file);
return 1;
}
part2_moves(crates, moves, move_count);
print_crates(crates);
crates_free(crates);
fclose(file);
return 0;
}