Skip to content

Commit

Permalink
Advent of code day4 (#419)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Dec 4, 2023
1 parent 171226c commit 35afac4
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 0 deletions.
50 changes: 50 additions & 0 deletions examples/aoc2023/day04/part1.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import "stdlib/io.jou"
import "stdlib/mem.jou"
import "stdlib/str.jou"
import "stdlib/ascii.jou"


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

total_score = 0

line: byte[1000]
while fgets(line, sizeof(line) as int, f) != NULL:
words = split_by_ascii_whitespace(line)
assert words[0] != NULL and strcmp(words[0], "Card") == 0
assert words[1] != NULL # id number

winning: int[100]
nwinning = 0
score = 0

no_separator_yet = True
for i = 2; words[i] != NULL; i++:
if strcmp(words[i], "|") == 0:
no_separator_yet = False
else:
n = atoi(words[i])
if no_separator_yet:
assert nwinning < sizeof(winning)/sizeof(winning[0])
winning[nwinning++] = n
else:
# check if this is a winning number
for k = 0; k < nwinning; k++:
if winning[k] == n:
score++
break

if score != 0:
k = 1
for i = 1; i < score; i++:
k *= 2
total_score += k

free(words)

fclose(f)

printf("%d\n", total_score) # Output: 13
return 0
75 changes: 75 additions & 0 deletions examples/aoc2023/day04/part2.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import "stdlib/io.jou"
import "stdlib/str.jou"
import "stdlib/mem.jou"
import "stdlib/ascii.jou"


# returned array is -1 terminated and should be free()d
def read_win_counts() -> int[500]:
f = fopen("sampleinput.txt", "r")
assert f != NULL

result: int[500]
result_len = 0

line: byte[1000]
while fgets(line, sizeof(line) as int, f) != NULL:
words = split_by_ascii_whitespace(line)
assert words[0] != NULL and strcmp(words[0], "Card") == 0
assert words[1] != NULL and atoi(words[1]) == result_len+1

winning: int[100]
nwinning = 0
match_count = 0

no_separator_yet = True
for i = 2; words[i] != NULL; i++:
if strcmp(words[i], "|") == 0:
no_separator_yet = False
else:
n = atoi(words[i])
if no_separator_yet:
assert nwinning < sizeof(winning)/sizeof(winning[0])
winning[nwinning++] = n
else:
# check if this is a winning number
for k = 0; k < nwinning; k++:
if winning[k] == n:
match_count++
break

assert result_len < sizeof(result)/sizeof(result[0])
result[result_len++] = match_count

free(words)

fclose(f)

assert result_len < sizeof(result)/sizeof(result[0])
result[result_len] = -1
return result


def main() -> int:
win_counts = read_win_counts()
num_cards = 0
for i = 0; win_counts[i] != -1; i++:
num_cards++

assert sizeof(win_counts)/sizeof(win_counts[0]) == 500
card_counts: int[500]
for i = 0; i < num_cards; i++:
card_counts[i] = 1

# process wins --> more cards
for i = 0; i < num_cards; i++:
for k = i+1; k <= i + win_counts[i]; k++:
assert k < num_cards
card_counts[k] += card_counts[i]

sum = 0
for i = 0; i < num_cards; i++:
sum += card_counts[i]
printf("%d\n", sum) # Output: 30

return 0
6 changes: 6 additions & 0 deletions examples/aoc2023/day04/sampleinput.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
52 changes: 52 additions & 0 deletions stdlib/ascii.jou
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,55 @@ def trim_ascii_whitespace(s: byte*) -> void:
if start != s:
memmove(s, start, len)
s[len] = '\0'


# Finds all non-whitespace parts of a string.
# For example: " foo bar baz \n" --> ["foo", "bar", "baz", NULL]
#
# Example usage:
#
# s = strdup(" foo bar baz\n")
# words = split_by_ascii_whitespace(s)
#
# for i = 0; words[i] != NULL; i++:
# printf("%s\n", words[i])
#
# free(words)
# free(s)
#
# Modifies s in-place to put '\0' bytes where words end.
# Returns an array of byte*, using NULL to mark last word.
# Return value (and perhaps s) must be free()d, but individual strings don't.
def split_by_ascii_whitespace(s: byte*) -> byte**:
# Count how many non-whitespace sections we have.
count = 0
flag = False
for p = s; *p != '\0'; p++:
if not flag and not is_ascii_whitespace(*p):
count++
flag = True
elif flag and is_ascii_whitespace(*p):
flag = False

result: byte** = malloc(sizeof(result[0]) * (count + 1))
result_ptr = result

while True:
while is_ascii_whitespace(*s):
s++
if *s == '\0':
break
*result_ptr++ = s

while not is_ascii_whitespace(*s):
s++

if *s == '\0':
break # do not go past end of string

# mark end of word and move on
*s++ = '\0'

assert result_ptr == &result[count]
*result_ptr = NULL
return result

0 comments on commit 35afac4

Please sign in to comment.