2024 day17 (incomplete)
This commit is contained in:
parent
69febabee8
commit
307e990924
@ -1,7 +1,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
//#include <stdio.h>
|
||||||
//#include "printf.h"
|
#include "printf.h"
|
||||||
#include "dijkstra.h"
|
#include "dijkstra.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
@ -95,6 +95,7 @@ int64_t _2024_day16_part2(const char * input, int length)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@ -107,3 +108,4 @@ int main()
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
printf("%ld\n", _2024_day16_part1(buf, length));
|
printf("%ld\n", _2024_day16_part1(buf, length));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
5
2024/day17/input.txt
Normal file
5
2024/day17/input.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Register A: 59397658
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 2,4,1,1,7,5,4,6,1,4,0,3,5,5,3,0
|
15
2024/day17/input.txt.h
Normal file
15
2024/day17/input.txt.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint32_t _binary_2024_day17_input_txt_start __asm("_binary_2024_day17_input_txt_start");
|
||||||
|
extern uint32_t _binary_2024_day17_input_txt_end __asm("_binary_2024_day17_input_txt_end");
|
||||||
|
extern uint32_t _binary_2024_day17_input_txt_size __asm("_binary_2024_day17_input_txt_size");
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
5
2024/day17/sample1.txt
Normal file
5
2024/day17/sample1.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Register A: 729
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 0,1,5,4,3,0
|
15
2024/day17/sample1.txt.h
Normal file
15
2024/day17/sample1.txt.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint32_t _binary_2024_day17_sample1_txt_start __asm("_binary_2024_day17_sample1_txt_start");
|
||||||
|
extern uint32_t _binary_2024_day17_sample1_txt_end __asm("_binary_2024_day17_sample1_txt_end");
|
||||||
|
extern uint32_t _binary_2024_day17_sample1_txt_size __asm("_binary_2024_day17_sample1_txt_size");
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
5
2024/day17/sample2.txt
Normal file
5
2024/day17/sample2.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Register A: 2024
|
||||||
|
Register B: 0
|
||||||
|
Register C: 0
|
||||||
|
|
||||||
|
Program: 0,3,5,4,3,0
|
15
2024/day17/sample2.txt.h
Normal file
15
2024/day17/sample2.txt.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint32_t _binary_2024_day17_sample2_txt_start __asm("_binary_2024_day17_sample2_txt_start");
|
||||||
|
extern uint32_t _binary_2024_day17_sample2_txt_end __asm("_binary_2024_day17_sample2_txt_end");
|
||||||
|
extern uint32_t _binary_2024_day17_sample2_txt_size __asm("_binary_2024_day17_sample2_txt_size");
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
243
2024/day17/solution.c
Normal file
243
2024/day17/solution.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "printf.h"
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
|
struct state {
|
||||||
|
int pc;
|
||||||
|
int64_t a;
|
||||||
|
int64_t b;
|
||||||
|
int64_t c;
|
||||||
|
char mem[256];
|
||||||
|
int mem_length;
|
||||||
|
char out[256];
|
||||||
|
int out_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int64_t combo_operand(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
switch (operand) {
|
||||||
|
case 0: return 0;
|
||||||
|
case 1: return 1;
|
||||||
|
case 2: return 2;
|
||||||
|
case 3: return 3;
|
||||||
|
case 4: return state->a;
|
||||||
|
case 5: return state->b;
|
||||||
|
case 6: return state->c;
|
||||||
|
default:
|
||||||
|
printf("invalid combo operand %d\n", operand);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_adv(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
int64_t value = combo_operand(state, operand);
|
||||||
|
const int64_t one = 1;
|
||||||
|
state->a = state->a / (one << value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_bxl(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
state->b = state->b ^ (int64_t)operand;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_bst(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
int64_t value = combo_operand(state, operand);
|
||||||
|
state->b = value % 8;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_jnz(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
if (state->a != 0) {
|
||||||
|
state->pc = operand;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_bxc(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
state->b = state->b ^ state->c;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_out(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
int64_t value = combo_operand(state, operand);
|
||||||
|
state->out[state->out_length++] = value % 8;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_bdv(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
int64_t value = combo_operand(state, operand);
|
||||||
|
state->b = state->a / (1 << value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_cdv(struct state * state, int operand)
|
||||||
|
{
|
||||||
|
int64_t value = combo_operand(state, operand);
|
||||||
|
state->c = state->a / (1 << value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * parse_register(const char * input, char c, int * value)
|
||||||
|
{
|
||||||
|
input = parse_match(input, "Register ");
|
||||||
|
input = parse_skip(input, c);
|
||||||
|
input = parse_match(input, ": ");
|
||||||
|
input = parse_base10(input, value);
|
||||||
|
input = parse_skip(input, '\n');
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void step(struct state * state)
|
||||||
|
{
|
||||||
|
int op = state->mem[state->pc];
|
||||||
|
int operand = state->mem[state->pc+1];
|
||||||
|
bool incpc;
|
||||||
|
switch (op) {
|
||||||
|
case 0: incpc = op_adv(state, operand); break;
|
||||||
|
case 1: incpc = op_bxl(state, operand); break;
|
||||||
|
case 2: incpc = op_bst(state, operand); break;
|
||||||
|
case 3: incpc = op_jnz(state, operand); break;
|
||||||
|
case 4: incpc = op_bxc(state, operand); break;
|
||||||
|
case 5: incpc = op_out(state, operand); break;
|
||||||
|
case 6: incpc = op_bdv(state, operand); break;
|
||||||
|
case 7: incpc = op_cdv(state, operand); break;
|
||||||
|
default:
|
||||||
|
printf("invalid opcode %d\n", op);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (incpc)
|
||||||
|
state->pc = state->pc + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * parse_program(const char * input, const char * end, struct state * state)
|
||||||
|
{
|
||||||
|
input = parse_match(input, "Program: ");
|
||||||
|
|
||||||
|
int value;
|
||||||
|
state->mem_length = 0;
|
||||||
|
input = parse_base10(input, &value);
|
||||||
|
state->mem[state->mem_length++] = value;
|
||||||
|
while (input < end) {
|
||||||
|
input = parse_skip(input, ',');
|
||||||
|
input = parse_base10(input, &value);
|
||||||
|
state->mem[state->mem_length++] = value;
|
||||||
|
input = parse_skip(input, '\n');
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void run_until_halt(struct state * state)
|
||||||
|
{
|
||||||
|
while (state->pc < state->mem_length) {
|
||||||
|
step(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_input(const char * input, int length, struct state * state)
|
||||||
|
{
|
||||||
|
const char * end = input + length;
|
||||||
|
|
||||||
|
state->pc = 0;
|
||||||
|
state->out_length = 0;
|
||||||
|
|
||||||
|
int reg;
|
||||||
|
input = parse_register(input, 'A', ®);
|
||||||
|
state->a = reg;
|
||||||
|
input = parse_register(input, 'B', ®);
|
||||||
|
state->b = reg;
|
||||||
|
input = parse_register(input, 'C', ®);
|
||||||
|
state->c = reg;
|
||||||
|
|
||||||
|
input = parse_skip(input, '\n');
|
||||||
|
parse_program(input, end, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_out(struct state * state)
|
||||||
|
{
|
||||||
|
printf("%d", state->out[0]);
|
||||||
|
for (int i = 1; i < state->out_length; i++) {
|
||||||
|
printf(",%d", state->out[i]);
|
||||||
|
}
|
||||||
|
print_char('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t _2024_day17_part1(const char * input, int length)
|
||||||
|
{
|
||||||
|
struct state state;
|
||||||
|
parse_input(input, length, &state);
|
||||||
|
|
||||||
|
run_until_halt(&state);
|
||||||
|
print_out(&state);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool out_eq_mem(const struct state * state)
|
||||||
|
{
|
||||||
|
if (state->mem_length != state->out_length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < state->mem_length; i++) {
|
||||||
|
if (state->mem[i] != state->out[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t _2024_day17_part2(const char * input, int length)
|
||||||
|
{
|
||||||
|
struct state state;
|
||||||
|
parse_input(input, length, &state);
|
||||||
|
|
||||||
|
int64_t a = 1;
|
||||||
|
int64_t last_a = a;
|
||||||
|
while (true) {
|
||||||
|
state.a = a;
|
||||||
|
state.b = 0;
|
||||||
|
state.c = 0;
|
||||||
|
state.pc = 0;
|
||||||
|
state.out_length = 0;
|
||||||
|
|
||||||
|
run_until_halt(&state);
|
||||||
|
|
||||||
|
if (state.out_length < state.mem_length) {
|
||||||
|
last_a = a;
|
||||||
|
a *= 2;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a = last_a;
|
||||||
|
while (true) {
|
||||||
|
state.a = a;
|
||||||
|
state.b = 0;
|
||||||
|
state.c = 0;
|
||||||
|
state.pc = 0;
|
||||||
|
state.out_length = 0;
|
||||||
|
|
||||||
|
run_until_halt(&state);
|
||||||
|
|
||||||
|
if (out_eq_mem(&state))
|
||||||
|
break;
|
||||||
|
|
||||||
|
a += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_out(&state);
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
@ -2,10 +2,10 @@
|
|||||||
#include "dijkstra.h"
|
#include "dijkstra.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
//#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
//#include <stdio.h>
|
||||||
#include <assert.h>
|
//#include <assert.h>
|
||||||
|
|
||||||
void dijkstra_cartesian(const char * graph,
|
void dijkstra_cartesian(const char * graph,
|
||||||
int stride,
|
int stride,
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#include "2024/day15/input.txt.h"
|
#include "2024/day15/input.txt.h"
|
||||||
#include "2024/day16/sample1.txt.h"
|
#include "2024/day16/sample1.txt.h"
|
||||||
#include "2024/day16/input.txt.h"
|
#include "2024/day16/input.txt.h"
|
||||||
|
#include "2024/day17/sample1.txt.h"
|
||||||
|
#include "2024/day17/sample2.txt.h"
|
||||||
|
#include "2024/day17/input.txt.h"
|
||||||
|
|
||||||
static struct start_size sample[][2] = {
|
static struct start_size sample[][2] = {
|
||||||
{
|
{
|
||||||
@ -171,6 +174,12 @@ static struct start_size sample[][2] = {
|
|||||||
{ ( char *)&_binary_2024_day16_sample1_txt_start,
|
{ ( char *)&_binary_2024_day16_sample1_txt_start,
|
||||||
(uint32_t)&_binary_2024_day16_sample1_txt_size },
|
(uint32_t)&_binary_2024_day16_sample1_txt_size },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
{ ( char *)&_binary_2024_day17_sample1_txt_start,
|
||||||
|
(uint32_t)&_binary_2024_day17_sample1_txt_size },
|
||||||
|
{ ( char *)&_binary_2024_day17_sample2_txt_start,
|
||||||
|
(uint32_t)&_binary_2024_day17_sample2_txt_size },
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct start_size input[] = {
|
static struct start_size input[] = {
|
||||||
@ -216,4 +225,6 @@ static struct start_size input[] = {
|
|||||||
(uint32_t)&_binary_2024_day15_input_txt_size },
|
(uint32_t)&_binary_2024_day15_input_txt_size },
|
||||||
{ ( char *)&_binary_2024_day16_input_txt_start,
|
{ ( char *)&_binary_2024_day16_input_txt_start,
|
||||||
(uint32_t)&_binary_2024_day16_input_txt_size },
|
(uint32_t)&_binary_2024_day16_input_txt_size },
|
||||||
|
{ ( char *)&_binary_2024_day17_input_txt_start,
|
||||||
|
(uint32_t)&_binary_2024_day17_input_txt_size },
|
||||||
};
|
};
|
||||||
|
2
runner.c
2
runner.c
@ -38,7 +38,7 @@ bool runner_tick(struct runner_state * runner_state)
|
|||||||
int year = solution[ix].year;
|
int year = solution[ix].year;
|
||||||
int day = solution[ix].day;
|
int day = solution[ix].day;
|
||||||
|
|
||||||
if (year != 2024 || day != 16) {
|
if (year != 2024 || day != 17) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ int64_t _2024_day15_part1(const char * input, int length);
|
|||||||
int64_t _2024_day15_part2(const char * input, int length);
|
int64_t _2024_day15_part2(const char * input, int length);
|
||||||
int64_t _2024_day16_part1(const char * input, int length);
|
int64_t _2024_day16_part1(const char * input, int length);
|
||||||
int64_t _2024_day16_part2(const char * input, int length);
|
int64_t _2024_day16_part2(const char * input, int length);
|
||||||
|
int64_t _2024_day17_part1(const char * input, int length);
|
||||||
|
int64_t _2024_day17_part2(const char * input, int length);
|
||||||
|
|
||||||
struct day_funcs solution[] = {
|
struct day_funcs solution[] = {
|
||||||
{
|
{
|
||||||
@ -153,4 +155,9 @@ struct day_funcs solution[] = {
|
|||||||
{_2024_day16_part1, _2024_day16_part2},
|
{_2024_day16_part1, _2024_day16_part2},
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
2024, 17,
|
||||||
|
{_2024_day17_part1, _2024_day17_part2},
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -66,4 +66,8 @@ DAY_OBJ = \
|
|||||||
2024/day15/solution.o \
|
2024/day15/solution.o \
|
||||||
2024/day16/sample1.txt.o \
|
2024/day16/sample1.txt.o \
|
||||||
2024/day16/input.txt.o \
|
2024/day16/input.txt.o \
|
||||||
2024/day16/solution.o
|
2024/day16/solution.o \
|
||||||
|
2024/day17/sample1.txt.o \
|
||||||
|
2024/day17/sample2.txt.o \
|
||||||
|
2024/day17/input.txt.o \
|
||||||
|
2024/day17/solution.o
|
||||||
|
Loading…
x
Reference in New Issue
Block a user