advent-of-code

Solutions for Advent of Code.
git clone git://git.amin.space/advent-of-code.git
Log | Files | Refs | LICENSE

commit 139a518977b7ab8394301ba008b29626bd3c06cd
parent 748af4eff54eaf7ac72479c7257d72b04f581153
Author: amin <dev@aminmesbah.com>
Date:   Wed, 21 Dec 2022 07:14:27 +0000

Solve 2022 day 1

FossilOrigin-Name: cfdb7e3e2d50cdead9b7106334accf0a860fed26a04e44e047c6e8da6c5f80cd
Diffstat:
A2022/am_base.h | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2022/am_list.h | 233+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2022/am_memory.h | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2022/am_string.h | 381+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2022/day01.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2022/day01_input.txt | 2269+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 3289 insertions(+), 0 deletions(-)

diff --git a/2022/am_base.h b/2022/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/2022/am_list.h b/2022/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) + +#ifdef AM_LIST_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 // AM_LIST_TESTS + +#endif // AM_LIST_H diff --git a/2022/am_memory.h b/2022/am_memory.h @@ -0,0 +1,185 @@ +#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) { + assert(dst); + for (u64 i = 0; i < size; i++) { + ((u8 *)dst)[i] = ((u8 *)src)[i]; + } +} + +internal void am_mem_set(u64 size, void *dst, u8 byte) { + assert(dst); + for (u64 i = 0; i < size; i++) { + ((u8 *)dst)[i] = byte; + } +} + +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; +} + +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++) { + assert(i < UINT8_MAX); + src[i] = (u8)i; + } + + am_mem_copy(dst, src, ARRAY_COUNT(dst)); + assert(am_mem_equal(dst, src, ARRAY_COUNT(dst))); + } +} + +#endif // AM_MEMORY_H diff --git a/2022/am_string.h b/2022/am_string.h @@ -0,0 +1,381 @@ +#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, (usz)(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; +} + +internal void am_str_list_discard_empty(StrList *list) { + assert(list); + if (list->node_count) { + StrListNode *previous = NULL; + + for (StrListNode *n = list->first; n; n = n->next) { + if (n->s.size == 0) { + assert(list->node_count > 0); + list->node_count--; + if (previous) { + previous->next = n->next; + } else { + list->first = n->next; + } + } else { + previous = n; + } + } + } +} + +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}; + } + + Str s = {0}; + + if (list->node_count) { + assert(list->node_count > 0); + + u64 total_size = list->total_size + + join.pre.size + + (join.mid.size * (list->node_count - 1)) + + join.post.size; + + s = (Str) { + .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; + break; + } + } + + if (split_byte) { + if (cursor == split_beginning) { + am_str_list_append(arena, &list, AM_STR_LIT("")); + } else { + am_str_list_append(arena, &list, am_str_from_range(split_beginning, cursor)); + } + split_beginning = cursor + 1; + } + cursor++; + } + + return list; +} + +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, four, "), (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); + } + + { + MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); + StrList lines = am_str_split(&a, AM_STR_LIT("one|two|three|four"), (u8 *)"|", 1); + + Str expected[] = { + AM_STR_LIT("one"), + AM_STR_LIT("two"), + AM_STR_LIT("three"), + AM_STR_LIT("four"), + }; + + size_t i = 0; + for (StrListNode *line = lines.first; line; line = line->next) { + printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); + assert(i < ARRAY_COUNT(expected)); + assert(am_str_eq(line->s, expected[i])); + i++; + } + + assert(i + 1 == ARRAY_COUNT(expected)); + am_mem_arena_release(&a); + } + + { + MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); + StrList lines = am_str_split(&a, AM_STR_LIT("|one|two||three|four|"), (u8 *)"|", 1); + + Str expected[] = { + AM_STR_LIT(""), + AM_STR_LIT("one"), + AM_STR_LIT("two"), + AM_STR_LIT(""), + AM_STR_LIT("three"), + AM_STR_LIT("four"), + AM_STR_LIT(""), + }; + + size_t i = 0; + for (StrListNode *line = lines.first; line; line = line->next) { + printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); + assert(i < ARRAY_COUNT(expected)); + assert(am_str_eq(line->s, expected[i])); + i++; + } + + assert(i + 1 == ARRAY_COUNT(expected)); + am_mem_arena_release(&a); + } + + { + MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); + StrList lines = am_str_split(&a, AM_STR_LIT("|||"), (u8 *)"|", 1); + + Str expected[] = { + AM_STR_LIT(""), + AM_STR_LIT(""), + AM_STR_LIT(""), + AM_STR_LIT(""), + }; + + size_t i = 0; + for (StrListNode *line = lines.first; line; line = line->next) { + printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); + assert(i < ARRAY_COUNT(expected)); + assert(am_str_eq(line->s, expected[i])); + i++; + } + + assert(i + 1 == ARRAY_COUNT(expected)); + am_mem_arena_release(&a); + } + + { + MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); + StrList lines = am_str_split(&a, AM_STR_LIT(""), (u8 *)"|", 1); + + assert(lines.node_count == 0); + am_mem_arena_release(&a); + } + + { + MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); + StrList lines = am_str_split(&a, AM_STR_LIT("one two three four"), (u8 *)"|", 1); + + Str expected[] = { + AM_STR_LIT("one two three four"), + }; + + size_t i = 0; + for (StrListNode *line = lines.first; line; line = line->next) { + printf("Expected: '%.*s', Got: '%.*s'\n", AM_STR_EXPAND(expected[i]), AM_STR_EXPAND(line->s)); + assert(i < ARRAY_COUNT(expected)); + assert(am_str_eq(line->s, expected[i])); + i++; + } + + assert(i + 1 == ARRAY_COUNT(expected)); + am_mem_arena_release(&a); + } +} + +#endif // AM_STRING_H diff --git a/2022/day01.c b/2022/day01.c @@ -0,0 +1,103 @@ +#if 0 +# Self-building c file. Invoke like: `./file.c` +outdir=out +input=$(basename "$0") +output="$outdir"/$(basename "$0" .c) +mkdir --parents "$outdir" || exit +echo "Building ${output}." || exit +clang -std=c11 -O0 -g -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit +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); + + int 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); + + usz items_read = fread(buf, 1, size, f); + assert(items_read == (usz)size); + + error = fclose(f); + assert(!error); + + return am_str(buf, size); +} + +u64 u64_from_string(Str s) { + u64 result = 0; + for (usz i = 0; i < s.size; i++) { + assert(s.str[i] >= '0' && s.str[i] <= '9'); + + u64 place_value = 1; + for (usz p = 0; p < (s.size - i - 1); p++) { + place_value *= 10; + } + + result += (s.str[i] - '0') * place_value; + } + return result; +} + +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 top[3] = {0}; + u64 calories = 0; + + for (StrListNode *line = lines.first; line; line = line->next) { + calories += u64_from_string(line->s); + + if (am_str_eq(line->s, AM_STR_LIT("")) || line == lines.last) { + if (calories > top[0]) { + top[0] = calories; + } + + u64 sum = top[0] + top[1] + top[2]; + u64 min = MIN(top[0], MIN(top[1], top[2])); + u64 max = MAX(top[0], MAX(top[1], top[2])); + + top[0] = min; + top[1] = sum - min - max; + top[2] = max; + + calories = 0; + } + } + + am_mem_arena_release(&a); + + printf("Day 1.1: %" PRIu64 "\n", top[2]); + printf("Day 1.2: %" PRIu64 "\n", top[0] + top[1] + top[2]); + return 0; +} diff --git a/2022/day01_input.txt b/2022/day01_input.txt @@ -0,0 +1,2269 @@ +3264 +4043 +2537 +3319 +2485 +3218 +5611 +1753 +7232 +3265 +1751 +2233 + +10589 +5121 +11465 +9307 +1347 +9392 +12037 + +6025 +4328 +3982 +4487 +1139 +1440 +2970 +3390 +1844 +5400 +1651 +4109 +3584 +2926 +4297 + +8921 +13298 +12300 +5607 +3304 +5037 + +1729 +10057 + +3538 +3984 +3451 +5638 +2880 +1008 +2940 +6245 +3865 +5060 +2878 +2460 +6557 + +1584 +6391 +3479 +2264 +2683 +3680 +1183 +5121 +6499 +5543 +1192 +4818 + +1337 +8128 +8966 +7601 +7749 +5017 +3251 +1074 +6095 + +11824 +17144 +5396 +15416 + +6244 +6589 +4953 +4250 +1422 +1252 +4555 +5240 +4244 +4088 + +27353 + +6629 +7231 +7673 +7029 +6994 +6347 +6381 +1503 +2145 +1114 +6068 + +3473 +3935 +4054 +3558 +3818 +5370 +4807 +2703 +5407 +2532 +6833 +1675 + +20016 +7587 +13088 + +3477 +3118 +5815 +3551 +2316 +4254 +4814 +5726 +5324 +6096 +3596 +3374 +3975 +4152 +1946 + +4549 +3639 +6338 +6882 +3514 +6488 +2192 +4522 +4370 +3637 +3500 +2964 +1850 + +6900 +5145 +13864 +8145 +4579 + +1984 +1589 +9279 +10987 +5213 + +3997 +1978 +5061 +2710 +2695 +4713 +5930 +3005 +6189 +2619 +6897 +5032 +2374 + +1738 +6817 +1993 +13747 +8574 +13341 + +3869 +1810 +3501 +1366 +4240 +2005 +6102 +6069 +4135 +6667 +1239 +2799 +1900 + +4711 +1330 +9725 +5965 +8271 +11932 + +5319 +6078 +1652 +1958 +1992 +1997 +2824 +6542 +1998 +2713 +6806 +4993 +6569 + +9262 + +3814 +11917 +4812 +1884 +3686 +10993 + +8845 +6032 +9899 +10384 +3834 +2275 + +3559 +2268 +1446 + +2265 +5503 +5056 +2547 +7394 +2514 +8105 +4630 +9392 + +2377 +10479 +3452 +9175 +13773 + +6090 +1467 +2747 +9310 +2839 +9392 +10752 +5771 + +8193 +4139 +4728 +5180 +5884 +9236 + +5721 +10884 +10268 +3255 +2377 +11574 +4498 + +17228 +7306 +6465 + +69149 + +6323 +3435 +2801 +6385 +4192 +1593 +4373 +6654 +7190 +6142 + +10960 +3399 +12251 +8249 +8210 +3571 + +2299 +4349 +1476 +5703 +1497 +4008 +1435 +5043 +2203 +4252 +2407 +5891 + +1419 +1588 + +4266 +2424 +1846 +3265 +5720 +5396 +2013 +2664 +4712 +1040 +3186 +1693 +1537 +3226 + +15568 +16153 +15408 +9417 +15524 + +18017 +4247 +1764 +18920 + +14176 +18583 + +4896 +1029 +14517 +10183 +9726 + +5242 +4156 +2314 +4018 +3542 +1619 +5349 +2524 +2620 +4675 +6491 +5315 +3959 +5215 + +2638 +5346 +6209 +1466 +2854 +6677 +2242 +8476 +5236 + +3827 +4489 +7735 +5656 +11568 +12323 + +8560 +7046 +5453 +4141 +1356 +8940 +8338 +3749 +7297 + +10693 +7191 +8803 +10504 +2033 +6374 +6820 +10316 + +5869 +12102 +12675 +7688 +10906 +12593 + +9028 +8234 +4453 +2117 +7328 +9404 +6664 +7206 +6357 + +3018 +5515 +6479 +1522 +4582 +5881 +4019 +1288 +5288 +4007 +5816 +2354 +5648 +5405 + +4120 +3890 +11718 +5713 +6986 +10362 +5529 + +8243 +2097 +10194 +3023 +11120 +9524 +2052 + +12552 +14406 +3981 +9703 +10329 + +7256 +9424 +4701 + +5694 +1262 +3521 +4194 +3530 +7472 +1773 +1787 +6229 +6608 +5905 +3065 + +3366 + +15198 +25328 + +3805 +4163 +4192 +4013 +2693 +3029 +4559 +5243 +3088 +4804 +1245 +1800 +4999 +3162 +6114 + +3808 +3672 +6397 +3747 +4312 +5015 +4237 +5326 +3961 +1382 +1380 +5517 +1140 + +3360 +6936 +3880 +4242 +7431 +5597 +6195 +5305 +1051 +1015 +1866 +3179 + +17144 +2423 +8330 + +5153 +2301 +4944 +1566 +5647 +6726 +6248 +1537 +6951 +1272 +1177 +2013 + +7595 +9953 +19751 +14200 + +2576 +1684 +6463 +6643 +2911 +1650 +2492 +5726 +4830 +6591 +4477 +6691 +6390 + +5209 +5099 +1115 +5456 +4573 +5954 +4389 +1703 +1595 +1348 +5814 +4031 +3086 +4039 +5445 + +3506 +3956 +1504 +5435 +5660 +6882 +1962 +4891 +2596 +3838 +7206 +5554 + +10423 +4792 +16000 +12857 +5040 + +7410 +2589 +6769 +8168 +7526 +4349 + +5160 +12452 +13889 +7499 +1985 +12491 + +1033 +9259 +6288 +5566 +6134 +11010 +7512 + +5196 +4644 +1825 +5564 +5759 +7134 +5589 +5387 +1328 +2314 +4948 +7354 + +6875 +2105 +3444 +6997 +3962 +1141 +2000 +7561 +6447 +5629 +7035 + +1499 +7160 +5201 +3206 +2719 +5177 +6566 +3455 +3304 +1648 +3273 + +6142 +3697 +2247 +6537 +5579 +7126 +2674 +1842 +1482 +5504 +1105 + +5669 +7401 +8229 +6261 +4378 +5548 +2360 +5703 +7650 +2086 + +23865 +10240 +2321 + +4221 +8067 +1395 +1397 +5776 +5136 +6820 +1428 +3375 +6117 +4467 + +2505 +4307 +5626 +8867 + +4709 +5951 +3811 +4998 +4460 +6243 +1790 +2172 +5694 +6245 +3273 +2664 +4813 +5669 + +5803 +4856 +2508 +6301 +4454 +2430 +4868 +4883 +6211 +1749 +2998 +3450 +2414 +5617 + +9135 +8583 +7582 +8349 +7609 +4434 +8362 +3472 + +44093 + +7933 +3349 +6041 +3238 +5036 +9100 +4252 + +14356 +24185 + +11887 +23333 +16694 + +6324 +1438 +5180 +5329 +6798 +4806 +5285 +4757 +4599 +3897 +2308 +5014 + +1455 +4268 +1903 +1436 +4563 +5135 +4876 +6561 +4776 +3530 +3080 +5724 +5520 + +3419 +2363 +4474 +6069 +2504 +6749 +4094 +5991 +8045 +1302 +5649 + +20607 +13990 + +7588 +9960 +8919 +11254 +6295 +3856 +10295 + +1161 +3773 +1559 +1198 +5967 +5237 +3369 +4437 +7698 +2756 +2639 + +43493 + +18577 +2593 +16336 +13785 + +6567 +2409 +8001 +4173 +11587 +8238 +3023 + +5146 +10077 +2630 +4827 +6199 +3701 +3840 +3068 + +3272 +5212 +3674 +5352 +3129 +4242 +2711 +3064 +4987 +5362 +4858 +3180 +6090 +2265 +4791 + +14702 +1034 + +12170 +8780 +14933 +3727 + +4239 +7116 +1120 +7853 +7862 +5512 +2309 +3094 +6359 + +9172 +12494 +8382 + +8629 +11921 +9629 +11535 +7792 +9996 + +6887 +10548 +3429 +2373 +6208 +5406 +5440 + +2164 +3233 +1512 +1556 +5476 +3462 +4261 +3563 +2409 +6236 +2568 +4638 +4775 +1131 + +27798 +30212 + +5409 +4676 +5445 +2119 +3557 +1135 +6724 +2779 +1324 +2157 +4456 +6329 +2155 + +4084 +1379 +7443 +12904 + +7167 +12163 +9588 +11186 +9015 + +35132 +18974 + +3418 + +12568 +1418 +7691 +12369 +1144 +6141 + +2523 +5150 +2276 +6036 +1492 +5069 +5782 +2999 +4505 +2347 +1234 +5376 +3356 +2489 +1456 + +30181 + +3189 +2572 +5145 +4350 +6403 +1285 +5678 +3796 +3792 +2334 +2710 +3536 +5580 + +2991 +7718 +1798 +5300 +11608 +3376 +11658 + +58468 + +6099 +4433 +7634 +7768 +3804 +5523 +6959 +4752 +8693 +2705 + +5315 +4218 + +5678 +2293 +2385 +2568 +1644 +3332 +5968 +4159 +5935 +2667 +4518 +2823 +4648 +3072 +5644 + +14306 +7557 +15251 +6896 +14250 + +10549 +1662 +10040 +2614 +4843 +1111 +9585 + +9531 +2249 +1949 +8715 +9466 +1471 +7952 + +2585 +8702 +10548 +12849 +5342 +10193 + +21463 +24241 +9125 + +36676 + +18212 +11298 +8690 + +6861 +1095 +4586 +1260 +2795 +3208 +4650 +4147 +5764 +1051 +6882 +5670 + +16681 +22273 +1336 + +3370 +3537 +2062 +4985 +2063 +2339 +5988 +3777 +5822 +2760 +1915 +4668 +4717 +5847 +4598 + +5829 +4829 +4872 +3893 +5320 +1832 +7637 +7137 +6079 +3006 +7422 + +34780 +21066 + +1164 +3444 +8079 +4633 +5030 +8296 +8703 +7929 +8767 +4489 + +1950 +5492 +4920 +3849 +6553 +1802 +1574 +4962 +1671 +2382 +4990 +2511 +3485 + +6003 +8237 + +10793 +12510 +2959 +9397 +6153 + +7943 +1934 +3817 +7937 +6856 +3813 +4408 +8046 +4605 +3994 +8081 + +10589 +11870 +8367 +7889 +10172 +9758 +9447 + +6566 +4971 +4600 +6863 +4212 +5240 +6523 +7979 +2695 +4934 + +6527 +2008 +4595 +7104 +7497 +10199 +6640 +7909 + +7970 +7026 +4812 +4331 +3244 +5260 +3089 +2871 +3915 +1445 + +3182 +9915 +5769 +6470 +10524 +7486 +5041 + +5575 + +6482 +2235 +2834 +3999 +4428 +1713 +3366 +4477 +2282 +1331 +5095 +5268 +5482 +3409 + +21109 + +8502 +2007 +3250 +6035 +6099 +2605 +6323 +5532 +3677 +8194 + +11224 +1704 +10152 +11640 +1018 +7016 +2700 + +12204 + +1191 +5039 +5036 +3778 +1669 +5277 +5345 +3833 +5379 +1286 +2042 +5365 +4518 +5517 + +2750 +4544 +3817 +5392 +1745 +4056 +1557 +1819 +6187 +4867 +6445 +4475 +3026 +5516 + +13176 +25505 +2657 + +29617 +4098 + +1733 +3055 +3730 +5327 +3111 +4912 +1842 +2471 +1964 +2747 +1573 +4097 +5558 +4940 +2065 + +1177 +3510 +6178 +1267 +9395 +1387 +1251 +9112 +1265 + +4073 +8822 + +5585 +4905 +1005 +4303 +2129 +1565 +1577 +1747 +7097 +7135 +2546 + +6368 +6384 +1873 +2027 +2111 +5781 +4392 +1640 +1874 +5147 +6551 +4992 + +11673 +15872 +10747 +5457 + +7576 +6084 +3279 +5582 +8329 +7176 +6561 +5342 +8481 +6333 + +7617 +12916 +8957 +17210 + +4173 +1088 +5981 +2094 +4598 +3192 +3968 +1486 +3888 +4186 +5948 +3764 +3173 +1597 +5057 + +7430 +3183 +20030 +4003 + +5891 +6434 +2213 +1762 +6106 +7550 +6766 +6075 +1119 +4462 + +2460 +7385 +3906 +2805 +2519 +2189 +6803 +2705 +5167 +2972 +6855 +6996 + +3922 +4300 +2172 +7515 +9388 +8687 +5087 +6373 +4001 + +3288 +3888 +3873 +7575 +1902 +3315 +4831 +3272 +4914 + +2120 +3223 +3582 +4864 +1944 +2625 +2666 +1710 +2511 +4362 +3073 +3994 +3171 + +8037 +2890 +3124 +8901 +1411 +6858 +5184 +1294 +7790 + +7884 +7169 +4372 +5820 +6836 +2878 +7608 +2434 +8600 +8117 + +33732 +17277 + +31526 +6202 + +6081 +5669 +1460 +7548 +1054 +3713 +8470 + +7033 +4205 +4404 +4261 +2975 +7865 +5190 +1675 +1349 +7748 + +7345 +6389 +3056 +2777 +12209 +10038 + +5285 +7634 +5875 +6074 +3076 +2687 +4342 +5471 +4113 + +2993 +10714 +5204 +6732 +4746 +12416 + +19555 +17202 +13776 +6280 + +2820 +11278 +6160 +9522 +6585 + +9093 +6397 +10417 +4902 +4899 + +5602 +4917 +4964 +5689 +4316 +4041 +5290 +3223 +4065 +3514 +3552 +5864 +4823 +6481 + +3239 +5151 +2862 +4568 +1964 +3003 +3575 +4445 +6875 +5511 +1591 +1681 +6874 + +7348 +1881 +7702 +6305 +2373 +6320 +1544 +2897 +2784 +5977 +6964 + +1757 +7460 +5212 +3491 +1157 +3753 +1983 +3015 +1298 +2812 +3569 +4680 + +22481 + +8578 +7141 +11229 +5622 +13937 +1699 + +3479 +1258 +2782 +5573 +7720 +6726 +4043 +3059 +5028 +8075 + +3232 +6633 +5344 +1862 +6215 +3674 +2507 +5509 +1982 +4422 +1709 + +2759 +2497 +3959 +1725 +2430 +3256 +1416 +4213 +3452 +6809 +6817 +3151 + +5187 +2502 +6982 +3414 +11460 +12085 +5775 + +1490 +4368 +4135 +1494 +5683 +5443 +5182 +6209 +3240 +1433 +3373 +3048 +5768 +4132 + +22305 +10502 + +6633 +2336 +6714 +3046 +4740 +4650 +2901 +5832 +5690 +4211 +6168 +4901 +2448 + +8640 +11265 +10961 +10744 +10955 + +16404 +15126 +4253 +1372 + +9862 +9547 +20599 + +8872 +3452 +2169 +7757 +5535 +9697 +8147 +8775 + +14862 + +68282 + +4343 +11948 +2346 +16745 + +12892 +12538 +15571 +11814 + +4406 +1323 +3769 +5868 +5023 +6057 +5967 +2891 +2778 +5696 +4376 +2244 +4102 +4721 + +8420 + +8564 +2803 +11178 +17801 + +34616 + +4635 +3716 +6634 +3494 +2905 +4254 +8053 +4871 +5523 +5088 +2928 + +7447 +16669 +9215 +14663 + +4248 +3260 +3347 +5552 +4781 +1715 +5642 +5414 +3223 +3043 +3415 +6463 +5932 + +29980 +37187 + +9703 +7176 +8191 +10002 +7145 +5926 +10760 +7384 + +32599 +26889 + +5843 +1632 +3871 +5645 +9544 +3097 +1820 + +6941 +4838 +5440 +4389 +5309 +5449 +5897 +4418 +4641 +6905 +4951 +2198 +1031 + +4553 +1428 +4164 +2850 +1146 +2496 +4807 +4776 +1573 +2865 +1225 +5182 +2617 +1514 +5828 + +5660 +1567 +5066 +4985 +4683 +4819 +3894 +4432 +5188 +4791 +5916 +3867 +4285 +5863 +5570 + +5394 +3391 +4052 +3230 +4524 +1059 +3685 +1808 +2161 +2662 +3718 +5945 +5094 +4867 +4258 + +28646 +31561 + +11012 +2804 +5719 +5299 +2500 +11059 + +1318 +5060 +1097 +5290 +1059 +3435 +1082 +6242 +1623 +2004 +3567 +1725 +5056 + +4643 +5165 +14091 +6412 +13186 + +5560 + +7978 +4943 +8311 +6023 +15930 + +1972 +7310 +6563 +1748 +6142 +4529 +2106 +7066 +4598 +7301 +2132 +4005 + +1173 +6436 +6047 +5197 +6500 +4588 +5341 +4781 +4750 +4244 +1199 +4931 +4863 +5628 + +10302 +8627 +5405 +6570 +11439 +1447 + +22318 +21787 +9491 + +4710 +4259 +5894 +2971 +4273 +4994 +3414 +4179 +2483 +5404 +1646 +3099 +4035 +4066 + +6374 +8210 +4288 +2226 +3271 +8759 +6171 +7020 +8299 +1958 + +2744 +6690 +1431 +5118 +5387 +7128 +5517 +6299 +7515 +4304 +1846 + +1941 +1309 +1888 +4992 +5942 +4182 +2334 +3283 +4907 +2610 +3373 +2936 +1908 + +3400 +6953 +5233 +5348 +8743 +2799 +7890 +1898 +7783 + +38934 + +3843 +1038 +3364 +6113 +3952 +7192 +5767 +3932 +4462 +2088 +3925 +3990 + +2596 +10301 +11026 +12033 +2542 +13448 + +4798 +6076 +3906 +1617 +8462 +2051 +4827 +1905 +5940 +7175 + +8305 +6626 +1600 +5228 +6332 +1206 +4840 +4600 +5363 + +6425 +13475 +11305 +14037 + +6154 +1016 +3673 +1827 +3628 +4238 +2483 +4762 +3413 +3148 +4659 +3451 +6465 +2363 + +35242 +27022 + +2722 +11484 +12323 +6822 +7951 +4387 + +36866 + +5755 +20057 +5657 + +2491 +2205 +3527 +9556 +8363 +3109 +8618 +1481 +6234 + +7365 +1920 +1578 +3271 +3325 +1263 +1816 +7031 +8020 +2353 +3127 + +8027 +13092 +7531 +12350 + +10451 +9259 +13080 +12849 + +3984 +2140 +2655 +2766 +8665 +2282 +4391 +1435 +4821 +4977 + +2366 + +6198 +17922 +22945 + +2077 +6263 +11643 +11377 +3735 +11634 +5022 + +16598 +7968 + +31400 +22664 + +5414 +5057 +1898 +3063 +4075 +2527 +3502 +6713 +3109 +6376 +2487 +2279 +1057 + +12654 +11007 +2365 +8272 +2895 + +15798 +3536 +14549 + +1066 +1181 +6142 +9592 +3412 +8683 + +3274 +1129 +1645 +4784 +4039 +5447 +4766 +1310 +3346 +4062 +2219 +4290 +4733 +3033 +1306 + +2006 +2898 +3600 +1802 +4760 +5306 +1000 +1279 +1205 +5224 +2652 +4914 +4042 +1559 + +20342 +16632 + +18586 +1712 +11316 +16623 + +7964 +6856 +7863 +7417 +4608 +7216 +4263 +6552 +3187 + +6415 +2442 +2928 +4853 +6899 +6747 +3803 +3522 +5680 +6184 +3326 +5707 +1695 + +61737 + +18154 +7052 + +4635 +3560 +8043 +5917 +9440 +7535 +7213 +7625 + +3389 +1034 +4154 +4872 +4843 +2238 +1174 +2922 +1067 +5715 +5093 +3302 +1076 +3017 +4711 + +9322 +11596 +6347 +11332 +9376 +9230 + +6475 +6492 +4953 +6492 +3935 +2286 +7152 +4659 +5762 +4989 +6438 +1020