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