day 2
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
day1
|
*.txt
|
||||||
day1_input
|
*.elf
|
||||||
day1_test
|
blink.log
|
||||||
|
compile_commands.json
|
||||||
|
|||||||
16
Makefile
16
Makefile
@@ -1,4 +1,14 @@
|
|||||||
all: day1
|
FILES = $(wildcard ./*)
|
||||||
|
SRCS = $(filter %.c,$(FILES))
|
||||||
|
BINS = $(SRCS:%.c=%.elf)
|
||||||
|
|
||||||
%: %.c
|
CFLAGS = -Wall -Werror -pedantic -D_GNU_SOURCE -std=gnu2y -O3 -g -Wno-unused\
|
||||||
gcc-tree -o $@ -Wall -Werror -pedantic -D_GNU_SOURCE -std=gnu2y -O3 -g $<
|
-nostartfiles -static -Ttext=C475000
|
||||||
|
|
||||||
|
all: $(BINS)
|
||||||
|
|
||||||
|
%.elf: %.c
|
||||||
|
gcc-tree -o $@ $(CFLAGS) $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm ./*.elf
|
||||||
|
|||||||
72
day1.c
72
day1.c
@@ -1,23 +1,26 @@
|
|||||||
#include <stdio.h>
|
#include "lib.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdcountof.h>
|
|
||||||
|
|
||||||
|
#define DBG 1
|
||||||
|
|
||||||
|
#define RUN_PART1 1
|
||||||
|
#define RUN_PART2 1
|
||||||
|
#define RUN_TEST1 1
|
||||||
|
#define RUN_TEST2 1
|
||||||
|
|
||||||
|
#define TEST1_EXPECT 3
|
||||||
|
#define TEST2_EXPECT 6
|
||||||
|
|
||||||
|
static
|
||||||
char input[] = {
|
char input[] = {
|
||||||
#embed "day1_input"
|
#embed "day1_input.txt"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static
|
||||||
char test[] = {
|
char test[] = {
|
||||||
#embed "day1_test"
|
#embed "day1_test.txt"
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned grabnum(const char *s, const char **end) {
|
static
|
||||||
unsigned r = 0;
|
|
||||||
for (; *s >= '0' && *s <= '9'; s++)
|
|
||||||
r = r * 10 + (*s - '0');
|
|
||||||
*end = s;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long do_part1(size_t src_len, const char src[src_len]) {
|
unsigned long do_part1(size_t src_len, const char src[src_len]) {
|
||||||
const char *s = src;
|
const char *s = src;
|
||||||
unsigned long count = 0;
|
unsigned long count = 0;
|
||||||
@@ -36,6 +39,7 @@ unsigned long do_part1(size_t src_len, const char src[src_len]) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
unsigned do_part2(size_t src_len, const char src[src_len]) {
|
unsigned do_part2(size_t src_len, const char src[src_len]) {
|
||||||
const char *s = src, *ns = s + 1;
|
const char *s = src, *ns = s + 1;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
@@ -70,24 +74,40 @@ unsigned do_part2(size_t src_len, const char src[src_len]) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
void _start() {
|
||||||
printf("PART 1 TEST: ");
|
#if RUN_TEST1
|
||||||
if (unsigned long v = do_part1(countof(test), test); v != 3) {
|
print("PART 1 TEST: ");
|
||||||
printf("FAILED (got %lu, expected 3)\n", v);
|
if (unsigned long v = do_part1(countof(test), test); v != TEST1_EXPECT) {
|
||||||
|
print("FAILED (got ");
|
||||||
|
printd(v);
|
||||||
|
print(", expected " xstr(TEST1_EXPECT) ")\n");
|
||||||
} else {
|
} else {
|
||||||
printf("PASSED\n");
|
print("PASSED\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("PART 1 RESULT: %lu\n",
|
#if RUN_PART1
|
||||||
do_part1(countof(input), input));
|
print("PART 1 RESULT: ");
|
||||||
|
printd(do_part1(countof(input), input));
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("PART 2 TEST: ");
|
#if RUN_TEST2
|
||||||
if (unsigned v = do_part2(countof(test), test); v != 6) {
|
print("PART 2 TEST: ");
|
||||||
printf("FAILED (got %u, expected 6)\n", v);
|
if (unsigned v = do_part2(countof(test), test); v != TEST2_EXPECT) {
|
||||||
|
print("FAILED (got ");
|
||||||
|
printd(v);
|
||||||
|
print(", expected " xstr(TEST2_EXPECT) ")\n");
|
||||||
} else {
|
} else {
|
||||||
printf("PASSED\n");
|
print("PASSED\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("PART 2 RESULT: %u\n",
|
#if RUN_PART2
|
||||||
do_part2(countof(input), input));
|
print("PART 2 RESULT: ");
|
||||||
|
printd(do_part2(countof(input), input));
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
syscall(SYS_exit_group, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
296
day2.c
Normal file
296
day2.c
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
#define DBG 0
|
||||||
|
|
||||||
|
static
|
||||||
|
unsigned char input[] = {
|
||||||
|
#embed "day2_input.txt"
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
unsigned char test[] = {
|
||||||
|
#embed "day2_test.txt"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct id {
|
||||||
|
size_t len;
|
||||||
|
bcdint v;
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
struct id next_palindrome_part1(struct id s) {
|
||||||
|
if (s.len % 2 == 1) {
|
||||||
|
size_t len = s.len + 1;
|
||||||
|
unsigned high_shift = (len / 2) * 4;
|
||||||
|
|
||||||
|
bcdint high = 1 << (high_shift - 4);
|
||||||
|
|
||||||
|
return (struct id) {
|
||||||
|
.len = len,
|
||||||
|
.v = (high << high_shift) | high
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned high_shift = (s.len / 2) * 4;
|
||||||
|
bcdint low_mask = (1 << high_shift) - 1;
|
||||||
|
|
||||||
|
bcdint high = s.v >> high_shift;
|
||||||
|
bcdint low = s.v & low_mask;
|
||||||
|
|
||||||
|
if (low > high)
|
||||||
|
high = bcdadd(high, 1);
|
||||||
|
|
||||||
|
return (struct id) {
|
||||||
|
.len = s.len,
|
||||||
|
.v = (high << high_shift) | high
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bcdint do_part1(size_t file_len, unsigned char file[file_len]) {
|
||||||
|
unsigned char *src = file, *tmp;
|
||||||
|
bcdint result = 0;
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do {
|
||||||
|
#if DBG
|
||||||
|
print_watch_ptr(src);
|
||||||
|
print("\t");
|
||||||
|
print(str(src) ":");
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
print(" ");
|
||||||
|
print_hex_char(src[i]);
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tmp = src;
|
||||||
|
bcdint rs = grabbcd(src, &src);
|
||||||
|
struct id first = {
|
||||||
|
.len = src - tmp,
|
||||||
|
.v = rs
|
||||||
|
};
|
||||||
|
|
||||||
|
src++;
|
||||||
|
|
||||||
|
tmp = src;
|
||||||
|
bcdint re = grabbcd(src, &src);
|
||||||
|
|
||||||
|
src++;
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
printh(rs);
|
||||||
|
print(" to ");
|
||||||
|
printh(re);
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct id next = first;
|
||||||
|
do {
|
||||||
|
next = next_palindrome_part1(next);
|
||||||
|
if (next.v <= re) {
|
||||||
|
result = bcdadd(result, next.v);
|
||||||
|
#if DBG
|
||||||
|
print_watch_hex(next.v);
|
||||||
|
print("\t");
|
||||||
|
print_watch_hex(next.len);
|
||||||
|
print("\t");
|
||||||
|
print_watch_hex(result);
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
bcdint tmp = bcdadd(next.v, 1);
|
||||||
|
for (bcdint chk = next.v; chk > 0; chk >>= 4) {
|
||||||
|
if ((chk & 0xF) != 9) goto no_len_change;
|
||||||
|
}
|
||||||
|
next.len++;
|
||||||
|
no_len_change:
|
||||||
|
next.v = tmp;
|
||||||
|
} while (next.v <= re);
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
print("reached ");
|
||||||
|
printh(re);
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} while (src != &file[file_len]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
struct id next_palindrome_part2(struct id s) {
|
||||||
|
bcdint best = -1;
|
||||||
|
|
||||||
|
for (unsigned i = 2; i <= s.len; i++) {
|
||||||
|
if (s.len % i == 0) {
|
||||||
|
unsigned high_shift = (s.len / i) * 4;
|
||||||
|
|
||||||
|
bcdint high = s.v >> (high_shift * (i - 1));
|
||||||
|
|
||||||
|
for (int j = i - 2; j >= 0; j--) {
|
||||||
|
bcdint low = (s.v >> (high_shift * (j))) & ((1 << high_shift) - 1);
|
||||||
|
|
||||||
|
if (low < high) {
|
||||||
|
break;
|
||||||
|
} else if (low > high) {
|
||||||
|
high = bcdadd(high, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bcdint next = 0;
|
||||||
|
for (unsigned j = 0; j < i; j++) {
|
||||||
|
next |= high << (high_shift * j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next < best) {
|
||||||
|
best = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best != -1) {
|
||||||
|
return (struct id) {
|
||||||
|
.len = s.len,
|
||||||
|
.v = best
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = s.len + 1;
|
||||||
|
unsigned high_shift = (len / 2) * 4;
|
||||||
|
|
||||||
|
bcdint high = 1 << (high_shift - 4);
|
||||||
|
|
||||||
|
return (struct id) {
|
||||||
|
.len = len,
|
||||||
|
.v = (high << high_shift) | high
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bcdint do_part2(size_t file_len, unsigned char file[file_len]) {
|
||||||
|
unsigned char *src = file, *tmp;
|
||||||
|
bcdint result = 0;
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do {
|
||||||
|
#if DBG
|
||||||
|
print_watch_ptr(src);
|
||||||
|
print("\t");
|
||||||
|
print(str(src) ":");
|
||||||
|
for (size_t i = 0; i < 2; i++) {
|
||||||
|
print(" ");
|
||||||
|
print_hex_char(src[i]);
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tmp = src;
|
||||||
|
bcdint rs = grabbcd(src, &src);
|
||||||
|
struct id first = {
|
||||||
|
.len = src - tmp,
|
||||||
|
.v = rs
|
||||||
|
};
|
||||||
|
|
||||||
|
src++;
|
||||||
|
|
||||||
|
tmp = src;
|
||||||
|
bcdint re = grabbcd(src, &src);
|
||||||
|
|
||||||
|
src++;
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
printh(rs);
|
||||||
|
print(" to ");
|
||||||
|
printh(re);
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct id next = first;
|
||||||
|
do {
|
||||||
|
next = next_palindrome_part2(next);
|
||||||
|
if (next.v <= re) {
|
||||||
|
result = bcdadd(result, next.v);
|
||||||
|
#if DBG
|
||||||
|
print_watch_hex(next.v);
|
||||||
|
print("\t");
|
||||||
|
print_watch_hex(next.len);
|
||||||
|
print("\t");
|
||||||
|
print_watch_hex(result);
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
bcdint tmp = bcdadd(next.v, 1);
|
||||||
|
for (bcdint chk = next.v; chk > 0; chk >>= 4) {
|
||||||
|
if ((chk & 0xF) != 9) goto no_len_change;
|
||||||
|
}
|
||||||
|
next.len++;
|
||||||
|
no_len_change:
|
||||||
|
next.v = tmp;
|
||||||
|
} while (next.v <= re);
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
print("reached ");
|
||||||
|
printh(re);
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} while (src != &file[file_len]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RUN_TEST1 1
|
||||||
|
#define RUN_PART1 1
|
||||||
|
#define RUN_TEST2 1
|
||||||
|
#define RUN_PART2 1
|
||||||
|
|
||||||
|
#define TEST1_EXPECT 0x1227775554l
|
||||||
|
#define TEST2_EXPECT 0x4174379265l
|
||||||
|
|
||||||
|
void _start() {
|
||||||
|
#if RUN_TEST1
|
||||||
|
print("PART 1 TEST: ");
|
||||||
|
if (bcdint v = do_part1(countof(test), test); v != TEST1_EXPECT) {
|
||||||
|
print("FAILED (got ");
|
||||||
|
printh(v);
|
||||||
|
print(", expected " xstr(TEST1_EXPECT) ")\n");
|
||||||
|
} else {
|
||||||
|
print("PASSED\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if RUN_PART1
|
||||||
|
print("PART 1 RESULT: ");
|
||||||
|
printh(do_part1(countof(input), input));
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if RUN_TEST2
|
||||||
|
print("PART 2 TEST: ");
|
||||||
|
if (bcdint v = do_part2(countof(test), test); v != TEST2_EXPECT) {
|
||||||
|
print("FAILED (got ");
|
||||||
|
printh(v);
|
||||||
|
print(", expected " xstr(TEST2_EXPECT) ")\n");
|
||||||
|
} else {
|
||||||
|
print("PASSED\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if RUN_PART2
|
||||||
|
print("PART 2 RESULT: ");
|
||||||
|
printh(do_part2(countof(input), input));
|
||||||
|
print("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
syscall(SYS_exit_group, 0);
|
||||||
|
}
|
||||||
147
lib.h
Normal file
147
lib.h
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdcountof.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define xstr(s) str(s)
|
||||||
|
#define str(s) #s
|
||||||
|
|
||||||
|
typedef uint64_t bcdint;
|
||||||
|
|
||||||
|
static
|
||||||
|
void printns(size_t len, unsigned char chars[len]) {
|
||||||
|
syscall(SYS_write, STDOUT_FILENO, chars, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void printptr(uintptr_t v) {
|
||||||
|
char buf[sizeof(uintptr_t)*2] = { };
|
||||||
|
char *p = buf+countof(buf);
|
||||||
|
for (size_t i = 0; i < countof(buf); i++) {
|
||||||
|
p--;
|
||||||
|
if ((v & 0x0F) < 0xA) {
|
||||||
|
*p = '0' + (v & 0x0F);
|
||||||
|
} else {
|
||||||
|
*p = 'A' - 0xA + (v & 0x0F);
|
||||||
|
}
|
||||||
|
v >>= 4;
|
||||||
|
}
|
||||||
|
syscall(SYS_write, STDOUT_FILENO, p, countof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void print_many_char(size_t len, char chars[len]) {
|
||||||
|
syscall(SYS_write, STDOUT_FILENO, chars, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define print(string) print_many_char(sizeof(string)-1, string)
|
||||||
|
|
||||||
|
static
|
||||||
|
void printd(unsigned long v) {
|
||||||
|
if (!v) {
|
||||||
|
print("0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buf[32];
|
||||||
|
char *p = buf+32;
|
||||||
|
unsigned count = 0;
|
||||||
|
while (v) {
|
||||||
|
p--;
|
||||||
|
*p = '0' + (v % 10);
|
||||||
|
v /= 10;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
syscall(SYS_write, STDOUT_FILENO, p, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void printh(unsigned long v) {
|
||||||
|
if (!v) {
|
||||||
|
print("0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buf[32];
|
||||||
|
char *p = buf+32;
|
||||||
|
unsigned count = 0;
|
||||||
|
while (v) {
|
||||||
|
p--;
|
||||||
|
if ((v & 0x0F) < 0xA) {
|
||||||
|
*p = '0' + (v & 0x0F);
|
||||||
|
} else {
|
||||||
|
*p = 'A' - 0xA + (v & 0x0F);
|
||||||
|
}
|
||||||
|
v >>= 4;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
syscall(SYS_write, STDOUT_FILENO, p, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void print_hex_char(unsigned char v) {
|
||||||
|
char buf[2];
|
||||||
|
|
||||||
|
if ((v >> 4) < 0x0A) {
|
||||||
|
buf[0] = '0' + (v >> 4);
|
||||||
|
} else {
|
||||||
|
buf[0] = 'A' - 0xA + (v >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((v & 0x0F) < 0xA) {
|
||||||
|
buf[1] = '0' + (v & 0x0F);
|
||||||
|
} else {
|
||||||
|
buf[1] = 'A' - 0xA + (v & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall(SYS_write, STDOUT_FILENO, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void print_pre_hex(size_t len, unsigned char prefix[len], unsigned long v) {
|
||||||
|
printns(len, prefix);
|
||||||
|
printh(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void print_pre_ptr(size_t len, unsigned char prefix[len], void *ptr) {
|
||||||
|
printns(len, prefix);
|
||||||
|
printptr((uintptr_t)ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define print_watch_ptr(expr) print_pre_ptr(\
|
||||||
|
sizeof(#expr ": ")-1, (unsigned char*)(#expr ": "), expr)
|
||||||
|
#define print_watch_hex(expr) print_pre_hex(\
|
||||||
|
sizeof(#expr ": ")-1, (unsigned char*)(#expr ": "), expr)
|
||||||
|
|
||||||
|
static
|
||||||
|
bcdint grabbcd(unsigned char *s, unsigned char **end) {
|
||||||
|
bcdint r = 0;
|
||||||
|
for (; *s >= '0' && *s <= '9'; s++)
|
||||||
|
r = (r << 4) + (*s - '0');
|
||||||
|
if (end) *end = s;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
unsigned grabnum(const char *s, const char **end) {
|
||||||
|
unsigned r = 0;
|
||||||
|
for (; *s >= '0' && *s <= '9'; s++)
|
||||||
|
r = r * 10 + (*s - '0');
|
||||||
|
*end = s;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// from wikipedia, the free encyclopedia
|
||||||
|
// https://en.wikipedia.org/wiki/Binary-coded_decimal
|
||||||
|
static bcdint bcdadd(bcdint a, bcdint b) {
|
||||||
|
bcdint t1, t2;
|
||||||
|
t1 = a + 0x0666666666666666;
|
||||||
|
t2 = t1 ^ b;
|
||||||
|
t1 = t1 + b;
|
||||||
|
t2 = t1 ^ t2;
|
||||||
|
t2 = ~t2 & 0x1111111111111110;
|
||||||
|
t2 = (t2 >> 2) | (t2 >> 3);
|
||||||
|
return t1 - t2;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user