From 5b8fcd4f166784bb43b09ef025b398875d13af5c Mon Sep 17 00:00:00 2001 From: Akuli Date: Sun, 5 Jan 2025 12:06:06 +0200 Subject: [PATCH] AoC 2024 day 23 (#544) --- examples/aoc2024/day23/part1.jou | 89 ++++++++++++++++ examples/aoc2024/day23/part2.jou | 140 +++++++++++++++++++++++++ examples/aoc2024/day23/sampleinput.txt | 32 ++++++ 3 files changed, 261 insertions(+) create mode 100644 examples/aoc2024/day23/part1.jou create mode 100644 examples/aoc2024/day23/part2.jou create mode 100644 examples/aoc2024/day23/sampleinput.txt diff --git a/examples/aoc2024/day23/part1.jou b/examples/aoc2024/day23/part1.jou new file mode 100644 index 00000000..ec4f23c7 --- /dev/null +++ b/examples/aoc2024/day23/part1.jou @@ -0,0 +1,89 @@ +import "stdlib/str.jou" +import "stdlib/mem.jou" +import "stdlib/io.jou" + + +class Computer: + name: byte[3] + connections: void*[100] # TODO: should be Computer*[100], can't be due to compiler bug + + def connect(self, other: Computer*) -> None: + assert other != NULL + + for i = 0; i < sizeof(self->connections)/sizeof(self->connections[0]); i++: + if self->connections[i] == NULL: + self->connections[i] = other + return + + # array is full + assert False + + def is_connected(self, other: Computer*) -> bool: + for i = 0; i < sizeof(self->connections)/sizeof(self->connections[0]); i++: + if self->connections[i] == other: + return True + return False + + +def find_or_create_computer(computers: Computer*, ncomputers: int*, name: byte*) -> Computer*: + for i = 0; i < *ncomputers; i++: + if strcmp(computers[i].name, name) == 0: + return &computers[i] + + c = &computers[*ncomputers] + assert strlen(name) == 2 + strcpy(c->name, name) + memset(c->connections, 0, sizeof(c->connections)) + + ++*ncomputers + return c + + +def main() -> int: + computers: Computer* = malloc(sizeof(computers[0]) * 5000) + assert computers != NULL + ncomputers = 0 + + f = fopen("sampleinput.txt", "r") + assert f != NULL + name1: byte[3] + name2: byte[3] + + while fscanf(f, "%2s-%2s\n", name1, name2) == 2: + assert ncomputers < 5000 + c1 = find_or_create_computer(computers, &ncomputers, name1) + assert ncomputers < 5000 + c2 = find_or_create_computer(computers, &ncomputers, name2) + c1->connect(c2) + c2->connect(c1) + + fclose(f) + printf("Got %d computers\n", ncomputers) # Output: Got 16 computers + + n = 0 + for i = 0; i < ncomputers; i++: + for j = i+1; j < ncomputers; j++: + if i == j or not computers[i].is_connected(&computers[j]): + continue + + for k = j+1; k < ncomputers; k++: + if ( + k == i + or k == j + or not computers[k].is_connected(&computers[i]) + or not computers[k].is_connected(&computers[j]) + ): + continue + + if ( + computers[i].name[0] == 't' + or computers[j].name[0] == 't' + or computers[k].name[0] == 't' + ): + # Found 3 connected + n++ + + printf("%d\n", n) # Output: 7 + + free(computers) + return 0 diff --git a/examples/aoc2024/day23/part2.jou b/examples/aoc2024/day23/part2.jou new file mode 100644 index 00000000..ea50ff48 --- /dev/null +++ b/examples/aoc2024/day23/part2.jou @@ -0,0 +1,140 @@ +import "stdlib/str.jou" +import "stdlib/mem.jou" +import "stdlib/io.jou" + + +def add_computer_if_not_exist(names: byte[3]*, ncomputers: int*, name: byte*) -> None: + for i = 0; i < *ncomputers; i++: + if strcmp(names[i], name) == 0: + return + + assert strlen(name) == 2 + strcpy(names[(*ncomputers)++], name) + + +def find_computer(names: byte[3]*, ncomputers: int, name: byte*) -> int: + for i = 0; i < ncomputers; i++: + if strcmp(names[i], name) == 0: + return i + assert False + + +# If conn_matrix[i][j] is True, then computers i and j are connected +def create_conn_matrix(ncomputers: int) -> bool**: + conn_matrix: bool** = malloc(sizeof(conn_matrix[0]) * ncomputers) + assert conn_matrix != NULL + + for i = 0; i < ncomputers; i++: + conn_matrix[i] = calloc(sizeof(conn_matrix[i][0]), ncomputers) + assert conn_matrix[i] != NULL + + return conn_matrix + + +def sort_names(names: byte[3]*, len: int) -> None: + # very dumb algorithm + while True: + did_something = False + for i = 1; i < len; i++: + if strcmp(names[i-1], names[i]) > 0: + memswap(&names[i-1], &names[i], sizeof(names[0])) + did_something = True + if not did_something: + break + + +# recursive (depth-first search) +def add_more_members_to_group( + group: int*, + group_len: int, + biggest_group: int*, + biggest_group_len: int*, + ncomputers: int, + conn_matrix: bool**, +) -> None: + if group_len > *biggest_group_len: + *biggest_group_len = group_len + memcpy(biggest_group, group, sizeof(group[0]) * group_len) + + # Always add members in order, speeds up search a lot + assert group_len > 0 + for i = group[group_len - 1] + 1; i < ncomputers; i++: + # Do not add same group member twice. + # Do not add members that don't connect with all existing members. + ok = True + for k = 0; k < group_len; k++: + if not conn_matrix[i][group[k]]: + ok = False + break + + if ok: + # Temporarily add new member to the group and recurse with it + group[group_len] = i + add_more_members_to_group( + group, + group_len + 1, + biggest_group, + biggest_group_len, + ncomputers, + conn_matrix, + ) + + +def main() -> int: + names: byte[3]* = malloc(sizeof(names[0]) * 5000) + assert names != NULL + ncomputers = 0 + + f = fopen("sampleinput.txt", "r") + assert f != NULL + + name1: byte[3] + name2: byte[3] + while fscanf(f, "%2s-%2s\n", name1, name2) == 2: + assert ncomputers < 5000 + add_computer_if_not_exist(names, &ncomputers, name1) + assert ncomputers < 5000 + add_computer_if_not_exist(names, &ncomputers, name2) + + sort_names(names, ncomputers) + + rewind(f) + conn_matrix = create_conn_matrix(ncomputers) + while fscanf(f, "%2s-%2s\n", name1, name2) == 2: + i1 = find_computer(names, ncomputers, name1) + i2 = find_computer(names, ncomputers, name2) + conn_matrix[i1][i2] = True + conn_matrix[i2][i1] = True + + fclose(f) + + assert ncomputers < 5000 + group: int[5000] + biggest_group: int[5000] + biggest_group_len = 0 + + for i = 0; i < ncomputers; i++: + group[0] = i + add_more_members_to_group( + group, + 1, + biggest_group, + &biggest_group_len, + ncomputers, + conn_matrix, + ) + + # Output: co,de,ka,ta + for i = 0; i < biggest_group_len; i++: + if i != 0: + printf(",") + printf("%s", names[biggest_group[i]]) + printf("\n") + + for i = 0; i < ncomputers; i++: + free(conn_matrix[i]) + free(conn_matrix) + + free(names) + + return 0 diff --git a/examples/aoc2024/day23/sampleinput.txt b/examples/aoc2024/day23/sampleinput.txt new file mode 100644 index 00000000..3d497667 --- /dev/null +++ b/examples/aoc2024/day23/sampleinput.txt @@ -0,0 +1,32 @@ +kh-tc +qp-kh +de-cg +ka-co +yn-aq +qp-ub +cg-tb +vc-aq +tb-ka +wh-tc +yn-cg +kh-ub +ta-co +de-co +tc-td +tb-wq +wh-td +ta-ka +td-qp +aq-cg +wq-ub +ub-vc +de-ta +wq-aq +wq-vc +wh-yn +ka-de +kh-ta +co-tc +wh-qp +tb-vc +td-yn