day11
This commit is contained in:
parent
9271e4c3e5
commit
4547fe2238
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
||||
all: $(patsubst %.cpp,%.elf,$(wildcard example/*.cpp))
|
||||
|
||||
OPT = -Og
|
||||
OPT = -O3
|
||||
|
||||
include dreamcast/base.mk
|
||||
include dreamcast/common.mk
|
||||
|
4
aoc.mk
4
aoc.mk
@ -20,6 +20,10 @@ DREAMCAST_OBJ = \
|
||||
$(LIB)/font/dejavusansmono/dejavusansmono.data.o \
|
||||
$(LIB)/sh7091/serial.o \
|
||||
$(LIB)/maple/maple.o
|
||||
# libgcc/_divdi3.o \
|
||||
# libgcc/_moddi3.o \
|
||||
# libgcc/_udiv_qrnnd_16.o \
|
||||
# libgcc/_clz.o
|
||||
|
||||
include solutions.mk
|
||||
|
||||
|
1
day11/input.txt
Normal file
1
day11/input.txt
Normal file
@ -0,0 +1 @@
|
||||
70949 6183 4 3825336 613971 0 15 182
|
15
day11/input.txt.h
Normal file
15
day11/input.txt.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t _binary_day11_input_txt_start __asm("_binary_day11_input_txt_start");
|
||||
extern uint32_t _binary_day11_input_txt_end __asm("_binary_day11_input_txt_end");
|
||||
extern uint32_t _binary_day11_input_txt_size __asm("_binary_day11_input_txt_size");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
1
day11/sample1.txt
Normal file
1
day11/sample1.txt
Normal file
@ -0,0 +1 @@
|
||||
125 17
|
15
day11/sample1.txt.h
Normal file
15
day11/sample1.txt.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t _binary_day11_sample1_txt_start __asm("_binary_day11_sample1_txt_start");
|
||||
extern uint32_t _binary_day11_sample1_txt_end __asm("_binary_day11_sample1_txt_end");
|
||||
extern uint32_t _binary_day11_sample1_txt_size __asm("_binary_day11_sample1_txt_size");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
172
day11/solution.c
Normal file
172
day11/solution.c
Normal file
@ -0,0 +1,172 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "unparse.h"
|
||||
#include "printf.h"
|
||||
|
||||
static void split_base10(int64_t n, int digits, int64_t * a, int64_t * b)
|
||||
{
|
||||
int pow = 1;
|
||||
digits /= 2;
|
||||
while (digits-- > 0)
|
||||
pow *= 10;
|
||||
int64_t split = pow;
|
||||
*a = n / split;
|
||||
*b = n % split;
|
||||
}
|
||||
|
||||
static int stone_rule(int64_t n, int64_t * a, int64_t * b)
|
||||
{
|
||||
int digits;
|
||||
if (n == 0) {
|
||||
*a = 1;
|
||||
return 1;
|
||||
} else if ((digits = digits_base10_64(n)) % 2 == 0) {
|
||||
split_base10(n, digits, a, b);
|
||||
return 2;
|
||||
} else {
|
||||
*a = n * 2024;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct entry {
|
||||
int64_t n;
|
||||
int32_t depth;
|
||||
int32_t _;
|
||||
int64_t value;
|
||||
};
|
||||
|
||||
#define CACHE_LENGTH (262144)
|
||||
|
||||
struct cache {
|
||||
struct entry entry[CACHE_LENGTH];
|
||||
volatile int length;
|
||||
};
|
||||
|
||||
static void sift_up(struct entry * e, int ix)
|
||||
{
|
||||
while (ix > 0) {
|
||||
int parent = (ix - 1) / 2;
|
||||
if (e[parent].depth < e[ix].depth || e[parent].n < e[ix].n) {
|
||||
// swap parent and ix
|
||||
struct entry tmp = e[parent];
|
||||
e[parent] = e[ix];
|
||||
e[ix] = tmp;
|
||||
ix = parent;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int search(struct entry * e, int length, int ix, int64_t n, int32_t depth)
|
||||
{
|
||||
if (e[ix].depth == depth && e[ix].n == n) {
|
||||
/*
|
||||
uint32_t r15;
|
||||
asm volatile ("mov r15,%0"
|
||||
: "=r" (r15));
|
||||
if (r15 < min) {
|
||||
//printf("%08x\n", r15);
|
||||
min = r15;
|
||||
}
|
||||
*/
|
||||
|
||||
return ix;
|
||||
}
|
||||
|
||||
int child_l = 2 * ix + 1;
|
||||
int child_r = 2 * ix + 2;
|
||||
|
||||
if (child_r < length && (e[child_r].depth >= depth || e[child_r].n >= n)) {
|
||||
int i = search(e, length, child_r, n, depth);
|
||||
if (i >= 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
if (child_l < length && (e[child_l].depth >= depth || e[child_l].n >= n)) {
|
||||
int i = search(e, length, child_l, n, depth);
|
||||
if (i >= 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void cache_add(struct cache * cache, int64_t n, int32_t depth, int64_t value)
|
||||
{
|
||||
if (cache->length >= CACHE_LENGTH)
|
||||
return;
|
||||
|
||||
int ix = cache->length;
|
||||
cache->entry[ix].n = n;
|
||||
cache->entry[ix].depth = depth;
|
||||
cache->entry[ix].value = value;
|
||||
sift_up(cache->entry, ix);
|
||||
cache->length += 1;
|
||||
}
|
||||
|
||||
static int64_t simulate_step(int64_t n, int depth, int max_depth, struct cache * cache)
|
||||
{
|
||||
if (depth == max_depth)
|
||||
return 1;
|
||||
|
||||
int cache_ix = search(cache->entry, cache->length, 0, n, depth);
|
||||
if (cache_ix >= 0) {
|
||||
//printf("hit ix:%l %d %l\n", n, depth, cache->entry[cache_ix].value);
|
||||
return cache->entry[cache_ix].value;
|
||||
}
|
||||
|
||||
int64_t a[2];
|
||||
int new_stones = stone_rule(n, &a[0], &a[1]);
|
||||
int64_t sum = 0;
|
||||
for (int i = 0; i < new_stones; i++) {
|
||||
sum += simulate_step(a[i], depth + 1, max_depth, cache);
|
||||
}
|
||||
|
||||
//printf("store: %l %d %l\n", n, depth, sum);
|
||||
cache_add(cache, n, depth, sum);
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int parse_input(const char * input, int length,
|
||||
int64_t * stones)
|
||||
{
|
||||
const char * end = input + length;
|
||||
|
||||
int i = 0;
|
||||
while (input < end) {
|
||||
input = parse_base10_64(input, &stones[i]);
|
||||
input = parse_skip(input, ' ');
|
||||
input = parse_skip(input, '\n');
|
||||
i += 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int64_t solve(const char * input, int length, int max_depth)
|
||||
{
|
||||
static struct cache cache;
|
||||
int64_t stones[20];
|
||||
|
||||
int count = parse_input(input, length, stones);
|
||||
|
||||
int64_t sum = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
cache.length = 0;
|
||||
sum += simulate_step(stones[i], 0, max_depth, &cache);
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
int64_t day11_part1(const char * input, int length)
|
||||
{
|
||||
return solve(input, length, 25);
|
||||
}
|
||||
|
||||
int64_t day11_part2(const char * input, int length)
|
||||
{
|
||||
return solve(input, length, 75);
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
#include "day9/input.txt.h"
|
||||
#include "day10/sample1.txt.h"
|
||||
#include "day10/input.txt.h"
|
||||
#include "day11/sample1.txt.h"
|
||||
#include "day11/input.txt.h"
|
||||
|
||||
static struct start_size sample[][2] = {
|
||||
{
|
||||
@ -81,6 +83,12 @@ static struct start_size sample[][2] = {
|
||||
{ ( char *)&_binary_day10_sample1_txt_start,
|
||||
(uint32_t)&_binary_day10_sample1_txt_size },
|
||||
},
|
||||
{
|
||||
{ ( char *)&_binary_day11_sample1_txt_start,
|
||||
(uint32_t)&_binary_day11_sample1_txt_size },
|
||||
{ ( char *)&_binary_day11_sample1_txt_start,
|
||||
(uint32_t)&_binary_day11_sample1_txt_size },
|
||||
},
|
||||
};
|
||||
|
||||
static struct start_size input[] = {
|
||||
@ -104,4 +112,6 @@ static struct start_size input[] = {
|
||||
(uint32_t)&_binary_day9_input_txt_size },
|
||||
{ ( char *)&_binary_day10_input_txt_start,
|
||||
(uint32_t)&_binary_day10_input_txt_size },
|
||||
{ ( char *)&_binary_day11_input_txt_start,
|
||||
(uint32_t)&_binary_day11_input_txt_size },
|
||||
};
|
||||
|
2
runner.c
2
runner.c
@ -32,7 +32,7 @@ bool runner_tick(struct runner_state * runner_state)
|
||||
int part = tick % 2;
|
||||
int day = tick / 2;
|
||||
|
||||
if (day < 9)
|
||||
if (day < 10)
|
||||
return true;
|
||||
|
||||
runner_state->want_render = solution[day].render != NULL;
|
||||
|
@ -21,6 +21,8 @@ int64_t day9_part1(const char * input, int length);
|
||||
int64_t day9_part2(const char * input, int length);
|
||||
int64_t day10_part1(const char * input, int length);
|
||||
int64_t day10_part2(const char * input, int length);
|
||||
int64_t day11_part1(const char * input, int length);
|
||||
int64_t day11_part2(const char * input, int length);
|
||||
|
||||
struct day_funcs solution[] = {
|
||||
{
|
||||
@ -63,4 +65,8 @@ struct day_funcs solution[] = {
|
||||
{day10_part1, day10_part2},
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
{day11_part1, day11_part2},
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
@ -30,4 +30,7 @@ DAY_OBJ = \
|
||||
day9/solution.o \
|
||||
day10/sample1.txt.o \
|
||||
day10/input.txt.o \
|
||||
day10/solution.o
|
||||
day10/solution.o \
|
||||
day11/sample1.txt.o \
|
||||
day11/input.txt.o \
|
||||
day11/solution.o
|
||||
|
Loading…
x
Reference in New Issue
Block a user