Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AOC 2024: days 2-7 #522

Merged
merged 16 commits into from
Dec 8, 2024
66 changes: 66 additions & 0 deletions examples/aoc2024/day02/part1.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import "stdlib/io.jou"
import "stdlib/mem.jou"
import "stdlib/math.jou"
import "stdlib/str.jou"
import "stdlib/ascii.jou"


class Report:
data: int*
len: int

def free(self) -> None:
free(self->data)

def is_safe(self) -> bool:
inc = True
dec = True

for i = 0; i < self->len - 1; i++:
d = self->data[i+1] - self->data[i]

if d <= 0:
inc = False
if d >= 0:
dec = False

if not (1 <= abs(d) and abs(d) <= 3):
return False

return inc or dec


# mutates the line in-place through split_by_ascii_whitespace()
def parse_report(line: byte*) -> Report:
words = split_by_ascii_whitespace(line)

n = 0
while words[n] != NULL:
n++

report = Report{len=n}
report.data = malloc(sizeof(report.data[0]) * n)
for i = 0; i < n; i++:
report.data[i] = atoi(words[i])

free(words)
return report


def main() -> int:
f = fopen("sampleinput.txt", "r")
assert f != NULL

num_safe = 0

line: byte[1024]
while fgets(line, sizeof(line) as int, f) != NULL:
report = parse_report(line)
if report.is_safe():
num_safe++
report.free()

printf("%d\n", num_safe) # Output: 2

fclose(f)
return 0
84 changes: 84 additions & 0 deletions examples/aoc2024/day02/part2.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import "stdlib/io.jou"
import "stdlib/mem.jou"
import "stdlib/math.jou"
import "stdlib/str.jou"
import "stdlib/ascii.jou"


class Report:
data: int*
len: int

def free(self) -> None:
free(self->data)

def is_safe(self) -> bool:
inc = True
dec = True

for i = 0; i < self->len - 1; i++:
d = self->data[i+1] - self->data[i]

if d <= 0:
inc = False
if d >= 0:
dec = False

if not (1 <= abs(d) and abs(d) <= 3):
return False

return inc or dec

def pop(self, i: int) -> int:
bye = self->data[i]
memmove(&self->data[i], &self->data[i+1], sizeof(self->data[0]) * (--self->len - i))
return bye

def insert(self, i: int, value: int) -> None:
# assumes there is enough room in the array and no reallocation is needed
memmove(&self->data[i+1], &self->data[i], sizeof(self->data[0]) * (self->len++ - i))
self->data[i] = value


# mutates the line in-place through split_by_ascii_whitespace()
def parse_report(line: byte*) -> Report:
words = split_by_ascii_whitespace(line)

n = 0
while words[n] != NULL:
n++

report = Report{len=n}
report.data = malloc(sizeof(report.data[0]) * n)
for i = 0; i < n; i++:
report.data[i] = atoi(words[i])

free(words)
return report


def main() -> int:
f = fopen("sampleinput.txt", "r")
assert f != NULL

num_safe = 0

line: byte[1024]
while fgets(line, sizeof(line) as int, f) != NULL:
report = parse_report(line)
if report.is_safe():
num_safe++
else:
for i = 0; i < report.len; i++:
temp_missing = report.pop(i)
if report.is_safe():
num_safe++
break
report.insert(i, temp_missing)

report.free()

printf("%d\n", num_safe) # Output: 4

fclose(f)
return 0
6 changes: 6 additions & 0 deletions examples/aoc2024/day02/sampleinput.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9
56 changes: 56 additions & 0 deletions examples/aoc2024/day03/part1.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import "stdlib/str.jou"
import "stdlib/io.jou"
import "stdlib/mem.jou"
import "stdlib/ascii.jou"


# Moves s in-place beyond used characters. Returns 0 on failure.
def parse_int(s: byte**) -> int:
result = 0
while is_ascii_digit(**s):
result *= 10
result += (*(*s)++ - '0')
return result


# Returns 0 if doesn't match.
def parse_mul(s: byte*) -> int:
if not starts_with(s, "mul("):
return 0
s = &s[4]

a = parse_int(&s)
if *s++ != ',':
return 0
b = parse_int(&s)
if *s++ != ')':
return 0
return a*b


def main() -> int:
max_size = 100000
big_string: byte* = malloc(max_size)

f = fopen("sampleinput1.txt", "r")
assert f != NULL

i = 0
while True:
c = fgetc(f)
EOF = -1 # TODO: belongs to stdlib
if c == EOF:
break
assert i < max_size
big_string[i++] = c as byte

fclose(f)

result = 0 as long
s = big_string
while *s != '\0':
result += parse_mul(s++)

