Skip to content

Commit

Permalink
Aoc days 9, 10, 11 (#446)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Dec 11, 2023
1 parent 5df53c8 commit 0e585e1
Show file tree
Hide file tree
Showing 11 changed files with 591 additions and 6 deletions.
13 changes: 7 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
# ide stuff
/.vscode/

# Advent of Code input files https://adventofcode.com/
# These are large text files, and each AoC user gets different input files.
# Tests use sampleinput.txt files, copied from problem descriptions
# Advent of Code files https://adventofcode.com/
# Inputs are large text files, and each AoC user gets different input files.
# Tests use sampleinput.txt files, copied from problem descriptions.
#
# Creator of AoC tells people not to commit inputs to git. I also cannot
# commit problem descriptions to git because of copyright.
/examples/aoc2023/day*/input
/examples/aoc2023/day*/input.txt

# files created by https://github.com/scarvalhojr/aoc-cli
# not sure if I can commit these to git because copyright
/examples/aoc2023/day*/puzzle.md
48 changes: 48 additions & 0 deletions examples/aoc2023/day09/part1.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import "stdlib/io.jou"
import "stdlib/ascii.jou"
import "stdlib/str.jou"
import "stdlib/mem.jou"


def predict_next(nums: long*, len: int) -> long:
all_zero = True
for i = 0; i < len; i++:
if nums[i] != 0:
all_zero = False
break

if all_zero:
return 0

diffs: long* = malloc(sizeof(diffs[0]) * len)
for i = 1; i < len; i++:
diffs[i-1] = nums[i]-nums[i-1]

result = nums[len-1] + predict_next(diffs, len-1)
free(diffs)
return result


# return value is an array terminated by nums_len=-1
def main() -> int:
f = fopen("sampleinput.txt", "r")
assert f != NULL

line: byte[1000]
result: long = 0

while fgets(line, sizeof(line) as int, f) != NULL:
nums: long[100]
nnums = 0
parts = split_by_ascii_whitespace(line)
for p = parts; *p != NULL; p++:
assert nnums < sizeof(nums)/sizeof(nums[0])
nums[nnums++] = atoll(*p)
free(parts)

result += predict_next(nums, nnums)

fclose(f)

printf("%lld\n", result) # Output: 114
return 0
62 changes: 62 additions & 0 deletions examples/aoc2023/day09/part2.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import "stdlib/io.jou"
import "stdlib/ascii.jou"
import "stdlib/str.jou"
import "stdlib/mem.jou"


def predict_next(nums: long*, len: int) -> long:
all_zero = True
for i = 0; i < len; i++:
if nums[i] != 0:
all_zero = False
break

if all_zero:
return 0

diffs: long* = malloc(sizeof(diffs[0]) * len)
for i = 1; i < len; i++:
diffs[i-1] = nums[i]-nums[i-1]

result = nums[len-1] + predict_next(diffs, len-1)
free(diffs)
return result


def swap(a: long*, b: long*) -> None:
tmp = *a
*a = *b
*b = tmp


def reverse(nums: long*, len: int) -> None:
p = nums
q = &nums[len-1]
while p < q:
swap(p++, q--)


# return value is an array terminated by nums_len=-1
def main() -> int:
f = fopen("sampleinput.txt", "r")
assert f != NULL

line: byte[1000]
result: long = 0

while fgets(line, sizeof(line) as int, f) != NULL:
nums: long[100]
nnums = 0
parts = split_by_ascii_whitespace(line)
for p = parts; *p != NULL; p++:
assert nnums < sizeof(nums)/sizeof(nums[0])
nums[nnums++] = atoll(*p)
free(parts)

reverse(nums, nnums)
result += predict_next(nums, nnums)

fclose(f)

printf("%lld\n", result) # Output: 2
return 0
3 changes: 3 additions & 0 deletions examples/aoc2023/day09/sampleinput.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
0 3 6 9 12 15
1 3 6 10 15 21
10 13 16 21 30 45
103 changes: 103 additions & 0 deletions examples/aoc2023/day10/part1.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import "stdlib/io.jou"
import "stdlib/mem.jou"
import "stdlib/str.jou"


class Input:
width: int
height: int
data: byte*

def is_in_bounds(self, point: int[2]) -> bool:
x = point[0]
y = point[1]
return 0 <= x and x < self->width and 0 <= y and y < self->height

def get(self, point: int[2]) -> byte:
assert self->is_in_bounds(point)
x = point[0]
y = point[1]
return self->data[(self->width + 1)*y + x]


def find_S(input: Input*) -> int[2]:
for x = 0; x < input->width; x++:
for y = 0; y < input->height; y++:
if input->get([x, y]) == 'S':
return [x, y]

assert False


def get_dirs(c: byte) -> int[2][2]:
if c == '7':
return [[-1, 0], [0, 1]]
if c == 'J':
return [[-1, 0], [0, -1]]
if c == 'L':
return [[1, 0], [0, -1]]
if c == 'F':
return [[1, 0], [0, 1]]
if c == '-':
return [[-1, 0], [1, 0]]
if c == '|':
return [[0, -1], [0, 1]]

assert False


def eq(a: int[2], b: int[2]) -> bool:
return a[0] == b[0] and a[1] == b[1]


def find_initial_direction(input: Input*, S: int[2]) -> int[2]:
directions = [[0,1], [0,-1], [1,0], [-1,0]]
for d = &directions[0]; d < &directions[4]; d++:
S_to_neighbor = *d
neighbor = [S[0] + S_to_neighbor[0], S[1] + S_to_neighbor[1]]

if input->is_in_bounds(neighbor) and input->get(neighbor) != '.':
dirs = get_dirs(input->get(neighbor))
if eq(dirs[0], S_to_neighbor) or eq(dirs[1], S_to_neighbor):
return S_to_neighbor

assert False


def main() -> int:
max_len = 100000
input = Input{data = calloc(1, max_len+1)}

f = fopen("sampleinput.txt", "r")
assert f != NULL
fread(input.data, 1, max_len, f)
fclose(f)

input.width = strcspn(input.data, "\n") as int
input.height = (strlen(input.data) as int) / (input.width + 1)

point = find_S(&input)

# take first step away from S
dir = find_initial_direction(&input, point)
point[0] += dir[0]
point[1] += dir[1]
loop_length = 1

while input.get(point) != 'S':
came_from = [-dir[0], -dir[1]]
dirs = get_dirs(input.get(point))
assert eq(came_from, dirs[0]) or eq(came_from, dirs[1])
if eq(came_from, dirs[0]):
dir = dirs[1]
else:
dir = dirs[0]
point[0] += dir[0]
point[1] += dir[1]
loop_length++

assert loop_length % 2 == 0
printf("%d\n", loop_length / 2) # Output: 4

free(input.data)
return 0
Loading

0 comments on commit 0e585e1

Please sign in to comment.