Compare commits
10 Commits
80a315131b
...
907c70335a
Author | SHA1 | Date | |
---|---|---|---|
907c70335a | |||
2eda698664 | |||
33c22748da | |||
bbe7d66027 | |||
de73079754 | |||
6e9cf2c26a | |||
68cd93cbed | |||
5987591a2a | |||
6a191037e0 | |||
81b2f98dbf |
36
c/2019/2/1202_program_alarm.c
Normal file
36
c/2019/2/1202_program_alarm.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../../lib/intcode.h"
|
||||||
|
|
||||||
|
#define EXPECTED_OUTPUT 19690720
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ic_load_rom_from_input();
|
||||||
|
|
||||||
|
IC *c = ic_new_computer();
|
||||||
|
ic_poke(c, 1, 12);
|
||||||
|
ic_poke(c, 2, 2);
|
||||||
|
ic_run(c);
|
||||||
|
|
||||||
|
printf("Part 1: %d\n", ic_peek(c, 0));
|
||||||
|
|
||||||
|
int noun, verb;
|
||||||
|
for (noun = 0; noun < 100; noun++) {
|
||||||
|
for (verb = 0; verb < 100; verb++) {
|
||||||
|
ic_reset(c);
|
||||||
|
ic_poke(c, 1, noun);
|
||||||
|
ic_poke(c, 2, verb);
|
||||||
|
ic_run(c);
|
||||||
|
if (ic_peek(c, 0) == EXPECTED_OUTPUT) goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
|
||||||
|
printf("Part 2: %d\n", noun * 100 + verb);
|
||||||
|
|
||||||
|
aoc_free();
|
||||||
|
return 0;
|
||||||
|
}
|
19
c/2019/5/sunny_with_a_chance_of_asteroids.c
Normal file
19
c/2019/5/sunny_with_a_chance_of_asteroids.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../../lib/intcode.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ic_load_rom_from_input();
|
||||||
|
|
||||||
|
IC *c = ic_new_computer();
|
||||||
|
ic_run(c);
|
||||||
|
|
||||||
|
printf("Part 1: %d\n", c->output_buffer[c->output_buffer_count - 1]);
|
||||||
|
// printf("Part 2: %d\n", noun * 100 + verb);
|
||||||
|
|
||||||
|
aoc_free();
|
||||||
|
return 0;
|
||||||
|
}
|
141
c/2024/11/plutonian_pebbles.c
Normal file
141
c/2024/11/plutonian_pebbles.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "../../lib/aoc.h"
|
||||||
|
|
||||||
|
typedef long long stone;
|
||||||
|
|
||||||
|
typedef struct Stones {
|
||||||
|
stone first;
|
||||||
|
stone second;
|
||||||
|
} Stones;
|
||||||
|
|
||||||
|
typedef struct StonePile {
|
||||||
|
stone value;
|
||||||
|
long long count;
|
||||||
|
} StonePile;
|
||||||
|
|
||||||
|
int sort_stone_piles(const void *a, const void *b) {
|
||||||
|
return ((*(StonePile*) a).value - (*(StonePile*) b).value) % INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_digits(stone s) {
|
||||||
|
stone comp = 10;
|
||||||
|
int digits = 1;
|
||||||
|
while (s >= comp) {
|
||||||
|
digits++;
|
||||||
|
comp *= 10;
|
||||||
|
}
|
||||||
|
return digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_children(stone s, int generations_remaining) {
|
||||||
|
if (generations_remaining == 0) return 1;
|
||||||
|
|
||||||
|
int next_gen = generations_remaining - 1;
|
||||||
|
int stone_num_digits = num_digits(s);
|
||||||
|
int nc;
|
||||||
|
|
||||||
|
if (s == 0ll) {
|
||||||
|
nc = num_children(1, next_gen);
|
||||||
|
} else if (stone_num_digits % 2 == 0) {
|
||||||
|
stone comp = 10;
|
||||||
|
for (int i = 1; i < stone_num_digits / 2; i++) comp *= 10;
|
||||||
|
nc = num_children(s / comp, next_gen) + num_children(s % comp, next_gen);
|
||||||
|
} else {
|
||||||
|
nc = num_children(s * 2024, next_gen);
|
||||||
|
}
|
||||||
|
return nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stones change(stone s) {
|
||||||
|
Stones stones;
|
||||||
|
int stone_num_digits = num_digits(s);
|
||||||
|
|
||||||
|
if (s == 0ll) {
|
||||||
|
stones.first = 1;
|
||||||
|
stones.second = -1;
|
||||||
|
} else if (stone_num_digits % 2 == 0) {
|
||||||
|
stone comp = 10;
|
||||||
|
for (int i = 1; i < stone_num_digits / 2; i++) comp *= 10;
|
||||||
|
stones.first = s / comp;
|
||||||
|
stones.second = s % comp;
|
||||||
|
} else {
|
||||||
|
stones.first = s * 2024;
|
||||||
|
stones.second = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stones;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *input = aoc_read_input();
|
||||||
|
|
||||||
|
StonePile stone_array[50000], next_stone_array[50000];
|
||||||
|
int stone_count = 0, next_stone_count = 0;
|
||||||
|
char *current_token = strtok(input, " ");
|
||||||
|
|
||||||
|
long long stone_count_sum = 0ll;
|
||||||
|
long long big_stone_count_sum = 0ll;
|
||||||
|
|
||||||
|
while (current_token != NULL) {
|
||||||
|
stone_array[stone_count].value = atoll(current_token);
|
||||||
|
stone_array[stone_count].count = 1ll;
|
||||||
|
stone_count++;
|
||||||
|
current_token = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 75; i++) {
|
||||||
|
next_stone_count = 0;
|
||||||
|
for (int j = 0; j < stone_count; j++) {
|
||||||
|
Stones s = change(stone_array[j].value);
|
||||||
|
next_stone_array[next_stone_count].value = s.first;
|
||||||
|
next_stone_array[next_stone_count].count = stone_array[j].count;
|
||||||
|
next_stone_count++;
|
||||||
|
if (s.second != -1) {
|
||||||
|
next_stone_array[next_stone_count].value = s.second;
|
||||||
|
next_stone_array[next_stone_count].count = stone_array[j].count;
|
||||||
|
next_stone_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qsort(next_stone_array, next_stone_count, sizeof(StonePile), sort_stone_piles);
|
||||||
|
|
||||||
|
stone_array[0].count = next_stone_array[0].count;
|
||||||
|
stone_array[0].value = next_stone_array[0].value;
|
||||||
|
stone_count = 1;
|
||||||
|
|
||||||
|
for (int j = 1; j < next_stone_count; j++) {
|
||||||
|
if (next_stone_array[j].value == stone_array[stone_count - 1].value) {
|
||||||
|
stone_array[stone_count - 1].count += next_stone_array[j].count;
|
||||||
|
} else {
|
||||||
|
stone_count++;
|
||||||
|
stone_array[stone_count - 1].value = next_stone_array[j].value;
|
||||||
|
stone_array[stone_count - 1].count = next_stone_array[j].count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 24) {
|
||||||
|
stone_count_sum = 0;
|
||||||
|
for (int j = 0; j < stone_count; j++) {
|
||||||
|
stone_count_sum += stone_array[j].count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 74) {
|
||||||
|
big_stone_count_sum = 0;
|
||||||
|
for (int j = 0; j < stone_count; j++) {
|
||||||
|
big_stone_count_sum += stone_array[j].count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf("Part 1: %lld\n", stone_count_sum);
|
||||||
|
printf("Part 2: %lld\n", big_stone_count_sum);
|
||||||
|
|
||||||
|
aoc_free();
|
||||||
|
return 0;
|
||||||
|
}
|
218
c/2024/12/garden_groups.c
Normal file
218
c/2024/12/garden_groups.c
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../../lib/aoc.h"
|
||||||
|
|
||||||
|
struct Map;
|
||||||
|
|
||||||
|
typedef struct Region {
|
||||||
|
struct Map *map;
|
||||||
|
char plant;
|
||||||
|
int positions[1000];
|
||||||
|
int positions_count;
|
||||||
|
} Region;
|
||||||
|
|
||||||
|
typedef struct Map {
|
||||||
|
char *data;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int input_length;
|
||||||
|
Region regions[1000];
|
||||||
|
int regions_count;
|
||||||
|
} Map;
|
||||||
|
|
||||||
|
int region_perimeter(Region *r) {
|
||||||
|
int perimeter = 0;
|
||||||
|
for (int i = 0; i < r->positions_count; i++) {
|
||||||
|
int position = r->positions[i];
|
||||||
|
if (position - r->map->width < 0 || r->map->data[position - r->map->width] != r->plant - 'A' + 'a') {
|
||||||
|
perimeter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position - 1 < 0 || r->map->data[position - 1] != r->plant - 'A' + 'a') {
|
||||||
|
perimeter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position + 1 > r->map->input_length || r->map->data[position + 1] != r->plant - 'A' + 'a') {
|
||||||
|
perimeter++;
|
||||||
|
}
|
||||||
|
if (position + r->map->width > r->map->input_length || r->map->data[position + r->map->width] != r->plant - 'A' + 'a') {
|
||||||
|
perimeter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return perimeter;
|
||||||
|
}
|
||||||
|
|
||||||
|
int region_inner_corner_count(Region *r) {
|
||||||
|
int inner_corners = 0;
|
||||||
|
for (int i = 0; i < r->positions_count; i++) {
|
||||||
|
int position = r->positions[i];
|
||||||
|
bool up = false, down = false, left = false, right = false;
|
||||||
|
bool up_left = false, down_left = false, up_right = false, down_right = false;
|
||||||
|
|
||||||
|
if (position - r->map->width - 1 >= 0 && r->map->data[position - r->map->width - 1] == r->plant - 'A' + 'a') {
|
||||||
|
up_left = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position - r->map->width >= 0 && r->map->data[position - r->map->width] == r->plant - 'A' + 'a') {
|
||||||
|
up = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position - r->map->width + 1 >= 0 && r->map->data[position - r->map->width + 1] == r->plant - 'A' + 'a') {
|
||||||
|
up_right = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position - 1 > 0 && r->map->data[position - 1] == r->plant - 'A' + 'a') {
|
||||||
|
left = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position + 1 < r->map->input_length && r->map->data[position + 1] == r->plant - 'A' + 'a') {
|
||||||
|
right = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position + r->map->width - 1 < r->map->input_length && r->map->data[position + r->map->width - 1] == r->plant - 'A' + 'a') {
|
||||||
|
down_left = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position + r->map->width < r->map->input_length && r->map->data[position + r->map->width] == r->plant - 'A' + 'a') {
|
||||||
|
down = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position + r->map->width + 1 < r->map->input_length && r->map->data[position + r->map->width + 1] == r->plant - 'A' + 'a') {
|
||||||
|
down_right = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (up && left && !up_left) inner_corners++;
|
||||||
|
if (up && right && !up_right) inner_corners++;
|
||||||
|
if (down && left && !down_left) inner_corners++;
|
||||||
|
if (down && right && !down_right) inner_corners++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inner_corners;
|
||||||
|
}
|
||||||
|
|
||||||
|
int region_outer_corner_count(Region *r) {
|
||||||
|
int outer_corners = 0;
|
||||||
|
for (int i = 0; i < r->positions_count; i++) {
|
||||||
|
int position = r->positions[i];
|
||||||
|
int fences = 0;
|
||||||
|
bool top_fence = false, left_fence = false, right_fence = false, bottom_fence = false;
|
||||||
|
if (position - r->map->width < 0 || r->map->data[position - r->map->width] != r->plant - 'A' + 'a') {
|
||||||
|
top_fence = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position - 1 < 0 || r->map->data[position - 1] != r->plant - 'A' + 'a') {
|
||||||
|
left_fence = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position + 1 > r->map->input_length || r->map->data[position + 1] != r->plant - 'A' + 'a') {
|
||||||
|
right_fence = true;
|
||||||
|
}
|
||||||
|
if (position + r->map->width > r->map->input_length || r->map->data[position + r->map->width] != r->plant - 'A' + 'a') {
|
||||||
|
bottom_fence = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top_fence && left_fence) outer_corners++;
|
||||||
|
if (bottom_fence && left_fence) outer_corners++;
|
||||||
|
if (top_fence && right_fence) outer_corners++;
|
||||||
|
if (bottom_fence && right_fence) outer_corners++;
|
||||||
|
}
|
||||||
|
return outer_corners;
|
||||||
|
}
|
||||||
|
|
||||||
|
int region_price(Region *r) {
|
||||||
|
return region_perimeter(r) * r->positions_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int region_price_2(Region *r) {
|
||||||
|
int roc = region_outer_corner_count(r);
|
||||||
|
int ric = region_inner_corner_count(r);
|
||||||
|
return (roc + ric) * r->positions_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *input = aoc_read_input();
|
||||||
|
int input_length = strlen(input);
|
||||||
|
|
||||||
|
Map m;
|
||||||
|
fflush(stdout);
|
||||||
|
m.data = input;
|
||||||
|
m.width = strchr(input, '\n') - input + 1;
|
||||||
|
m.height = input_length / m.width;
|
||||||
|
m.regions_count = 0;
|
||||||
|
m.input_length = input_length;
|
||||||
|
|
||||||
|
// initialize regions
|
||||||
|
for (int i = 0; i < input_length; i++) {
|
||||||
|
if (m.data[i] == '\n' || m.data[i] < 'A' || m.data[i] > 'Z') continue;
|
||||||
|
|
||||||
|
Region *r = &(m.regions[m.regions_count++]);
|
||||||
|
r->plant = m.data[i];
|
||||||
|
r->positions_count = 0;
|
||||||
|
r->map = &m;
|
||||||
|
|
||||||
|
int next_positions[1000];
|
||||||
|
next_positions[0] = i;
|
||||||
|
int next_positions_count = 1;
|
||||||
|
|
||||||
|
int nn_positions[1000];
|
||||||
|
int nn_positions_count = 0;
|
||||||
|
|
||||||
|
while (next_positions_count > 0) {
|
||||||
|
for (int j = 0; j < next_positions_count; j++) {
|
||||||
|
int next_position = next_positions[j];
|
||||||
|
r->positions[r->positions_count++] = next_position;
|
||||||
|
m.data[next_position] = m.data[next_position] - 'A' + 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < next_positions_count; j++) {
|
||||||
|
int next_position = next_positions[j];
|
||||||
|
if (next_position - m.width > 0 && m.data[next_position - m.width] == r->plant) {
|
||||||
|
nn_positions[nn_positions_count++] = next_position - m.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_position - 1 > 0 && m.data[next_position - 1] == r->plant) {
|
||||||
|
nn_positions[nn_positions_count++] = next_position - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_position + 1 < input_length && m.data[next_position + 1] == r->plant) {
|
||||||
|
nn_positions[nn_positions_count++] = next_position + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_position + m.width < input_length && m.data[next_position + m.width] == r->plant) {
|
||||||
|
nn_positions[nn_positions_count++] = next_position + m.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(nn_positions, nn_positions_count, sizeof(int), aoc_sort_int);
|
||||||
|
if (nn_positions_count == 0) break;
|
||||||
|
|
||||||
|
next_positions_count = 1;
|
||||||
|
next_positions[0] = nn_positions[0];
|
||||||
|
for (int j = 1; j < nn_positions_count; j++) {
|
||||||
|
if (nn_positions[j] != next_positions[next_positions_count - 1]) {
|
||||||
|
next_positions[next_positions_count++] = nn_positions[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nn_positions_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cost = 0;
|
||||||
|
int cost_2 = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < m.regions_count; i++) {
|
||||||
|
cost += region_price(&m.regions[i]);
|
||||||
|
cost_2 += region_price_2(&m.regions[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Part 1: %d\n", cost);
|
||||||
|
printf("Part 2: %lld\n", cost_2);
|
||||||
|
|
||||||
|
aoc_free();
|
||||||
|
return 0;
|
||||||
|
}
|
101
c/2024/13/claw_contraption.c
Normal file
101
c/2024/13/claw_contraption.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../../lib/aoc.h"
|
||||||
|
|
||||||
|
typedef struct Ratio {
|
||||||
|
long long num;
|
||||||
|
long long denom;
|
||||||
|
} Ratio;
|
||||||
|
|
||||||
|
typedef struct Line {
|
||||||
|
Ratio slope;
|
||||||
|
Ratio offset;
|
||||||
|
} Line;
|
||||||
|
|
||||||
|
Ratio ratio_subtract(Ratio r1, Ratio r2) {
|
||||||
|
Ratio r3;
|
||||||
|
r3.num= r1.num * r2.denom - r2.num * r1.denom;
|
||||||
|
r3.denom= r1.denom* r2.denom;
|
||||||
|
return r3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ratio ratio_divide(Ratio r1, Ratio r2) {
|
||||||
|
Ratio r3;
|
||||||
|
r3.num = r1.num * r2.denom;
|
||||||
|
r3.denom = r1.denom * r2.num;
|
||||||
|
return r3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool proper(Ratio r) {
|
||||||
|
return r.num % r.denom == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ratio intersect_x(Line l1, Line l2) {
|
||||||
|
Ratio left_side = ratio_subtract(l1.slope, l2.slope);
|
||||||
|
Ratio right_side = ratio_subtract(l2.offset, l1.offset);
|
||||||
|
Ratio divided = ratio_divide(right_side, left_side);
|
||||||
|
printf("left: %lld/%lld, right: %lld/%lld, divided: %lld/%lld\n", left_side.num, left_side.denom, right_side.num, right_side.denom, divided.num, divided.denom);
|
||||||
|
return divided;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long li_cost(int ax, int ay, int bx, int by, long long px, long long py) {
|
||||||
|
printf("prize at %lld, %lld\n", px, py);
|
||||||
|
Line b_line;
|
||||||
|
b_line.slope.num = by;
|
||||||
|
b_line.slope.denom = bx;
|
||||||
|
b_line.offset.num = 0;
|
||||||
|
b_line.offset.denom = 1;
|
||||||
|
|
||||||
|
Line a_line;
|
||||||
|
a_line.slope.num = ay;
|
||||||
|
a_line.slope.denom = ax;
|
||||||
|
a_line.offset.num = -1 * ((px * ay) - (py * ax));
|
||||||
|
a_line.offset.denom = ax;
|
||||||
|
|
||||||
|
Ratio r = intersect_x(b_line, a_line);
|
||||||
|
|
||||||
|
if (!proper(r)) {
|
||||||
|
printf("bzzt\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long long b_x_movement = (r.num / r.denom);
|
||||||
|
if (b_x_movement % bx != 0) return 0; // Fuuuuuuuuuuuuuuck this
|
||||||
|
long long b_cost = b_x_movement / bx;
|
||||||
|
long long a_x_movement = px - b_x_movement;
|
||||||
|
if (a_x_movement % ax != 0) return 0; // Fuuuuuuuuuuuuuuck this
|
||||||
|
long long a_cost = (a_x_movement / ax) * 3;
|
||||||
|
printf("b: %lld, a: %lld\n", b_x_movement, a_x_movement);
|
||||||
|
printf("b presses: %lld, a presses: %lld\n", b_x_movement / bx, a_x_movement / ax);
|
||||||
|
if (b_x_movement < 0 || a_x_movement < 0) return 0;
|
||||||
|
printf("cost: %lld\n", b_cost + a_cost);
|
||||||
|
return b_cost + a_cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int ax, ay, bx, by;
|
||||||
|
long long px, py;
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
long long cost = 0;
|
||||||
|
long long cost_2 = 0;
|
||||||
|
while((line = aoc_read_line()) != NULL) {
|
||||||
|
sscanf(line, "Button A: X+%d, Y+%d", &ax, &ay);
|
||||||
|
sscanf(aoc_read_line(), "Button B: X+%d, Y+%d", &bx, &by);
|
||||||
|
sscanf(aoc_read_line(), "Prize: X=%d, Y=%d", &px, &py);
|
||||||
|
aoc_read_line();
|
||||||
|
|
||||||
|
cost += li_cost(ax, ay, bx, by, px, py);
|
||||||
|
cost_2 += li_cost(ax, ay, bx, by, px + 10000000000000, py + 10000000000000);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Part 1: %lld\n", cost);
|
||||||
|
printf("Part 2: %lld\n", cost_2);
|
||||||
|
|
||||||
|
aoc_free();
|
||||||
|
return 0;
|
||||||
|
}
|
78
c/2024/14/restroom_redoubt.c
Normal file
78
c/2024/14/restroom_redoubt.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../../lib/aoc.h"
|
||||||
|
|
||||||
|
#define WIDTH 101
|
||||||
|
#define HEIGHT 103
|
||||||
|
#define CYCLES 100
|
||||||
|
|
||||||
|
typedef struct Robot {
|
||||||
|
int px;
|
||||||
|
int py;
|
||||||
|
int vx;
|
||||||
|
int vy;
|
||||||
|
} Robot;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
int px, py, vx, vy;
|
||||||
|
|
||||||
|
int q1 = 0, q2 = 0, q3 = 0, q4 = 0;
|
||||||
|
Robot robots[500];
|
||||||
|
int robots_count = 0;
|
||||||
|
|
||||||
|
while((line = aoc_read_line()) != NULL) {
|
||||||
|
sscanf(line, "p=%d,%d v=%d,%d", &px, &py, &vx, &vy);
|
||||||
|
robots[robots_count].px = px;
|
||||||
|
robots[robots_count].py = py;
|
||||||
|
robots[robots_count].vx = vx;
|
||||||
|
robots[robots_count].vy = vy;
|
||||||
|
robots_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char blank_map[((WIDTH + 1) * HEIGHT) + 1];
|
||||||
|
for (int i = 0; i < (WIDTH + 1) * HEIGHT; i++) {
|
||||||
|
blank_map[i] = i % (WIDTH + 1) == WIDTH ? '\n' : '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
char map[((WIDTH + 1) * HEIGHT) + 1];
|
||||||
|
|
||||||
|
// Isn't it lovely?
|
||||||
|
char *christmas_tree = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
strcpy(map, blank_map);
|
||||||
|
for (int j = 0; j < robots_count; j++) {
|
||||||
|
map[robots[j].px + (robots[j].py * (WIDTH + 1))] = 'X';
|
||||||
|
robots[j].px += robots[j].vx;
|
||||||
|
robots[j].px = (robots[j].px + WIDTH) % WIDTH;
|
||||||
|
robots[j].py += robots[j].vy;
|
||||||
|
robots[j].py = (robots[j].py + HEIGHT) % HEIGHT;
|
||||||
|
}
|
||||||
|
if (strstr(map, christmas_tree) != NULL) break;
|
||||||
|
|
||||||
|
if (i == CYCLES - 1) {
|
||||||
|
for (int j = 0; j < robots_count; j++) {
|
||||||
|
Robot r = robots[j];
|
||||||
|
if (r.px < WIDTH / 2 && r.py < HEIGHT / 2) q1++;
|
||||||
|
if (r.px > WIDTH / 2 && r.py < HEIGHT / 2) q2++;
|
||||||
|
if (r.px < WIDTH / 2 && r.py > HEIGHT / 2) q3++;
|
||||||
|
if (r.px > WIDTH / 2 && r.py > HEIGHT / 2) q4++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uncomment this to print the pretty christmas tree
|
||||||
|
// printf("%s\n", map);
|
||||||
|
|
||||||
|
printf("Part 1: %lld\n", q1 * q2 * q3 * q4);
|
||||||
|
printf("Part 2: %lld\n", i);
|
||||||
|
|
||||||
|
aoc_free();
|
||||||
|
return 0;
|
||||||
|
}
|
166
c/lib/intcode.h
Normal file
166
c/lib/intcode.h
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include "./aoc.h"
|
||||||
|
|
||||||
|
#define ROM_LENGTH 1000
|
||||||
|
#define OUTPUT_BUFFER_LENGTH 1000
|
||||||
|
|
||||||
|
#define POSITION_MODE 0
|
||||||
|
#define IMMEDIATE_MODE 1
|
||||||
|
|
||||||
|
int rom[ROM_LENGTH];
|
||||||
|
int rom_count;
|
||||||
|
|
||||||
|
typedef struct IC {
|
||||||
|
int *rom;
|
||||||
|
int *data;
|
||||||
|
int program_counter;
|
||||||
|
bool halted;
|
||||||
|
int output_buffer[OUTPUT_BUFFER_LENGTH];
|
||||||
|
int output_buffer_count;
|
||||||
|
} IC;
|
||||||
|
|
||||||
|
int ic_peek(IC *c, int address) {
|
||||||
|
return c->data[address];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_poke(IC *c, int address, int value) {
|
||||||
|
c->data[address] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ic_read(IC *c) {
|
||||||
|
return ic_peek(c, c->program_counter++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_write(IC *c, int value) {
|
||||||
|
ic_poke(c, ic_peek(c, c->program_counter++), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_halt(IC *c) {
|
||||||
|
c->halted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_instruction_add(IC *c, int modes) {
|
||||||
|
bool x_mode = modes % 10;
|
||||||
|
modes /= 10;
|
||||||
|
bool y_mode = modes % 10;
|
||||||
|
modes /= 10;
|
||||||
|
|
||||||
|
int x = ic_read(c);
|
||||||
|
if (x_mode == POSITION_MODE) x = ic_peek(c, x);
|
||||||
|
int y = ic_read(c);
|
||||||
|
if (y_mode == POSITION_MODE) y = ic_peek(c, y);
|
||||||
|
|
||||||
|
ic_write(c, x + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_instruction_multiply(IC *c, int modes) {
|
||||||
|
bool x_mode = modes % 10;
|
||||||
|
modes /= 10;
|
||||||
|
bool y_mode = modes % 10;
|
||||||
|
modes /= 10;
|
||||||
|
|
||||||
|
int x = ic_read(c);
|
||||||
|
if (x_mode == POSITION_MODE) x = ic_peek(c, x);
|
||||||
|
int y = ic_read(c);
|
||||||
|
if (y_mode == POSITION_MODE) y = ic_peek(c, y);
|
||||||
|
|
||||||
|
ic_write(c, x * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_instruction_input(IC *c, int _modes) {
|
||||||
|
ic_write(c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_instruction_output(IC *c, int modes) {
|
||||||
|
if (c->output_buffer_count >= OUTPUT_BUFFER_LENGTH) {
|
||||||
|
printf("Output buffer overflow!\n");
|
||||||
|
ic_halt(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mode = modes % 10;
|
||||||
|
modes /= 10;
|
||||||
|
int to_output = ic_read(c);
|
||||||
|
if (mode == POSITION_MODE) to_output = ic_peek(c, to_output);
|
||||||
|
c->output_buffer[c->output_buffer_count++] = to_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_instruction_halt(IC *c, int _modes) {
|
||||||
|
ic_halt(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ic_execute_instruction(IC *c) {
|
||||||
|
int instruction = ic_read(c);
|
||||||
|
int opcode = instruction % 100;
|
||||||
|
int modes = instruction / 100;
|
||||||
|
// printf("Running %d: opcode %d with modes %d\n", instruction, opcode, modes);
|
||||||
|
// printf("PC: %d\n", c->program_counter - 1);
|
||||||
|
switch(opcode) {
|
||||||
|
case 1:
|
||||||
|
ic_instruction_add(c, modes);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ic_instruction_multiply(c, modes);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ic_instruction_input(c, modes);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ic_instruction_output(c, modes);
|
||||||
|
break;
|
||||||
|
case 99:
|
||||||
|
ic_instruction_halt(c, modes);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Invalid opcode [%d] encountered at %d\n", opcode, c->program_counter - 1);
|
||||||
|
ic_instruction_halt(c, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_print(IC *c) {
|
||||||
|
printf("PC: %d\n", c->program_counter);
|
||||||
|
|
||||||
|
for (int i = 0; i < rom_count; i++) {
|
||||||
|
printf("%6d ", c->data[i]);
|
||||||
|
if (i % 8 == 7) printf("\n");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Output buffer: ");
|
||||||
|
for (int i = 0; i < c->output_buffer_count; i++) {
|
||||||
|
printf("[%d] ", c->output_buffer[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_reset(IC *c) {
|
||||||
|
memcpy(c->data, c->rom, rom_count * sizeof(int));
|
||||||
|
c->program_counter = 0;
|
||||||
|
c->halted = true;
|
||||||
|
c->output_buffer_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_run(IC *c) {
|
||||||
|
c->halted = false;
|
||||||
|
while (!c->halted) ic_execute_instruction(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
IC *ic_new_computer(void) {
|
||||||
|
IC *c = malloc(sizeof(IC));
|
||||||
|
c->rom = rom;
|
||||||
|
c->data = malloc(rom_count * sizeof(int));
|
||||||
|
ic_reset(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ic_load_rom_from_input(void) {
|
||||||
|
char *input = aoc_read_input();
|
||||||
|
|
||||||
|
char *token = strtok(input, ",");
|
||||||
|
while (token != NULL) {
|
||||||
|
rom[rom_count++] = atoi(token);
|
||||||
|
token = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
return rom_count;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user