free(big_string)
printf("%d\n", result) # Output: 161
return 0
74 changes: 74 additions & 0 deletions examples/aoc2024/day03/part2.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import "stdlib/str.jou"
import "stdlib/io.jou"
import "stdlib/mem.jou"
import "stdlib/ascii.jou"


# Moves s in-place beyond used characters. Returns 0 on failure.
def parse_int(s: byte**) -> int:
result = 0
while is_ascii_digit(**s):
result *= 10
result += (*(*s)++ - '0')
return result


# Returns 0 if doesn't match.
def parse_mul(s: byte*) -> int:
if not starts_with(s, "mul("):
return 0
s = &s[4]

a = parse_int(&s)
if *s++ != ',':
return 0
b = parse_int(&s)
if *s++ != ')':
return 0
return a*b


def remove_disabled_sections(s: byte*) -> None:
while True:
dont = strstr(s, "don't()")
if dont == NULL:
break

do = strstr(dont, "do()")
if do == NULL:
# disable to end
*dont = '\0'
else:
# delete dont()...do()
do_end = &do[4]
memmove(dont, do_end, strlen(do_end) + 1)


def main() -> int:
max_size = 100000
big_string: byte* = malloc(max_size)

f = fopen("sampleinput.txt", "r")
Akuli marked this conversation as resolved.
Show resolved Hide resolved
assert f != NULL

i = 0
while True:
c = fgetc(f)
EOF = -1 # TODO: belongs to stdlib
if c == EOF:
break
assert i < max_size
big_string[i++] = c as byte

fclose(f)

remove_disabled_sections(big_string)

result = 0 as long
s = big_string
while *s != '\0':
result += parse_mul(s++)

free(big_string)
printf("%d\n", result) # Output: 48
return 0
1 change: 1 addition & 0 deletions examples/aoc2024/day03/sampleinput1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
1 change: 1 addition & 0 deletions examples/aoc2024/day03/sampleinput2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
56 changes: 56 additions & 0 deletions examples/aoc2024/day04/part1.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import "../grid.jou"
import "stdlib/str.jou"
import "stdlib/mem.jou"
import "stdlib/io.jou"


def count_in_string(s: byte*) -> int:
n = 0
for i = 0; s[i] != '\0'; i++:
if starts_with(&s[i], "XMAS") or starts_with(&s[i], "SAMX"):
n++
return n


def count_diagonals(grid: Grid*) -> int:
big_size = grid->width + grid->height + 69
temp_string: byte* = malloc(big_size)
assert temp_string != NULL

result = 0

for c = -big_size; c <= big_size; c++:
# diagonals like /, along lines whose equation is y = x + c
p = temp_string
for x = 0; x < grid->width; x++:
y = x + c
if 0 <= y and y < grid->height:
*p++ = grid->get([x, y])
*p = '\0'
result += count_in_string(temp_string)

# diagonals like \, along lines whose equation is y = -x + c
p = temp_string
for x = 0; x < grid->width; x++:
y = -x + c
if 0 <= y and y < grid->height:
*p++ = grid->get([x, y])
*p = '\0'
result += count_in_string(temp_string)

free(temp_string)
return result


def main() -> int:
f = fopen("sampleinput.txt", "r")
grid = read_grid_from_file(f)
fclose(f)

horizontal = count_in_string(grid.data)
grid.transpose()
vertical = count_in_string(grid.data)
diagonal = count_diagonals(&grid)
printf("%d\n", horizontal + vertical + diagonal) # Output: 18

return 0
46 changes: 46 additions & 0 deletions examples/aoc2024/day04/part2.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import "../grid.jou"
import "stdlib/io.jou"
import "stdlib/mem.jou"


# Count how many times template matches grid
# "." in template can be any character
def count_template(grid: Grid*, template: Grid*) -> int:
count = 0
for ox = 0; ox <= grid->width - template->width; ox++:
for oy = 0; oy <= grid->height - template->height; oy++:
all_match = True
for x = 0; x < template->width; x++:
for y = 0; y < template->height; y++:
grid_byte = grid->get([ox + x, oy + y])
template_byte = template->get([x, y])
if grid_byte != template_byte and template_byte != '.':
all_match = False
if all_match:
count += 1
return count


def main() -> int:
templates: Grid[10]
num_templates = 0

f = fopen("part2_templates.txt", "r")
while feof(f) == 0:
assert num_templates < sizeof(templates)/sizeof(templates[0])
templates[num_templates++] = read_grid_from_file(f)
fclose(f)

f = fopen("sampleinput.txt", "r")
grid = read_grid_from_file(f)
fclose(f)

result = 0
for i = 0; i < num_templates; i++:
result += count_template(&grid, &templates[i])
printf("%d\n", result) # Output: 9

for i = 0; i < num_templates; i++:
free(templates[i].data)

return 0
Loading
Loading