Day8 C
This commit is contained in:
BIN
day8/c/day8
Executable file
BIN
day8/c/day8
Executable file
Binary file not shown.
228
day8/c/day8.c
Normal file
228
day8/c/day8.c
Normal file
@@ -0,0 +1,228 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define LINE_MAX_LENGTH 512
|
||||
#define MAX_INSTRUCTIONS 512
|
||||
#define MAX_NODES 2048
|
||||
#define MAX_HISTORY 32*1024
|
||||
|
||||
enum direction {
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
typedef struct node {
|
||||
char name[3];
|
||||
char left_name[3];
|
||||
char right_name[3];
|
||||
struct node *left;
|
||||
struct node *right;
|
||||
} node_t;
|
||||
|
||||
typedef struct h {
|
||||
node_t *node;
|
||||
unsigned long idx;
|
||||
} history_t;
|
||||
|
||||
typedef struct period {
|
||||
unsigned long offset;
|
||||
unsigned long period;
|
||||
unsigned long z[10];
|
||||
int z_num;
|
||||
} period_t;
|
||||
|
||||
void connect_nodes(node_t nodes[], int nodes_num);
|
||||
int all_ending_with(char endchar, node_t *nodes[], int nodes_num);
|
||||
|
||||
int main() {
|
||||
char *p, *buf, c;
|
||||
|
||||
int first = 1, instructions_num = 0;
|
||||
enum direction instructions[MAX_INSTRUCTIONS];
|
||||
|
||||
int nodes_num = 0;
|
||||
node_t nodes[MAX_NODES];
|
||||
|
||||
buf = (char *)malloc(LINE_MAX_LENGTH);
|
||||
memset(buf, 0, LINE_MAX_LENGTH);
|
||||
p = buf;
|
||||
|
||||
while ((c = getchar()) != EOF) {
|
||||
*p++ = c;
|
||||
if (c == '\n') {
|
||||
if (first && buf[0] == '\n') {
|
||||
first = 0;
|
||||
} else if (first) {
|
||||
p = buf;
|
||||
while (*p != '\n') {
|
||||
instructions[instructions_num] = *p == 'L' ? LEFT : RIGHT;
|
||||
instructions_num++;
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
sscanf(buf, "%c%c%c = (%c%c%c, %c%c%c)", &nodes[nodes_num].name[0], &nodes[nodes_num].name[1], &nodes[nodes_num].name[2], &nodes[nodes_num].left_name[0], &nodes[nodes_num].left_name[1], &nodes[nodes_num].left_name[2], &nodes[nodes_num].right_name[0], &nodes[nodes_num].right_name[1], &nodes[nodes_num].right_name[2]);
|
||||
nodes_num++;
|
||||
}
|
||||
|
||||
memset(buf, 0, LINE_MAX_LENGTH);
|
||||
p = buf;
|
||||
}
|
||||
}
|
||||
|
||||
connect_nodes(nodes, nodes_num);
|
||||
|
||||
unsigned long step_counter = 0;
|
||||
node_t *curr;
|
||||
#ifndef ONLY_PART2
|
||||
// Find start node
|
||||
for (int i = 0; i < nodes_num; i++) {
|
||||
if (nodes[i].name[0] == 'A' && nodes[i].name[1] == 'A' && nodes[i].name[2] == 'A') {
|
||||
curr = &nodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (curr->name[0] != 'Z' || curr->name[1] != 'Z' || curr->name[2] != 'Z') {
|
||||
switch (instructions[step_counter % instructions_num]) {
|
||||
case LEFT:
|
||||
curr = curr->left;
|
||||
break;
|
||||
case RIGHT:
|
||||
curr = curr->right;
|
||||
break;
|
||||
}
|
||||
|
||||
step_counter++;
|
||||
}
|
||||
|
||||
printf("%lu\n", step_counter);
|
||||
#endif
|
||||
|
||||
// Part2
|
||||
node_t *current_nodes[MAX_NODES];
|
||||
int current_nodes_num = 0;
|
||||
|
||||
// Search all nodes ending with 'A'
|
||||
for (int i = 0; i < nodes_num; i++) {
|
||||
if (nodes[i].name[2] == 'A') {
|
||||
current_nodes[current_nodes_num] = &nodes[i];
|
||||
current_nodes_num++;
|
||||
}
|
||||
}
|
||||
|
||||
period_t periods[MAX_NODES];
|
||||
|
||||
for (int i = 0; i < current_nodes_num; i++) {
|
||||
history_t history[MAX_HISTORY];
|
||||
int history_num = 0;
|
||||
|
||||
step_counter = 0;
|
||||
int found = 0;
|
||||
curr = current_nodes[i];
|
||||
|
||||
while (!found) {
|
||||
history[history_num].node = curr;
|
||||
history[history_num].idx = step_counter % instructions_num;
|
||||
history_num++;
|
||||
|
||||
switch (instructions[step_counter % instructions_num]) {
|
||||
case LEFT:
|
||||
curr = curr->left;
|
||||
break;
|
||||
case RIGHT:
|
||||
curr = curr->right;
|
||||
break;
|
||||
}
|
||||
|
||||
step_counter++;
|
||||
for (int j = 0; j < history_num; j++) {
|
||||
if (history[j].node == curr && step_counter % instructions_num == history[j].idx) {
|
||||
found = 1;
|
||||
periods[i].offset = j;
|
||||
periods[i].period = history_num - j;
|
||||
|
||||
periods[i].z_num = 0;
|
||||
for (int k = periods[i].offset; k < history_num; k++) {
|
||||
if (history[k].node->name[2] == 'Z') {
|
||||
periods[i].z[periods[i].z_num] = k - periods[i].offset;
|
||||
periods[i].z_num++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long ref;
|
||||
int found = 0;
|
||||
step_counter = periods[0].offset;
|
||||
while (!found) {
|
||||
for (int i = 0; i < periods[0].z_num; i++) {
|
||||
found = 1;
|
||||
ref = step_counter + periods[0].z[i];
|
||||
for (int j = 0; j < current_nodes_num; j++) {
|
||||
int found2 = 0;
|
||||
for (int k = 0; k < periods[j].z_num; k++) {
|
||||
if ((ref - periods[j].offset) % periods[j].period == periods[j].z[k]) {
|
||||
found2 = 1;
|
||||
}
|
||||
}
|
||||
if (!found2) {
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
step_counter += periods[0].period;
|
||||
}
|
||||
|
||||
printf("%lu\n", ref);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void connect_nodes(node_t nodes[], int nodes_num) {
|
||||
for (int i = 0; i < nodes_num; i++) {
|
||||
// Left
|
||||
for (int j = 0; j < nodes_num; j++) {
|
||||
int found = 1;
|
||||
for (int k = 0; k < 3; k++) {
|
||||
if (nodes[i].left_name[k] != nodes[j].name[k]) {
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
nodes[i].left = &nodes[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Right
|
||||
for (int j = 0; j < nodes_num; j++) {
|
||||
int found = 1;
|
||||
for (int k = 0; k < 3; k++) {
|
||||
if (nodes[i].right_name[k] != nodes[j].name[k]) {
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
nodes[i].right = &nodes[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int all_ending_with(char endchar, node_t *nodes[], int nodes_num) {
|
||||
for (int i = 0; i < nodes_num; i++) {
|
||||
if (nodes[i]->name[2] != endchar) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user