commit a11c5cfa69db7d5291269e66a4aa64bf67cb6212
parent 4bfbfaea1f4d44c57060250805c4071b58bbbdac
Author: amin <dev@aminmesbah.com>
Date: Fri, 3 Dec 2021 22:33:42 +0000
Solve 2021 day 1 part 1
FossilOrigin-Name: 44901fcf7d9d6bcd32e0089cd6f3228c5236f0a779a80a2df8e5d89d06881bf3
Diffstat:
M | .gitignore | | | 1 | + |
A | 2021/am_base.h | | | 118 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | 2021/am_list.h | | | 233 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | 2021/am_memory.h | | | 178 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | 2021/am_string.h | | | 252 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | 2021/day01_01.c | | | 76 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | 2021/day01_input.txt | | | 2000 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
7 files changed, 2858 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1 +1,2 @@
zig-cache/
+**/out/
diff --git a/2021/am_base.h b/2021/am_base.h
@@ -0,0 +1,118 @@
+#ifndef AM_BASE_H
+#define AM_BASE_H
+
+#if __STDC_VERSION__ < 201112L
+# error "C11 or greater required."
+#endif
+
+// context
+// https://sourceforge.net/p/predef/wiki/Home/
+#if defined(__clang__)
+# define COMPILER_CLANG 1
+#elif defined (__GNUC__)
+# define COMPILER_GCC 1
+#else
+# error "Unsupported compiler."
+#endif
+
+#if !defined(COMPILER_CLANG)
+# define COMPILER_CLANG 0
+#endif
+#if !defined(COMPILER_GCC)
+# define COMPILER_GCC 0
+#endif
+
+#if defined (__linux__)
+# define OPERATING_SYSTEM_LINUX 1
+#elif defined(_WIN32)
+# define OPERATING_SYSTEM_WINDOWS 1
+#else
+# error "Unsupported OS."
+#endif
+
+#if !defined(OPERATING_SYSTEM_LINUX)
+# define OPERATING_SYSTEM_LINUX 0
+#endif
+#if !defined(OPERATING_SYSTEM_WINDOWS)
+# define OPERATING_SYSTEM_WINDOWS 0
+#endif
+
+// compiler builtins
+#if COMPILER_CLANG || COMPILER_GCC
+# ifndef __has_builtin
+# define __has_builtin(x) 0
+# endif
+#endif
+
+#define IMPLEMENTATION_UNSIGNED_CHAR (CHAR_MIN == 0)
+
+// freestanding headers
+#include <float.h>
+#include <limits.h>
+#include <stdalign.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdnoreturn.h>
+
+// preprocessor improvement
+#define AM__STRINGIFY(S) #S
+#define AM__GLUE(A, B) A##B
+#define AM_STRINGIFY(S) AM__STRINGIFY(S)
+#define AM_GLUE(A, B) AM__GLUE((A), (B))
+
+// assert
+#define static_assert(expr) _Static_assert((expr), "")
+
+#if !defined(AM_ENABLE_ASSERT)
+# define AM_ENABLE_ASSERT 0
+#endif
+
+#if AM_ENABLE_ASSERT
+# if !defined(AM_ASSERT_FAIL)
+# if __has_builtin(__builtin_trap)
+# define AM_ASSERT_FAIL(expr, file, line, func) __builtin_trap()
+# else
+# error "Must define implementation of AM_ASSERT_FAIL(expr, file, line, func)."
+# endif
+# endif
+# define assert(x) ((void)((x) || (AM_ASSERT_FAIL(AM_STRINGIFY(x), __FILE__, __LINE__, __func__),0)))
+#else
+# define assert(c) ((void)0)
+#endif
+
+#define AM_UNREACHABLE assert(false && "Unreachable code reached")
+
+// utility macros
+#define ALIGN_UP_POW_2(x, p) (((x) + (p) - 1) & ~((p) - (1)))
+#define ALIGN_DOWN_POW_2(x, p) ((x) & ~((p) - 1))
+#define ARRAY_COUNT(a) (sizeof(a)/sizeof(*(a)))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define CLAMP(a, x, b) (((x) < (a)) ? (a) : (((b) < (x)) ? (b) : (x)))
+#define CLAMP_TOP(a, b) MIN((a), (b))
+#define CLAMP_BOT(a, b) MAX((a), (b))
+#define UNUSED(p) (void)(p)
+
+// basic types
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef size_t usz;
+typedef float f32;
+typedef double f64;
+
+#define global static
+#define local_persist static
+#define internal static
+
+// sanity checks
+static_assert(CHAR_BIT == 8);
+
+#endif // AM_BASE_H
diff --git a/2021/am_list.h b/2021/am_list.h
@@ -0,0 +1,233 @@
+#ifndef AM_LIST_H
+#define AM_LIST_H
+
+#define DLL_APPEND_NP(f, l, n, next, prev) \
+ ((f) == NULL \
+ ? ((f) = (l) = (n) \
+ , (f)->prev = (n)->next = NULL) \
+ : ((n)->prev = (l) \
+ , (l)->next = (n) \
+ , (l) = (n) \
+ , (n)->next = NULL))
+
+#define DLL_REMOVE_NP(f, l, n, next, prev) \
+ ((f) == (l) && (f) == (n) \
+ ? ((f) = (l) = NULL) \
+ : ((f) == (n) \
+ ? ((f) = (f)->next \
+ , (f)->prev = NULL) \
+ : ((l) == (n) \
+ ? ((l) = (l)->prev \
+ , (l)->next = NULL) \
+ : ((n)->prev->next = (n)->next \
+ , (n)->next->prev = (n)->prev))))
+
+#define SLL_QUEUE_PUSH_N(f, l, n, next) \
+ ((f) == NULL \
+ ? ((f) = (l) = (n)) \
+ : ((l)->next = (n) \
+ , (l) = (n) \
+ , (n)->next = NULL))
+
+#define SLL_QUEUE_PUSH_FRONT_N(f, l, n, next) \
+ ((f) == NULL \
+ ? ((f) = (l) = (n) \
+ , (n)->next = NULL) \
+ : ((n)->next = (f) \
+ , (f) = (n)))
+
+// TODO: It's maybe somewhat surprising to the user that these pop functions
+// don't return the popped node.
+#define SLL_QUEUE_POP_N(f, l, next) \
+ ((f) == (l) \
+ ? ((f) = (l) = NULL) \
+ : ((f) = (f)->next))
+
+
+#define SLL_STACK_PUSH_N(f, n, next) ((n)->next = (f), (f) = (n))
+
+#define SLL_STACK_POP_N(f, next) \
+ ((f) == NULL \
+ ? 0 \
+ : ((f) = (f)->next))
+
+#define DLL_APPEND(f, l, n) DLL_APPEND_NP((f), (l), (n), next, prev)
+#define DLL_PREPEND(f, l, n) DLL_APPEND_NP((l), (f), (n), prev, next)
+#define DLL_REMOVE(f, l, n) DLL_REMOVE_NP((f), (l), (n), next, prev)
+
+#define SLL_QUEUE_PUSH(f, l, n) SLL_QUEUE_PUSH_N((f), (l), (n), next)
+#define SLL_QUEUE_PUSH_FRONT(f, l, n) SLL_QUEUE_PUSH_FRONT_N((f), (l), (n), next)
+#define SLL_QUEUE_POP(f, l) SLL_QUEUE_POP_N((f), (l), next)
+
+#define SLL_STACK_PUSH(f, n) SLL_STACK_PUSH_N((f), (n), next)
+#define SLL_STACK_POP(f) SLL_STACK_POP_N((f), next)
+
+#if defined(AM_INCLUDE_TESTS)
+typedef struct TestNode TestNode;
+struct TestNode {
+ TestNode *next;
+ TestNode *prev;
+ s32 val;
+};
+
+internal void am_list_test(void) {
+ TestNode nodes[10] = {0};
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ nodes[i].val = i;
+ }
+
+ {
+ TestNode *first = NULL;
+ TestNode *last = NULL;
+
+ printf("dll append and remove from front\n");
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ DLL_APPEND(first, last, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf(" <|> ");
+ for (TestNode *n = last; n; n = n->prev) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ DLL_REMOVE(first, last, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf(" <|> ");
+ for (TestNode *n = last; n; n = n->prev) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ printf("dll prepend and remove from back\n");
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ DLL_PREPEND(first, last, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf(" <|> ");
+ for (TestNode *n = last; n; n = n->prev) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ DLL_REMOVE(first, last, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf(" <|> ");
+ for (TestNode *n = last; n; n = n->prev) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ printf("dll append and remove from middle\n");
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ DLL_APPEND(first, last, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf(" <|> ");
+ for (TestNode *n = last; n; n = n->prev) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ DLL_REMOVE(first, last, &nodes[(i + (ARRAY_COUNT(nodes) / 2)) % ARRAY_COUNT(nodes)]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf(" <|> ");
+ for (TestNode *n = last; n; n = n->prev) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+ }
+
+ {
+ TestNode *first = NULL;
+ TestNode *last = NULL;
+
+ printf("sll queue push and pop\n");
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ SLL_QUEUE_PUSH(first, last, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ while (first) {
+ SLL_QUEUE_POP(first, last);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ printf("sll queue push front and pop\n");
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ SLL_QUEUE_PUSH_FRONT(first, last, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ while (first) {
+ SLL_QUEUE_POP(first, last);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+ }
+
+ {
+ TestNode *first = NULL;
+
+ printf("sll stack push and pop\n");
+ for (size_t i = 0; i < ARRAY_COUNT(nodes); i++) {
+ SLL_STACK_PUSH(first, &nodes[i]);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+
+ while (first) {
+ SLL_STACK_POP(first);
+ printf("[");
+ for (TestNode *n = first; n; n = n->next) {
+ printf(" %i ", n->val);
+ }
+ printf("]\n");
+ }
+ }
+}
+#endif // defined(AM_INCLUDE_TESTS)
+
+#endif // AM_LIST_H
diff --git a/2021/am_memory.h b/2021/am_memory.h
@@ -0,0 +1,178 @@
+#ifndef AM_MEMORY_H
+#define AM_MEMORY_H
+
+#define MEM_KIB(b) ((u64)(b) << 10)
+#define MEM_MIB(b) ((u64)(b) << 20)
+#define MEM_GIB(b) ((u64)(b) << 30)
+
+#define AM_MEM_RESERVE_FN(name) void *(name)(void *ctx, u64 size)
+typedef AM_MEM_RESERVE_FN(am_mem_reserve_fn);
+
+#define AM_MEM_CHANGE_FN(name) void (name)(void *ctx, void *ptr, u64 size)
+typedef AM_MEM_CHANGE_FN(am_mem_change_fn);
+
+typedef struct {
+ am_mem_reserve_fn* reserve;
+ am_mem_change_fn* commit;
+ am_mem_change_fn* decommit;
+ am_mem_change_fn* release;
+ void *ctx;
+} BaseAllocator;
+
+#define AM_MEM_ARENA_COMMIT_BLOCK_SIZE MEM_MIB(64)
+#define AM_MEM_ARENA_DEFAULT_RESERVE_SIZE MEM_GIB(1)
+
+typedef struct {
+ BaseAllocator *base;
+ u8 *mem;
+ u64 cap;
+ u64 pos;
+ u64 commit_pos;
+} MemArena;
+
+internal AM_MEM_CHANGE_FN(am_mem_change_noop) {
+ UNUSED(ctx);
+ UNUSED(ptr);
+ UNUSED(size);
+}
+
+internal AM_MEM_RESERVE_FN(am_mem_reserve_malloc) {
+ UNUSED(ctx);
+ return malloc(size);
+}
+
+internal AM_MEM_CHANGE_FN(am_mem_release_malloc) {
+ UNUSED(ctx);
+ UNUSED(size);
+ free(ptr);
+}
+
+internal BaseAllocator *am_mem_base_allocator_malloc(void) {
+ local_persist BaseAllocator b;
+ if (!b.reserve) {
+ b = (BaseAllocator) {
+ .reserve = am_mem_reserve_malloc,
+ .commit = am_mem_change_noop,
+ .decommit = am_mem_change_noop,
+ .release = am_mem_release_malloc,
+ };
+ }
+ return &b;
+}
+
+internal MemArena am_mem_arena_create_reserve(BaseAllocator *base, u64 reserve_size) {
+ MemArena a = {
+ .base = base,
+ };
+ a.mem = a.base->reserve(a.base->ctx, reserve_size);
+ a.cap = reserve_size;
+ return a;
+}
+
+internal MemArena am_mem_arena_create(BaseAllocator *base) {
+ return am_mem_arena_create_reserve(base, AM_MEM_ARENA_DEFAULT_RESERVE_SIZE);
+}
+
+internal void *am_mem_arena_push(MemArena *a, u64 size) {
+ void *result = NULL;
+ if (a->mem + size <= a->mem + a->cap) {
+ result = a->mem + a->pos;
+ a->pos += size;
+
+ if (a->pos > a->commit_pos) {
+ u64 aligned = ALIGN_UP_POW_2(a->pos, AM_MEM_ARENA_COMMIT_BLOCK_SIZE);
+ u64 next_commit_pos = CLAMP_TOP(aligned, a->cap);
+ u64 commit_size = next_commit_pos - a->commit_pos;
+ a->base->commit(a->base->ctx, a->mem + a->commit_pos, commit_size);
+ a->commit_pos = next_commit_pos;
+ }
+ }
+ return result;
+}
+
+#define AM_MEM_ARENA_PUSH_ARRAY(arena, T, count) (am_mem_arena_push((arena), sizeof(T) * (count)))
+
+internal void am_mem_arena_pop_to(MemArena *a, u64 pos) {
+ if (pos < a->pos) {
+ a->pos = pos;
+
+ u64 aligned = ALIGN_UP_POW_2(a->pos, AM_MEM_ARENA_COMMIT_BLOCK_SIZE);
+ u64 next_commit_pos = CLAMP_TOP(aligned, a->cap);
+ if (next_commit_pos < a->commit_pos) {
+ u64 decommit_size = a->commit_pos - next_commit_pos;
+ a->base->decommit(a->base->ctx, a->mem + a->commit_pos, decommit_size);
+ a->commit_pos = next_commit_pos;
+ }
+ }
+}
+
+internal void am_mem_arena_release(MemArena *a) {
+ a->base->release(a->base->ctx, a->mem, a->cap);
+ *a = (MemArena){0};
+}
+
+// TODO: SIMD
+internal void am_mem_copy(void *dst, void *src, u64 size) {
+ for (u64 i = 0; i < size; i++) {
+ ((u8 *)dst)[i] = ((u8 *)src)[i];
+ }
+}
+
+internal bool am_mem_equal(void *dst, void *src, u64 size) {
+ for (u64 i = 0; i < size; i++) {
+ if (((u8 *)dst)[i] != ((u8 *)src)[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+#if defined(AM_INCLUDE_TESTS)
+internal void am_memory_test(void) {
+ assert(MEM_KIB(10) == 10240);
+ assert(MEM_MIB(10) == 10485760);
+ assert(MEM_GIB(10) == 10737418240);
+
+ {
+ BaseAllocator *a = am_mem_base_allocator_malloc();
+ u64 num_test_ints = 10;
+ s32 *int_buf = a->reserve(NULL, num_test_ints * sizeof(s32));
+ assert(int_buf);
+ a->release(NULL, int_buf, 0);
+ }
+
+ {
+ MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc());
+ am_mem_arena_push(&a, 1020);
+ assert(a.pos == 1020);
+ u64 p = a.pos;
+ u64 cp = a.commit_pos;
+
+ AM_MEM_ARENA_PUSH_ARRAY(&a, u8, a.cap - a.pos);
+ assert(a.pos == a.cap);
+ assert(a.commit_pos == a.cap);
+
+ am_mem_arena_pop_to(&a, p);
+ assert(a.pos == p);
+ assert(a.commit_pos == cp);
+
+ am_mem_arena_release(&a);
+ assert(a.pos == 0);
+ assert(a.commit_pos == 0);
+ assert(a.mem == NULL);
+ }
+
+ {
+ u8 src[10] = {0};
+ u8 dst[10] = {0};
+ for (u64 i = 0; i < ARRAY_COUNT(src); i++) {
+ src[i] = i;
+ }
+
+ am_mem_copy(dst, src, ARRAY_COUNT(dst));
+ assert(am_mem_equal(dst, src, ARRAY_COUNT(dst)));
+ }
+}
+#endif // defined(AM_INCLUDE_TESTS)
+
+#endif // AM_MEMORY_H
diff --git a/2021/am_string.h b/2021/am_string.h
@@ -0,0 +1,252 @@
+#ifndef AM_STRING_H
+#define AM_STRING_H
+
+#ifndef AM_MEMORY_H
+ #error "am_memory.h is required"
+#endif
+#ifndef AM_LIST_H
+ #error "am_list.h is required"
+#endif
+
+typedef struct {
+ usz size;
+ u8 *str;
+} Str;
+
+typedef struct StrListNode StrListNode;
+struct StrListNode {
+ StrListNode *next;
+ Str s;
+};
+
+typedef struct {
+ StrListNode *first;
+ StrListNode *last;
+ u64 node_count;
+ u64 total_size;
+} StrList;
+
+#define AM_STR_LIT(s) (Str) { .str = (u8 *)(s), .size = sizeof(s) - 1, }
+#define AM_STR_EXPAND(s) (s32)((s).size), ((s).str)
+
+internal usz am_cstr_len(char *cstr) {
+ usz len = 0;
+ while (cstr && *cstr != '\0') {
+ len++;
+ cstr++;
+ }
+ return len;
+}
+
+internal Str am_str(u8 *str, usz size) {
+ return (Str) { .size = size, .str = str, };
+}
+
+internal Str am_str_from_range(u8 *start, u8 *opl) {
+ assert(start < opl);
+ return am_str(start, opl - start);
+}
+
+internal Str am_str_from_cstr(char *cstr, usz len) {
+ return am_str((u8 *)cstr, len);
+}
+
+// TODO: Use string interning
+internal bool am_str_eq(Str s1, Str s2) {
+ if (s1.size != s2.size) {
+ return false;
+ }
+
+ for (usz i = 0; i < s1.size; i++) {
+ if (s1.str[i] != s2.str[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+internal bool am_cstr_eq(char *cstr1, char *cstr2) {
+ usz len1 = am_cstr_len(cstr1);
+ usz len2 = am_cstr_len(cstr2);
+ return am_str_eq(am_str_from_cstr(cstr1, len1), am_str_from_cstr(cstr2, len2));
+}
+
+internal Str am_str_line(Str s, u8 *cursor) {
+ u8 *opl = s.str + s.size;
+
+ assert(cursor >= s.str && cursor < opl);
+
+ u8 *end = cursor;
+ while (end < opl) {
+ if (*end == '\n') {
+ break;
+ }
+ end++;
+ }
+
+ u8 *beginning = cursor - (*cursor == '\n');
+ while (beginning >= s.str) {
+ if (*beginning == '\n') {
+ beginning++;
+ break;
+ }
+ beginning--;
+ }
+
+ return am_str_from_range(beginning, end);
+}
+
+internal bool am_str_contains(Str s, char c) {
+ for (usz i = 0; i < s.size; i++) {
+ if (s.str[i] == c) {
+ return true;
+ }
+ }
+ return false;
+}
+
+internal bool am_cstr_contains(char *s, usz len, char c) {
+ return am_str_contains(am_str_from_cstr(s, len), c);
+}
+
+internal bool am_str_cstr_eq(Str s, char *cstr) {
+ return am_str_eq(s, am_str_from_cstr(cstr, am_cstr_len(cstr)));
+}
+
+internal void am_str_list_append(MemArena *arena, StrList *list, Str s) {
+ StrListNode *node = am_mem_arena_push(arena, sizeof(StrListNode));
+ *node = (StrListNode) {
+ .s = s,
+ };
+ SLL_QUEUE_PUSH(list->first, list->last, node);
+ list->node_count += 1;
+ list->total_size += s.size;
+}
+
+typedef struct {
+ Str pre;
+ Str mid;
+ Str post;
+} StringJoinOptions;
+
+internal Str am_str_join(MemArena *arena, StrList *list, StringJoinOptions *options) {
+ StringJoinOptions join;
+ if (options) {
+ join = *options;
+ } else {
+ join = (StringJoinOptions){0};
+ }
+
+ u64 total_size = list->total_size
+ + join.pre.size
+ + (join.mid.size * (list->node_count - 1))
+ + join.post.size;
+
+ Str s= {
+ .str = AM_MEM_ARENA_PUSH_ARRAY(arena, u8, total_size),
+ .size = total_size,
+ };
+
+ u8 *p = s.str;
+ am_mem_copy(p, join.pre.str, join.pre.size);
+ p += join.pre.size;
+
+ bool is_mid = false;
+ for (StrListNode *n = list->first; n; n = n->next) {
+ if (is_mid) {
+ am_mem_copy(p, join.mid.str, join.mid.size);
+ p += join.mid.size;
+ }
+
+ am_mem_copy(p, n->s.str, n->s.size);
+ p += n->s.size;
+
+ is_mid = true;
+ }
+
+ am_mem_copy(p, join.post.str, join.post.size);
+ p += join.post.size;
+
+ return s;
+}
+
+internal StrList am_str_split(MemArena *arena, Str s, u8 *split_chars, u64 split_char_count) {
+ StrList list = {0};
+
+ u8 *cursor = s.str;
+ u8 *split_beginning = cursor;
+ u8 *opl = s.str + s.size;
+ while (cursor < opl) {
+ bool split_byte = false;
+ for (u64 i = 0; i < split_char_count; i++) {
+ if (split_chars[i] == *cursor) {
+ split_byte = true;
+ }
+ }
+
+ if (split_byte) {
+ if (split_beginning < cursor) {
+ am_str_list_append(arena, &list, am_str_from_range(split_beginning, cursor));
+ }
+ split_beginning = cursor + 1;
+ }
+ cursor++;
+ }
+
+ return list;
+}
+
+#if defined(AM_INCLUDE_TESTS)
+internal void am_string_test(void) {
+ assert(am_cstr_len("abcdefg") == 7);
+ assert(am_cstr_len("") == 0);
+ assert(am_cstr_len("\0") == 0);
+ assert(am_cstr_eq("", ""));
+ assert(am_cstr_eq("\0", "\0"));
+ assert(am_cstr_eq("abc", "abc"));
+ assert(!am_cstr_eq("ABC", "abc"));
+ assert(!am_cstr_eq("", " "));
+ assert(!am_cstr_eq("abc", "abcde"));
+ assert(!am_str_cstr_eq(AM_STR_LIT("abcd"), "abc"));
+ assert(am_str_cstr_eq(AM_STR_LIT("abc"), "abc"));
+ assert(am_cstr_contains("abc", 3, 'c'));
+ assert(am_cstr_contains("a c", 3, ' '));
+ assert(am_cstr_contains("", 1, '\0'));
+ assert(!am_cstr_contains("abc", 3, 'z'));
+ assert(!am_cstr_contains("", 0, 'z'));
+ assert(!am_cstr_contains("", 0, '\0'));
+ assert(am_cstr_contains("https://www.example.com", 23, '/'));
+
+ {
+ StrList l = {0};
+ MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc());
+ Str strings[] = {
+ AM_STR_LIT("one"),
+ AM_STR_LIT("two"),
+ AM_STR_LIT("three"),
+ };
+
+ for (u64 i = 0; i < ARRAY_COUNT(strings); i++) {
+ am_str_list_append(&a, &l, strings[i]);
+ }
+
+ Str joined = am_str_join(&a, &l, &(StringJoinOptions){
+ .pre = AM_STR_LIT("Joined: '"),
+ .mid = AM_STR_LIT(", "),
+ .post = AM_STR_LIT("'."),
+ });
+
+ printf("%.*s\n", AM_STR_EXPAND(joined));
+
+ StrList split = am_str_split(&a, AM_STR_LIT(", one, two, three, "), (u8 *)", ", 2);
+
+ for (StrListNode *n = split.first; n; n = n->next) {
+ printf("split: '%.*s'\n", AM_STR_EXPAND(n->s));
+ }
+ am_mem_arena_release(&a);
+ }
+}
+#endif // defined(AM_INCLUDE_TESTS)
+
+#endif // AM_STRING_H
diff --git a/2021/day01_01.c b/2021/day01_01.c
@@ -0,0 +1,76 @@
+#if 0
+# Self-building c file. Invoke like: `./file.c`
+outdir=out
+input=$(basename "$0")
+output="$outdir"/$(basename "$0" .c)
+if [ "$input" -nt "$output" ];
+then
+ mkdir --parents "$outdir" || exit
+ echo "Building ${output}." || exit
+ clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit
+fi
+if [ "$1" = "-r" ];
+then
+ ./"$output" "$@"
+fi
+exit
+#endif
+
+#include <inttypes.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+_Noreturn void assert_fail(const char *expr, const char *file, int line, const char *func) {
+ fprintf(stderr, "%s:%d: %s: Assertion failed: '%s'\n", file, line, func, expr);
+ abort();
+}
+
+#define AM_ENABLE_ASSERT 1
+#define AM_ASSERT_FAIL(expr, file, line, func) assert_fail(expr, file, line, func)
+#include "am_base.h"
+#include "am_memory.h"
+#include "am_list.h"
+#include "am_string.h"
+
+Str open_file(MemArena *arena, char *path) {
+ FILE *f = fopen(path, "r");
+ assert(f);
+
+ s32 error = fseek(f, 0L, SEEK_END);
+ assert(!error);
+
+ s64 size = ftell(f);
+ assert(size >= 0);
+ rewind(f);
+
+ u8 *buf = am_mem_arena_push(arena, size);
+ assert(buf);
+
+ size_t items_read = fread(buf, 1, size, f);
+ assert(items_read == (size_t)size);
+
+ error = fclose(f);
+ assert(!error);
+
+ return am_str(buf, size);
+}
+
+int main(void) {
+ MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc());
+ Str input = open_file(&a, "day01_input.txt");
+ StrList lines = am_str_split(&a, input, (u8 *)"\n", 1);
+ u64 increase_count = 0;
+ u64 previous_number = UINT64_MAX;
+ for (StrListNode *line = lines.first; line; line = line->next) {
+ u64 number = 0;
+ for (usz i = 0; i < line->s.size; i++) {
+ u64 digit = line->s.str[i] - '0';
+ number = (number * 10) + digit;
+ }
+ increase_count += (number > previous_number);
+ previous_number = number;
+ }
+ printf("Increase Count: %" PRIu64 "\n", increase_count);
+ am_mem_arena_release(&a);
+ return 0;
+}
diff --git a/2021/day01_input.txt b/2021/day01_input.txt
@@ -0,0 +1,2000 @@
+149
+163
+165
+160
+179
+184
+186
+199
+207
+210
+211
+212
+228
+241
+242
+265
+269
+271
+287
+286
+295
+296
+293
+300
+301
+302
+304
+308
+320
+322
+321
+333
+350
+345
+348
+347
+351
+348
+349
+345
+353
+366
+376
+384
+387
+390
+391
+378
+382
+394
+409
+411
+415
+419
+424
+425
+427
+428
+436
+445
+446
+459
+464
+478
+479
+493
+492
+493
+482
+484
+491
+492
+497
+501
+506
+509
+521
+526
+527
+539
+546
+547
+551
+562
+567
+568
+573
+590
+591
+596
+612
+613
+618
+620
+593
+594
+596
+597
+596
+612
+616
+618
+620
+621
+622
+611
+612
+613
+610
+615
+616
+634
+647
+654
+655
+656
+657
+659
+676
+678
+675
+703
+715
+722
+738
+747
+760
+765
+771
+784
+789
+792
+769
+770
+773
+762
+772
+817
+823
+825
+864
+863
+849
+852
+862
+868
+893
+895
+896
+925
+946
+945
+946
+945
+964
+954
+962
+969
+976
+1004
+1007
+1015
+1029
+1037
+1043
+1048
+1070
+1080
+1100
+1097
+1094
+1102
+1099
+1098
+1099
+1096
+1097
+1117
+1123
+1124
+1125
+1127
+1119
+1121
+1137
+1173
+1174
+1179
+1181
+1200
+1204
+1175
+1179
+1180
+1189
+1194
+1195
+1197
+1199
+1206
+1200
+1208
+1211
+1213
+1214
+1229
+1230
+1271
+1278
+1279
+1282
+1288
+1285
+1291
+1290
+1294
+1297
+1299
+1300
+1320
+1324
+1323
+1328
+1329
+1330
+1331
+1334
+1337
+1311
+1313
+1314
+1320
+1323
+1318
+1323
+1331
+1339
+1340
+1328
+1334
+1336
+1342
+1343
+1350
+1357
+1359
+1377
+1378
+1384
+1368
+1369
+1371
+1380
+1360
+1349
+1374
+1373
+1376
+1372
+1382
+1384
+1391
+1393
+1399
+1403
+1404
+1419
+1427
+1425
+1454
+1455
+1458
+1459
+1479
+1484
+1485
+1487
+1492
+1497
+1499
+1496
+1503
+1528
+1543
+1535
+1546
+1547
+1549
+1546
+1547
+1549
+1550
+1553
+1581
+1583
+1598
+1616
+1618
+1640
+1638
+1655
+1686
+1685
+1671
+1674
+1680
+1673
+1675
+1676
+1673
+1674
+1679
+1681
+1689
+1701
+1702
+1708
+1722
+1723
+1727
+1739
+1742
+1743
+1756
+1759
+1763
+1767
+1768
+1772
+1771
+1775
+1783
+1784
+1794
+1796
+1815
+1811
+1812
+1822
+1820
+1836
+1825
+1828
+1826
+1827
+1832
+1844
+1847
+1854
+1855
+1857
+1864
+1854
+1869
+1868
+1867
+1868
+1872
+1875
+1876
+1880
+1874
+1875
+1876
+1877
+1881
+1882
+1897
+1898
+1903
+1904
+1906
+1904
+1911
+1908
+1909
+1930
+1929
+1928
+1948
+1958
+1963
+1964
+1967
+1971
+1960
+1958
+1968
+1969
+1972
+1973
+1974
+1980
+1981
+1992
+1993
+1999
+1998
+1997
+1996
+1997
+2008
+2007
+1987
+1991
+1992
+1998
+2006
+2007
+2014
+2017
+2022
+2027
+2017
+2020
+2048
+2049
+2050
+2054
+2055
+2067
+2072
+2089
+2075
+2076
+2077
+2078
+2085
+2086
+2088
+2091
+2086
+2094
+2102
+2103
+2105
+2107
+2109
+2111
+2124
+2125
+2127
+2130
+2131
+2133
+2136
+2147
+2148
+2153
+2152
+2158
+2157
+2164
+2165
+2167
+2166
+2200
+2201
+2200
+2206
+2207
+2197
+2208
+2209
+2211
+2217
+2235
+2236
+2243
+2233
+2226
+2238
+2244
+2237
+2232
+2229
+2233
+2242
+2239
+2240
+2241
+2242
+2247
+2248
+2260
+2276
+2273
+2275
+2301
+2317
+2340
+2341
+2328
+2332
+2326
+2322
+2323
+2330
+2334
+2351
+2352
+2360
+2370
+2371
+2370
+2377
+2378
+2381
+2392
+2406
+2385
+2392
+2397
+2395
+2393
+2397
+2395
+2414
+2418
+2424
+2429
+2431
+2455
+2456
+2468
+2478
+2483
+2485
+2484
+2485
+2486
+2475
+2484
+2493
+2494
+2513
+2519
+2529
+2530
+2535
+2537
+2555
+2540
+2541
+2539
+2533
+2534
+2543
+2548
+2551
+2557
+2561
+2563
+2565
+2600
+2601
+2595
+2594
+2609
+2613
+2587
+2591
+2598
+2604
+2564
+2568
+2570
+2576
+2575
+2577
+2595
+2602
+2605
+2613
+2615
+2606
+2601
+2600
+2598
+2599
+2601
+2603
+2617
+2623
+2625
+2626
+2638
+2641
+2642
+2636
+2637
+2630
+2617
+2619
+2616
+2615
+2624
+2633
+2635
+2663
+2666
+2668
+2671
+2672
+2675
+2685
+2686
+2697
+2702
+2704
+2723
+2724
+2729
+2716
+2718
+2727
+2731
+2770
+2761
+2778
+2800
+2801
+2798
+2799
+2800
+2801
+2798
+2794
+2795
+2835
+2836
+2845
+2848
+2858
+2873
+2874
+2892
+2906
+2898
+2927
+2933
+2936
+2940
+2948
+2950
+2945
+2947
+2957
+2949
+2950
+2951
+2957
+2959
+2960
+2962
+2978
+2982
+2983
+2986
+3000
+3002
+3004
+3005
+3002
+3009
+3022
+3009
+3002
+3003
+3022
+3037
+3040
+3041
+3042
+3044
+3045
+3049
+3053
+3057
+3060
+3061
+3059
+3060
+3070
+3071
+3072
+3075
+3076
+3081
+3084
+3081
+3080
+3086
+3098
+3099
+3100
+3105
+3107
+3113
+3121
+3126
+3131
+3136
+3145
+3150
+3153
+3154
+3156
+3157
+3165
+3154
+3155
+3156
+3169
+3176
+3191
+3188
+3190
+3197
+3199
+3221
+3254
+3262
+3263
+3259
+3258
+3259
+3267
+3266
+3268
+3263
+3268
+3269
+3291
+3295
+3294
+3326
+3327
+3335
+3327
+3343
+3346
+3369
+3368
+3372
+3375
+3379
+3386
+3395
+3396
+3397
+3409
+3412
+3416
+3418
+3419
+3418
+3417
+3414
+3424
+3425
+3430
+3431
+3433
+3434
+3435
+3421
+3422
+3424
+3425
+3416
+3429
+3423
+3432
+3444
+3451
+3468
+3469
+3468
+3470
+3471
+3472
+3473
+3471
+3483
+3486
+3495
+3496
+3501
+3505
+3496
+3497
+3507
+3512
+3515
+3519
+3523
+3524
+3525
+3524
+3549
+3551
+3525
+3526
+3534
+3536
+3542
+3545
+3548
+3527
+3529
+3528
+3553
+3555
+3560
+3561
+3580
+3582
+3579
+3582
+3586
+3584
+3588
+3564
+3572
+3568
+3567
+3565
+3583
+3575
+3579
+3581
+3589
+3605
+3613
+3615
+3617
+3643
+3645
+3652
+3654
+3653
+3654
+3659
+3656
+3659
+3653
+3651
+3654
+3657
+3675
+3677
+3679
+3707
+3710
+3717
+3755
+3758
+3759
+3761
+3766
+3768
+3759
+3761
+3762
+3790
+3791
+3793
+3797
+3784
+3785
+3786
+3787
+3790
+3792
+3784
+3789
+3792
+3795
+3789
+3790
+3797
+3783
+3795
+3792
+3801
+3804
+3806
+3810
+3808
+3813
+3793
+3797
+3802
+3810
+3822
+3825
+3830
+3839
+3838
+3837
+3838
+3839
+3840
+3841
+3842
+3862
+3870
+3871
+3886
+3887
+3890
+3882
+3890
+3884
+3885
+3907
+3914
+3926
+3934
+3935
+3944
+3954
+3946
+3951
+3954
+3957
+3958
+3970
+3981
+3988
+3985
+3988
+3989
+3982
+3978
+3979
+3980
+3981
+4001
+4002
+4011
+4016
+4021
+4026
+4024
+4027
+4043
+4044
+4062
+4066
+4069
+4067
+4087
+4099
+4097
+4091
+4093
+4090
+4088
+4094
+4100
+4108
+4109
+4105
+4121
+4138
+4141
+4144
+4145
+4154
+4153
+4156
+4157
+4153
+4151
+4157
+4161
+4162
+4163
+4165
+4162
+4171
+4170
+4177
+4192
+4202
+4203
+4204
+4213
+4217
+4218
+4220
+4221
+4222
+4228
+4258
+4259
+4261
+4262
+4263
+4267
+4269
+4277
+4279
+4278
+4256
+4258
+4277
+4301
+4297
+4336
+4315
+4301
+4302
+4299
+4291
+4294
+4295
+4297
+4291
+4292
+4297
+4303
+4313
+4319
+4327
+4312
+4311
+4316
+4321
+4323
+4335
+4337
+4338
+4348
+4343
+4344
+4345
+4327
+4329
+4331
+4334
+4355
+4356
+4352
+4360
+4366
+4376
+4383
+4391
+4373
+4388
+4376
+4372
+4369
+4366
+4376
+4392
+4397
+4398
+4406
+4405
+4420
+4427
+4426
+4423
+4419
+4420
+4418
+4420
+4418
+4423
+4427
+4428
+4430
+4419
+4420
+4421
+4417
+4418
+4435
+4434
+4448
+4449
+4450
+4451
+4456
+4453
+4456
+4480
+4481
+4504
+4512
+4519
+4527
+4530
+4529
+4530
+4549
+4569
+4572
+4579
+4578
+4583
+4587
+4599
+4604
+4619
+4618
+4619
+4627
+4628
+4626
+4627
+4629
+4628
+4632
+4635
+4636
+4669
+4681
+4684
+4681
+4683
+4682
+4686
+4690
+4689
+4690
+4692
+4695
+4696
+4692
+4691
+4722
+4721
+4720
+4721
+4732
+4735
+4734
+4737
+4736
+4739
+4744
+4775
+4790
+4796
+4769
+4770
+4763
+4765
+4787
+4804
+4792
+4794
+4795
+4793
+4794
+4799
+4817
+4828
+4842
+4844
+4849
+4852
+4876
+4877
+4892
+4896
+4906
+4907
+4910
+4922
+4927
+4930
+4933
+4934
+4935
+4940
+4938
+4951
+4966
+4975
+4987
+4988
+4991
+4992
+4996
+5001
+5002
+5014
+5026
+5031
+5035
+5038
+5037
+5038
+5048
+5049
+5072
+5074
+5100
+5101
+5107
+5116
+5115
+5127
+5125
+5134
+5136
+5140
+5143
+5150
+5148
+5178
+5179
+5181
+5186
+5187
+5191
+5202
+5204
+5202
+5206
+5217
+5214
+5224
+5221
+5236
+5231
+5232
+5235
+5226
+5230
+5231
+5210
+5219
+5223
+5224
+5225
+5229
+5230
+5239
+5254
+5261
+5262
+5265
+5261
+5262
+5263
+5270
+5275
+5274
+5270
+5267
+5263
+5265
+5289
+5290
+5298
+5300
+5303
+5301
+5302
+5305
+5319
+5324
+5348
+5351
+5355
+5356
+5354
+5365
+5359
+5356
+5357
+5380
+5378
+5395
+5403
+5413
+5422
+5421
+5431
+5430
+5446
+5458
+5462
+5466
+5467
+5471
+5472
+5471
+5486
+5494
+5495
+5497
+5500
+5520
+5522
+5525
+5529
+5562
+5563
+5566
+5569
+5572
+5586
+5592
+5594
+5595
+5598
+5603
+5587
+5588
+5592
+5595
+5596
+5605
+5626
+5628
+5629
+5632
+5637
+5639
+5643
+5647
+5629
+5634
+5642
+5643
+5651
+5646
+5662
+5663
+5675
+5677
+5684
+5688
+5700
+5703
+5681
+5720
+5731
+5738
+5741
+5743
+5744
+5754
+5756
+5764
+5770
+5769
+5777
+5780
+5788
+5791
+5812
+5813
+5817
+5830
+5839
+5840
+5866
+5870
+5871
+5864
+5867
+5870
+5873
+5874
+5912
+5914
+5917
+5922
+5931
+5932
+5936
+5937
+5936
+5938
+5959
+5961
+5955
+5960
+5985
+5998
+5997
+5999
+6000
+6003
+6013
+6027
+6028
+6048
+6047
+6049
+6043
+6050
+6073
+6074
+6097
+6098
+6099
+6100
+6102
+6104
+6117
+6116
+6118
+6138
+6139
+6151
+6152
+6150
+6152
+6153
+6163
+6187
+6191
+6187
+6191
+6190
+6202
+6205
+6214
+6213
+6216
+6217
+6219
+6225
+6200
+6201
+6211
+6212
+6222
+6231
+6230
+6249
+6250
+6282
+6309
+6312
+6315
+6310
+6314
+6328
+6335
+6336
+6341
+6348
+6351
+6353
+6358
+6357
+6384
+6385
+6372
+6377
+6382
+6384
+6380
+6382
+6384
+6385
+6388
+6391
+6406
+6405
+6414
+6415
+6417
+6418
+6423
+6424
+6436
+6453
+6460
+6459
+6461
+6475
+6479
+6476
+6477
+6479
+6482
+6481
+6479
+6478
+6491
+6500
+6504
+6505
+6506
+6483
+6473
+6474
+6476
+6477
+6487
+6498
+6500
+6501
+6499
+6497
+6501
+6503
+6512
+6510
+6509
+6496
+6497
+6498
+6513
+6520
+6521
+6523
+6546
+6545
+6548
+6558
+6578
+6579
+6584
+6582
+6588
+6593
+6610
+6616
+6605
+6607
+6629
+6626
+6628
+6648
+6647
+6675
+6674
+6682
+6684
+6691
+6716
+6725
+6726
+6731
+6747
+6764
+6771
+6774
+6780
+6784
+6785
+6789
+6802
+6823
+6838
+6853
+6860
+6847
+6848
+6863
+6862
+6868
+6872
+6873
+6865
+6869
+6870
+6872
+6874
+6898
+6902
+6908
+6907
+6914
+6912
+6913
+6918
+6940
+6942
+6943
+6944
+6945
+6948
+6949
+6950
+6956
+6961
+6978
+6984
+7007
+7011
+7019
+7031
+7038
+7052
+7053
+7059
+7064
+7058
+7064
+7067
+7069
+7063
+7062
+7084
+7086
+7093
+7096
+7088
+7091
+7102
+7099
+7103
+7131
+7132
+7127
+7130
+7131
+7132
+7133
+7134
+7133
+7144
+7145
+7152
+7156
+7157
+7158
+7155
+7169
+7172
+7182
+7184
+7209
+7212
+7180
+7185
+7184
+7185
+7190
+7176
+7178
+7181
+7178
+7186
+7179
+7180
+7183
+7182
+7183
+7179
+7181
+7185
+7187
+7200
+7201
+7202
+7204
+7205
+7213
+7216
+7217
+7219
+7220
+7217
+7234
+7235
+7238
+7239
+7237
+7240
+7241
+7264
+7280
+7278
+7267
+7273
+7283
+7284
+7287
+7289
+7288
+7286
+7311
+7323
+7332
+7333
+7336
+7339
+7343
+7351
+7376
+7380
+7381
+7382
+7392
+7402
+7400
+7402
+7409
+7431
+7435
+7437
+7439
+7455
+7451
+7465
+7468
+7495
+7503
+7504
+7508
+7498
+7502
+7503
+7504
+7496
+7504
+7509
+7517
+7519
+7514
+7532
+7534
+7553
+7551
+7555
+7550
+7551
+7552
+7553
+7554
+7556
+7557
+7558
+7559
+7583
+7588
+7589
+7590
+7589
+7605
+7606
+7608
+7615
+7637
+7652
+7664
+7665
+7667
+7669
+7688
+7690
+7716
+7717
+7720
+7728
+7732
+7738
+7752
+7758
+7780
+7789
+7801
+7839
+7838
+7849
+7848
+7860
+7851
+7844
+7845
+7844
+7849
+7850
+7855
+7853
+7854
+7864
+7865
+7866
+7867
+7875
+7888
+7889
+7895
+7899
+7911
+7906
+7934
+7938
+7941
+7943
+7936
+7935
+7937
+7938
+7940
+7950
+7959
+7958
+7966
+7968
+7992
+7996
+7997
+7991
+7995
+7996
+8005
+8006
+8007
+8010
+8013
+8015
+8014
+8016
+8048
+8053
+8051
+8030
+8032
+8029
+8028
+8029
+8038
+8047
+8069
+8084
+8099
+8095
+8099
+8105
+8096
+8101
+8102
+8107
+8131
+8151
+8154
+8156
+8158
+8177
+8207
+8208
+8187
+8188
+8191
+8168
+8169
+8172
+8179
+8180
+8181
+8183
+8193
+8205
+8245
+8246
+8255
+8247
+8251
+8252
+8251
+8250
+8252
+8258
+8259
+8260
+8267
+8271
+8290
+8305
+8315
+8322
+8335
+8338
+8341
+8342
+8332
+8337
+8345
+8364
+8375
+8362
+8361
+8362
+8354
+8361
+8362
+8377
+8379
+8382
+8406
+8409
+8412
+8413
+8419
+8418
+8419
+8430
+8435
+8429
+8434
+8435
+8417
+8443
+8434
+8447
+8449
+8452
+8459
+8486
+8487
+8489
+8490
+8510
+8508
+8509
+8513
+8514
+8511
+8514
+8493
+8476
+8473
+8487
+8511
+8509
+8517
+8521
+8544
+8549
+8567
+8589
+8594
+8598
+8624
+8650
+8654
+8655
+8663
+8662
+8675
+8676
+8693
+8694
+8691
+8693
+8698
+8699
+8720
+8739
+8740
+8747
+8739
+8740
+8761
+8767
+8761
+8768
+8762
+8752
+8757
+8754
+8756
+8765
+8771
+8775
+8780
+8787
+8774
+8772
+8784
+8778
+8783
+8787
+8789
+8808
+8809
+8819
+8837
+8847
+8850
+8848
+8864
+8862
+8864
+8891
+8892
+8884
+8886
+8887
+8888
+8893
+8894
+8895