From b7d21ac1b110886ad00d88f09669088727fedc61 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sat, 4 Jan 2025 00:56:15 +0200 Subject: [PATCH 1/6] day22 part1 --- examples/aoc2024/day22/part1.jou | 46 ++++++++++++++++++++++++++ examples/aoc2024/day22/sampleinput.txt | 4 +++ 2 files changed, 50 insertions(+) create mode 100644 examples/aoc2024/day22/part1.jou create mode 100644 examples/aoc2024/day22/sampleinput.txt diff --git a/examples/aoc2024/day22/part1.jou b/examples/aoc2024/day22/part1.jou new file mode 100644 index 00000000..44f72fd8 --- /dev/null +++ b/examples/aoc2024/day22/part1.jou @@ -0,0 +1,46 @@ +import "stdlib/io.jou" +import "stdlib/str.jou" + + +def xor(a: long, b: long) -> long: + assert a >= 0 + assert b >= 0 + + result = 0L + power_of_two = 1L + + while a != 0 or b != 0: + if a % 2 != b % 2: + result += power_of_two + a /= 2 + b /= 2 + power_of_two *= 2 + + return result + + +def next_num(n: long) -> long: + n = xor(n, n * 64) % 16777216 + n = xor(n, n / 32) % 16777216 + n = xor(n, n * 2048) % 16777216 + return n + + +def main() -> int: + f = fopen("sampleinput.txt", "r") + assert f != NULL + + result = 0L + + line: byte[100] + while fgets(line, sizeof(line) as int, f) != NULL: + n = atoll(line) + k = 2000 + while k --> 0: + n = next_num(n) + result += n + + printf("%lld\n", result) # Output: 37327623 + + fclose(f) + return 0 diff --git a/examples/aoc2024/day22/sampleinput.txt b/examples/aoc2024/day22/sampleinput.txt new file mode 100644 index 00000000..07b41ba7 --- /dev/null +++ b/examples/aoc2024/day22/sampleinput.txt @@ -0,0 +1,4 @@ +1 +10 +100 +2024 From 7c5f280eef6924c68f3e4ca88e126ca2c4a7f8d4 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sat, 4 Jan 2025 01:22:56 +0200 Subject: [PATCH 2/6] part2 works but really slow --- examples/aoc2024/day22/part1.jou | 2 +- examples/aoc2024/day22/part2.jou | 92 +++++++++++++++++++ .../{sampleinput.txt => sampleinput1.txt} | 0 examples/aoc2024/day22/sampleinput2.txt | 4 + 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 examples/aoc2024/day22/part2.jou rename examples/aoc2024/day22/{sampleinput.txt => sampleinput1.txt} (100%) create mode 100644 examples/aoc2024/day22/sampleinput2.txt diff --git a/examples/aoc2024/day22/part1.jou b/examples/aoc2024/day22/part1.jou index 44f72fd8..ab971bac 100644 --- a/examples/aoc2024/day22/part1.jou +++ b/examples/aoc2024/day22/part1.jou @@ -27,7 +27,7 @@ def next_num(n: long) -> long: def main() -> int: - f = fopen("sampleinput.txt", "r") + f = fopen("sampleinput1.txt", "r") assert f != NULL result = 0L diff --git a/examples/aoc2024/day22/part2.jou b/examples/aoc2024/day22/part2.jou new file mode 100644 index 00000000..87fd2aa2 --- /dev/null +++ b/examples/aoc2024/day22/part2.jou @@ -0,0 +1,92 @@ +import "stdlib/io.jou" +import "stdlib/str.jou" +import "stdlib/mem.jou" + + +# TODO: belongs to stdlib +declare memcmp(a: void*, b: void*, n: long) -> int + + +def xor(a: long, b: long) -> long: + assert a >= 0 + assert b >= 0 + + result = 0L + power_of_two = 1L + + while a != 0 or b != 0: + if a % 2 != b % 2: + result += power_of_two + a /= 2 + b /= 2 + power_of_two *= 2 + + return result + + +def next_num(n: long) -> long: + n = xor(n, n * 64) % 16777216 + n = xor(n, n / 32) % 16777216 + n = xor(n, n * 2048) % 16777216 + return n + + +def num_bananas_from_buyer(state: long, diff_seq: int[4]) -> int: + last_deltas = [69, 69, 69, 69] # dummy values + + k = 2000 + while k --> 0: + old = (state % 10) as int + state = next_num(state) + new = (state % 10) as int + delta = new - old + + # push to end + memmove(&last_deltas[0], &last_deltas[1], 3 * sizeof(last_deltas[0])) + last_deltas[3] = delta + + if memcmp(last_deltas, diff_seq, sizeof(diff_seq)) == 0: + return new + + return 0 + + +def main() -> int: + inputs: long[3000] + ninputs = 0 + + f = fopen("sampleinput2.txt", "r") + assert f != NULL + + line: byte[100] + while fgets(line, sizeof(line) as int, f) != NULL: + assert ninputs < sizeof(inputs)/sizeof(inputs[0]) + inputs[ninputs++] = atoll(line) + + fclose(f) + + + printf("%d\n", num_bananas_from_buyer(1, [-2,1,-1,3])) + printf("%d\n", num_bananas_from_buyer(2, [-2,1,-1,3])) + printf("%d\n", num_bananas_from_buyer(3, [-2,1,-1,3])) + printf("%d\n", num_bananas_from_buyer(2024, [-2,1,-1,3])) + + best = -1 + + for a = -9; a <= 9; a++: + for b = -9; b <= 9; b++: + printf("a=%d b=%d\n", a, b) + fflush(stdout) + for c = -9; c <= 9; c++: + for d = -9; d <= 9; d++: + result = 0 + for i = 0; i < ninputs; i++: + result += num_bananas_from_buyer(inputs[i], [a, b, c, d]) + + if result > best: + printf("best = %d bananas for [%d,%d,%d,%d]\n", result, a, b, c, d) + best = result + + printf("%d\n", result) # Output: 37327623 + + return 0 diff --git a/examples/aoc2024/day22/sampleinput.txt b/examples/aoc2024/day22/sampleinput1.txt similarity index 100% rename from examples/aoc2024/day22/sampleinput.txt rename to examples/aoc2024/day22/sampleinput1.txt diff --git a/examples/aoc2024/day22/sampleinput2.txt b/examples/aoc2024/day22/sampleinput2.txt new file mode 100644 index 00000000..201df766 --- /dev/null +++ b/examples/aoc2024/day22/sampleinput2.txt @@ -0,0 +1,4 @@ +1 +2 +3 +2024 From b894418d164ff165705ba6672bb4536ef1f5a9d5 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sat, 4 Jan 2025 01:37:51 +0200 Subject: [PATCH 3/6] faster, still too slow --- examples/aoc2024/day22/part2.jou | 50 ++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/examples/aoc2024/day22/part2.jou b/examples/aoc2024/day22/part2.jou index 87fd2aa2..bff5a4d3 100644 --- a/examples/aoc2024/day22/part2.jou +++ b/examples/aoc2024/day22/part2.jou @@ -31,23 +31,25 @@ def next_num(n: long) -> long: return n -def num_bananas_from_buyer(state: long, diff_seq: int[4]) -> int: - last_deltas = [69, 69, 69, 69] # dummy values - - k = 2000 - while k --> 0: +def compute_deltas_and_last_digits(state: long, deltas: int*, last_digits: int*) -> None: + result: int[2000] + for i = 0; i < 2000; i++: old = (state % 10) as int state = next_num(state) new = (state % 10) as int - delta = new - old - - # push to end - memmove(&last_deltas[0], &last_deltas[1], 3 * sizeof(last_deltas[0])) - last_deltas[3] = delta - - if memcmp(last_deltas, diff_seq, sizeof(diff_seq)) == 0: - return new - + deltas[i] = new - old + last_digits[i] = new + + +def num_bananas_from_buyer(deltas: int*, last_digits: int*, diff_seq: int[4]) -> int: + for i = 3; i < 2000; i++: + if ( + diff_seq[0] == deltas[i-3] + and diff_seq[1] == deltas[i-2] + and diff_seq[2] == deltas[i-1] + and diff_seq[3] == deltas[i] + ): + return last_digits[i] return 0 @@ -56,6 +58,7 @@ def main() -> int: ninputs = 0 f = fopen("sampleinput2.txt", "r") +# f = fopen("input", "r") assert f != NULL line: byte[100] @@ -65,28 +68,31 @@ def main() -> int: fclose(f) + # Precompute sequence of deltas for each input to speed up + deltas: int[2000]* = malloc(sizeof(deltas[0]) * ninputs) + last_digits: int[2000]* = malloc(sizeof(last_digits[0]) * ninputs) + + assert deltas != NULL + assert last_digits != NULL - printf("%d\n", num_bananas_from_buyer(1, [-2,1,-1,3])) - printf("%d\n", num_bananas_from_buyer(2, [-2,1,-1,3])) - printf("%d\n", num_bananas_from_buyer(3, [-2,1,-1,3])) - printf("%d\n", num_bananas_from_buyer(2024, [-2,1,-1,3])) + for i = 0; i < ninputs; i++: + compute_deltas_and_last_digits(inputs[i], deltas[i], last_digits[i]) best = -1 for a = -9; a <= 9; a++: for b = -9; b <= 9; b++: - printf("a=%d b=%d\n", a, b) - fflush(stdout) for c = -9; c <= 9; c++: for d = -9; d <= 9; d++: result = 0 for i = 0; i < ninputs; i++: - result += num_bananas_from_buyer(inputs[i], [a, b, c, d]) + result += num_bananas_from_buyer(deltas[i], last_digits[i], [a, b, c, d]) if result > best: printf("best = %d bananas for [%d,%d,%d,%d]\n", result, a, b, c, d) + fflush(stdout) best = result - printf("%d\n", result) # Output: 37327623 + printf("%d\n", best) # Output: 23 return 0 From 52583563d0c65e15474cca46064041a6294da178 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sat, 4 Jan 2025 01:55:54 +0200 Subject: [PATCH 4/6] part2 working really nicely --- examples/aoc2024/day22/part2.jou | 85 ++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/examples/aoc2024/day22/part2.jou b/examples/aoc2024/day22/part2.jou index bff5a4d3..8a076004 100644 --- a/examples/aoc2024/day22/part2.jou +++ b/examples/aoc2024/day22/part2.jou @@ -31,52 +31,59 @@ def next_num(n: long) -> long: return n -def compute_deltas_and_last_digits(state: long, deltas: int*, last_digits: int*) -> None: - result: int[2000] - for i = 0; i < 2000; i++: - old = (state % 10) as int - state = next_num(state) - new = (state % 10) as int - deltas[i] = new - old - last_digits[i] = new - - -def num_bananas_from_buyer(deltas: int*, last_digits: int*, diff_seq: int[4]) -> int: - for i = 3; i < 2000; i++: - if ( - diff_seq[0] == deltas[i-3] - and diff_seq[1] == deltas[i-2] - and diff_seq[2] == deltas[i-1] - and diff_seq[3] == deltas[i] - ): - return last_digits[i] - return 0 +# Return value is always less than 20*20*20*20 +def diffseq_to_int(diffseq: int[4]) -> int: + diffseq[0] += 10 + diffseq[1] += 10 + diffseq[2] += 10 + diffseq[3] += 10 + return ((diffseq[0] * 20 + diffseq[1]) * 20 + diffseq[2]) * 20 + diffseq[3] + + +class Buyer: + seed: long + diffseq_to_bananas: int* + + def init_from_seed(self) -> None: + last_digits: int[2000] + deltas: int[2000] + + state = self->seed + for i = 0; i < 2000; i++: + old = (state % 10) as int + state = next_num(state) + new = (state % 10) as int + + last_digits[i] = new + deltas[i] = new - old + + self->diffseq_to_bananas = calloc(sizeof(self->diffseq_to_bananas[0]), 20*20*20*20) + assert self->diffseq_to_bananas != NULL + + # Go backwards so that we overwrite with whatever appears first in array + for i = 1999; i >= 3; i--: + diffseq = [deltas[i-3], deltas[i-2], deltas[i-1], deltas[i]] + self->diffseq_to_bananas[diffseq_to_int(diffseq)] = last_digits[i] def main() -> int: - inputs: long[3000] - ninputs = 0 + max_buyers = 3000 + buyers: Buyer* = malloc(sizeof(buyers[0]) * 3000) + assert buyers != NULL + nbuyers = 0 f = fopen("sampleinput2.txt", "r") -# f = fopen("input", "r") assert f != NULL line: byte[100] while fgets(line, sizeof(line) as int, f) != NULL: - assert ninputs < sizeof(inputs)/sizeof(inputs[0]) - inputs[ninputs++] = atoll(line) + assert nbuyers < max_buyers + buyers[nbuyers++] = Buyer{seed = atoll(line)} fclose(f) - # Precompute sequence of deltas for each input to speed up - deltas: int[2000]* = malloc(sizeof(deltas[0]) * ninputs) - last_digits: int[2000]* = malloc(sizeof(last_digits[0]) * ninputs) - - assert deltas != NULL - assert last_digits != NULL - - for i = 0; i < ninputs; i++: - compute_deltas_and_last_digits(inputs[i], deltas[i], last_digits[i]) + for i = 0; i < nbuyers; i++: + buyers[i].init_from_seed() best = -1 @@ -85,14 +92,16 @@ def main() -> int: for c = -9; c <= 9; c++: for d = -9; d <= 9; d++: result = 0 - for i = 0; i < ninputs; i++: - result += num_bananas_from_buyer(deltas[i], last_digits[i], [a, b, c, d]) + for i = 0; i < nbuyers; i++: + result += buyers[i].diffseq_to_bananas[diffseq_to_int([a, b, c, d])] if result > best: - printf("best = %d bananas for [%d,%d,%d,%d]\n", result, a, b, c, d) - fflush(stdout) best = result printf("%d\n", best) # Output: 23 + for i = 0; i < nbuyers; i++: + free(buyers[i].diffseq_to_bananas) + free(buyers) + return 0 From 26bcad3a309a38bc8a5a72b00c4327ea793b070e Mon Sep 17 00:00:00 2001 From: Akuli Date: Sat, 4 Jan 2025 02:00:45 +0200 Subject: [PATCH 5/6] tiny cleanup --- examples/aoc2024/day22/part2.jou | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/aoc2024/day22/part2.jou b/examples/aoc2024/day22/part2.jou index 8a076004..274f87d1 100644 --- a/examples/aoc2024/day22/part2.jou +++ b/examples/aoc2024/day22/part2.jou @@ -3,10 +3,6 @@ import "stdlib/str.jou" import "stdlib/mem.jou" -# TODO: belongs to stdlib -declare memcmp(a: void*, b: void*, n: long) -> int - - def xor(a: long, b: long) -> long: assert a >= 0 assert b >= 0 From 6d0a6170a882f872e3c538011cb72b7c285c83d8 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sat, 4 Jan 2025 02:03:07 +0200 Subject: [PATCH 6/6] Use less memory so tests pass --- examples/aoc2024/day22/part2.jou | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/aoc2024/day22/part2.jou b/examples/aoc2024/day22/part2.jou index 274f87d1..7d148c8e 100644 --- a/examples/aoc2024/day22/part2.jou +++ b/examples/aoc2024/day22/part2.jou @@ -38,7 +38,7 @@ def diffseq_to_int(diffseq: int[4]) -> int: class Buyer: seed: long - diffseq_to_bananas: int* + diffseq_to_bananas: byte* def init_from_seed(self) -> None: last_digits: int[2000] @@ -59,7 +59,7 @@ class Buyer: # Go backwards so that we overwrite with whatever appears first in array for i = 1999; i >= 3; i--: diffseq = [deltas[i-3], deltas[i-2], deltas[i-1], deltas[i]] - self->diffseq_to_bananas[diffseq_to_int(diffseq)] = last_digits[i] + self->diffseq_to_bananas[diffseq_to_int(diffseq)] = last_digits[i] as byte def main() -> int: