Skip to content

Commit

Permalink
AoC 2024 day 23 (#544)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Jan 5, 2025
1 parent baae680 commit 5b8fcd4
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 0 deletions.
89 changes: 89 additions & 0 deletions examples/aoc2024/day23/part1.jou
Original file line number Diff line number Diff line change
@@ -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
140 changes: 140 additions & 0 deletions examples/aoc2024/day23/part2.jou
Original file line number Diff line number Diff line change
@@ -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
32 changes: 32 additions & 0 deletions examples/aoc2024/day23/sampleinput.txt
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 5b8fcd4

Please sign in to comment.