Compare commits

..

No commits in common. "2af6066ee3da9254a5ed6986cb4c300d95d4f3d6" and "9d0990e5e89c4fd7534b2960a7fed789ff468f0a" have entirely different histories.

35 changed files with 5 additions and 1898 deletions

View File

@ -157,19 +157,10 @@ namespace Kernel
BAN::ErrorOr<long> PseudoTerminalMaster::ioctl_impl(int request, void* argument) BAN::ErrorOr<long> PseudoTerminalMaster::ioctl_impl(int request, void* argument)
{ {
switch (request) auto slave = m_slave.lock();
{ if (!slave)
case FIONREAD:
*static_cast<int*>(argument) = m_buffer_size;
return 0;
case TIOCGWINSZ:
case TIOCSWINSZ:
if (auto slave = m_slave.lock())
return slave->ioctl(request, argument);
return BAN::Error::from_errno(ENODEV); return BAN::Error::from_errno(ENODEV);
} return slave->ioctl(request, argument);
return BAN::Error::from_errno(ENOTSUP);
} }
PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid) PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid)

View File

@ -202,11 +202,6 @@ namespace Kernel
TRY(set_font(BAN::move(new_font))); TRY(set_font(BAN::move(new_font)));
return 0; return 0;
} }
case FIONREAD:
{
*static_cast<int*>(argument) = m_output.flush ? m_output.bytes : 0;
return 0;
}
case TIOCGWINSZ: case TIOCGWINSZ:
{ {
auto* winsize = static_cast<struct winsize*>(argument); auto* winsize = static_cast<struct winsize*>(argument);

View File

@ -2,7 +2,6 @@ add_custom_target(userspace)
#add_subdirectory(aoc2023) #add_subdirectory(aoc2023)
#add_subdirectory(aoc2024) #add_subdirectory(aoc2024)
#add_subdirectory(aoc2025)
add_subdirectory(libraries) add_subdirectory(libraries)
add_subdirectory(programs) add_subdirectory(programs)
add_subdirectory(tests) add_subdirectory(tests)

View File

@ -1,37 +0,0 @@
set(AOC2025_PROJECTS
day1
day2
day3
day4
day5
day6
day7
day8
day9
day10
day11
day12
full
)
set(BANAN_AOC2025_BIN ${CMAKE_INSTALL_BINDIR}/aoc2025)
set(BANAN_AOC2025_INPUT ${BANAN_SHARE}/aoc2025)
set(CMAKE_INSTALL_BINDIR ${BANAN_AOC2025_BIN})
add_custom_target(aoc2025)
file(GLOB_RECURSE input_files "input/*")
foreach(file ${input_files})
install(FILES ${file} DESTINATION ${BANAN_AOC2025_INPUT})
endforeach()
foreach(AOC2025_PROJECT ${AOC2025_PROJECTS})
add_subdirectory(${AOC2025_PROJECT})
add_dependencies(aoc2025 aoc2025_${AOC2025_PROJECT})
target_link_options(aoc2025_${AOC2025_PROJECT} PRIVATE -nolibc)
target_compile_options(aoc2025_${AOC2025_PROJECT} PRIVATE -g -O2 -Wall -Wextra -Werror)
endforeach()
add_dependencies(userspace aoc2025)

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day-template ${SOURCES})
banan_include_headers(aoc2025_day-template ban)
banan_link_library(aoc2025_day-template libc)
install(TARGETS aoc2025_day-template OPTIONAL)

View File

@ -1,47 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
i64 part1(FILE* fp)
{
(void)fp;
return -1;
}
i64 part2(FILE* fp)
{
(void)fp;
return -1;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day-template_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day1 ${SOURCES})
banan_include_headers(aoc2025_day1 ban)
banan_link_library(aoc2025_day1 libc)
install(TARGETS aoc2025_day1 OPTIONAL)

View File

@ -1,87 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
i64 part1(FILE* fp)
{
int amount;
char direction;
i32 value = 50;
i32 result = 0;
while (fscanf(fp, "%c%d\n", &direction, &amount) == 2)
{
switch (direction)
{
case 'L':
value = (value - amount) % 100;
break;
case 'R':
value = (value + amount) % 100;
break;
}
if (value == 0)
result++;
}
return result;
}
i64 part2(FILE* fp)
{
int amount;
char direction;
i32 value = 50;
i32 result = 0;
while (fscanf(fp, "%c%d\n", &direction, &amount) == 2)
{
switch (direction)
{
case 'L':
if (amount >= value)
result += (value != 0) + (amount - value) / 100;
value = (((value - amount) % 100) + 100) % 100;
break;
case 'R':
result += (value + amount) / 100;
value = (value + amount) % 100;
break;
}
}
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day1_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day10 ${SOURCES})
banan_include_headers(aoc2025_day10 ban)
banan_link_library(aoc2025_day10 libc)
install(TARGETS aoc2025_day10 OPTIONAL)

View File

@ -1,216 +0,0 @@
#include <BAN/String.h>
#include <BAN/Vector.h>
#include <ctype.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
struct Machine
{
u32 indicator;
BAN::Vector<u32> buttons;
BAN::Vector<u32> joltages;
};
static BAN::Vector<Machine> parse_machines(FILE* fp)
{
BAN::Vector<Machine> machines;
BAN::String line;
char buffer[128];
while (fgets(buffer, sizeof(buffer), fp))
{
MUST(line.append(buffer));
if (line.back() != '\n')
continue;
if (line.front() != '[')
break;
Machine machine {};
size_t i = 1;
while (line[i] != ']')
{
if (line[i] == '#')
machine.indicator |= 1 << (i - 1);
i++;
}
i += 2;
while (line[i++] == '(')
{
u32 button = 0;
while (line[i] != ')')
{
if (line[i] == ',')
i++;
u32 index = 0;
while (isdigit(line[i]))
index = (index * 10) + (line[i++] - '0');
button |= 1 << index;
}
MUST(machine.buttons.push_back(button));
i += 2;
}
i--;
ASSERT(line[i] == '{');
while (line[i++] != '}')
{
u32 joltage = 0;
while (isdigit(line[i]))
joltage = (joltage * 10) + (line[i++] - '0');
MUST(machine.joltages.push_back(joltage));
}
MUST(machines.push_back(BAN::move(machine)));
line.clear();
}
return machines;
}
i64 part1(FILE* fp)
{
static constexpr bool (*works_with_n_buttons)(const Machine&, size_t, size_t, u32) =
[](const Machine& machine, size_t buttons, size_t index, u32 state) -> bool
{
if (buttons == 0)
return state == machine.indicator;
for (size_t i = index; i < machine.buttons.size(); i++)
if (works_with_n_buttons(machine, buttons - 1, i + 1, state ^ machine.buttons[i]))
return true;
return false;
};
i64 result = 0;
auto machines = parse_machines(fp);
for (const auto& machine : machines)
{
for (size_t i = 1; i < machine.buttons.size(); i++)
{
if (!works_with_n_buttons(machine, i, 0, 0))
continue;
result += i;
break;
}
}
return result;
}
// based on https://www.reddit.com/r/adventofcode/comments/1pk87hl/2025_day_10_part_2_bifurcate_your_way_to_victory/
static u32 minimum_presses(const BAN::Vector<BAN::Vector<u32>>& possible_indicators, const BAN::Vector<u32>& buttons, const BAN::Vector<u32>& joltages)
{
bool all_zeroes = true;
for (u32 joltage : joltages)
if (joltage != 0)
all_zeroes = false;
if (all_zeroes)
return 0;
u32 indicator = 0;
for (size_t i = 0; i < joltages.size(); i++)
if (joltages[i] % 2)
indicator |= 1 << i;
u32 result = 1'000'000;
for (u32 button_mask : possible_indicators[indicator])
{
size_t button_count = 0;
BAN::Vector<u32> new_joltages = joltages;
for (size_t i = 0; i < buttons.size(); i++)
{
if (!(button_mask & (1 << i)))
continue;
button_count++;
for (size_t bit = 0; bit < new_joltages.size(); bit++)
{
if (!(buttons[i] & (1 << bit)))
continue;
if (new_joltages[bit] == 0)
goto unusable;
new_joltages[bit]--;
}
}
for (u32& joltage : new_joltages)
joltage /= 2;
result = BAN::Math::min<u32>(result, button_count + 2 * minimum_presses(possible_indicators, buttons, new_joltages));
unusable:
(void)0;
}
return result;
}
i64 part2(FILE* fp)
{
i64 result = 0;
auto machines = parse_machines(fp);
for (const auto& machine : machines)
{
const size_t bits = machine.joltages.size();
BAN::Vector<BAN::Vector<u32>> possible_indicators;
MUST(possible_indicators.resize(1u << bits));
for (size_t button_mask = 0; button_mask < (1u << machine.buttons.size()); button_mask++)
{
u32 indicator = 0;
for (size_t button = 0; button < machine.buttons.size(); button++)
if (button_mask & (1 << button))
indicator ^= machine.buttons[button];
MUST(possible_indicators[indicator].push_back(button_mask));
}
result += minimum_presses(possible_indicators, machine.buttons, machine.joltages);
}
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day10_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day11 ${SOURCES})
banan_include_headers(aoc2025_day11 ban)
banan_link_library(aoc2025_day11 libc)
install(TARGETS aoc2025_day11 OPTIONAL)

View File

@ -1,151 +0,0 @@
#include <BAN/HashMap.h>
#include <BAN/StringView.h>
#include <BAN/Vector.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
struct Device
{
u32 distance { 0 };
BAN::Vector<u32> outputs;
};
static inline constexpr u32 name_to_u32(BAN::StringView name)
{
ASSERT(name.size() == 3);
return name[0] | (name[1] << 8) | (name[2] << 16);
}
static BAN::HashMap<u32, Device> parse_devices(FILE* fp, const char* first_node)
{
BAN::HashMap<u32, Device> result;
char buffer[128];
while (fgets(buffer, sizeof(buffer), fp))
{
auto buffer_sv = BAN::StringView(buffer);
ASSERT(buffer_sv.back() == '\n');
buffer_sv = buffer_sv.substring(0, buffer_sv.size() - 1);
const u32 device = name_to_u32(buffer_sv.substring(0, 3));
auto it = result.find(device);
if (it == result.end())
it = MUST(result.emplace(device));
const auto outputs = MUST(buffer_sv.substring(5).split(' '));
for (auto name : outputs)
MUST(it->value.outputs.push_back(name_to_u32(name)));
}
MUST(result.emplace(name_to_u32("out")));
BAN::Vector<u32> to_update;
MUST(to_update.push_back(name_to_u32(first_node)));
u32 distance = 1;
while (!to_update.empty())
{
BAN::Vector<u32> next_update;
for (u32 name : to_update)
{
auto& device = result[name];
if (device.distance >= distance)
continue;
for (u32 output : device.outputs)
MUST(next_update.push_back(output));
device.distance = distance;
}
to_update = BAN::move(next_update);
distance++;
}
return result;
}
static i64 count_paths(const BAN::HashMap<u32, Device>& devices, BAN::HashMap<u32, u32>& cache, u32 current, u32 destination)
{
if (current == destination)
return 1;
if (auto it = cache.find(current); it != cache.end())
return it->value;
if (devices[current].distance >= devices[destination].distance)
return 0;
i64 result = 0;
const auto& outputs = devices[current].outputs;
for (u32 output : outputs)
result += count_paths(devices, cache, output, destination);
MUST(cache.emplace(current, result));
return result;
}
i64 part1(FILE* fp)
{
auto devices = parse_devices(fp, "you");
BAN::HashMap<u32, u32> cache;
return count_paths(devices, cache, name_to_u32("you"), name_to_u32("out"));
}
i64 part2(FILE* fp)
{
auto devices = parse_devices(fp, "svr");
const bool fft_before = devices[name_to_u32("fft")].distance < devices[name_to_u32("dac")].distance;
const u32 real_path[] {
name_to_u32("svr"),
fft_before ? name_to_u32("fft") : name_to_u32("dac"),
fft_before ? name_to_u32("dac") : name_to_u32("fft"),
name_to_u32("out"),
};
i64 result = 1;
for (size_t i = 1; i < sizeof(real_path) / sizeof(*real_path); i++)
{
BAN::HashMap<u32, u32> cache;
result *= count_paths(devices, cache, real_path[i - 1], real_path[i]);
}
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day11_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day12 ${SOURCES})
banan_include_headers(aoc2025_day12 ban)
banan_link_library(aoc2025_day12 libc)
install(TARGETS aoc2025_day12 OPTIONAL)

View File

@ -1,80 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
// ehh im not happy about this but all inputs were crafted such that there
// is no need to overlap any presents, so a simple 3x3 fitting check works
i64 part1(FILE* fp)
{
char chs[2] {};
chs[0] = fgetc(fp);
chs[1] = fgetc(fp);
char ch;
while ((ch = fgetc(fp)) != 'x')
{
chs[0] = chs[1];
chs[1] = ch;
}
ungetc(ch, fp);
ungetc(chs[0], fp);
ungetc(chs[1], fp);
i64 result = 0;
u32 w, h;
while (fscanf(fp, "%" SCNu32 "x%" SCNu32 ":", &w, &h) == 2)
{
u32 blocks = 0;
u32 count;
while (fscanf(fp, "%" SCNu32 "%c", &count, &ch) == 2 && ch != '\n')
blocks += count;
blocks += count;
if ((w / 3) * (h / 3) >= blocks)
result++;
}
return result;
}
i64 part2(FILE* fp)
{
(void)fp;
return -1;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day12_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day2 ${SOURCES})
banan_include_headers(aoc2025_day2 ban)
banan_link_library(aoc2025_day2 libc)
install(TARGETS aoc2025_day2 OPTIONAL)

View File

@ -1,106 +0,0 @@
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
i64 part1(FILE* fp)
{
const auto is_invalid_id =
[](u64 id) -> bool
{
u64 temp_id = id;
u64 repeat = 0;
u64 mult = 1;
while (repeat * mult + repeat < id)
{
repeat += (temp_id % 10) * mult;
temp_id /= 10;
mult *= 10;
}
if (temp_id < mult / 10)
return false;
return repeat * mult + repeat == id;
};
u64 result = 0;
u64 start, end;
while (fscanf(fp, "%" SCNu64 "-%" SCNu64 ",", &start, &end) >= 2)
for (u64 id = start; id <= end; id++)
if (is_invalid_id(id))
result += id;
return result;
}
i64 part2(FILE* fp)
{
const auto is_invalid_id =
[](u64 id) -> bool
{
u64 temp_id = id;
u64 repeat = 0;
u64 mult = 1;
while (repeat * mult + repeat < id)
{
repeat += (temp_id % 10) * mult;
temp_id /= 10;
mult *= 10;
if (repeat < mult / 10)
continue;
u64 attempt = repeat * mult + repeat;
while (attempt < id)
attempt = attempt * mult + repeat;
if (attempt == id)
return true;
}
return false;
};
u64 result = 0;
u64 start, end;
while (fscanf(fp, "%" SCNu64 "-%" SCNu64 ",", &start, &end) >= 2)
for (u64 id = start; id <= end; id++)
if (is_invalid_id(id))
result += id;
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day2_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day3 ${SOURCES})
banan_include_headers(aoc2025_day3 ban)
banan_link_library(aoc2025_day3 libc)
install(TARGETS aoc2025_day3 OPTIONAL)

View File

@ -1,90 +0,0 @@
#include <BAN/Math.h>
#include <ctype.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
i64 get_max_joltage(const char* line, size_t batteries)
{
size_t line_len = 0;
while (isdigit(line[line_len]))
line_len++;
if (line_len < batteries)
return 0;
i64 result = 0;
size_t max_i = -1;
for (size_t battery = 0; battery < batteries; battery++)
{
i32 value = 0;
for (size_t i = max_i + 1; i < line_len - batteries + battery + 1; i++)
{
if (line[i] - '0' <= value)
continue;
value = line[i] - '0';
max_i = i;
if (value == 9)
break;
}
result = (result * 10) + value;
}
return result;
}
i64 part1(FILE* fp)
{
i64 result = 0;
char buffer[128];
while (fgets(buffer, sizeof(buffer), fp))
result += get_max_joltage(buffer, 2);
return result;
}
i64 part2(FILE* fp)
{
i64 result = 0;
char buffer[128];
while (fgets(buffer, sizeof(buffer), fp))
result += get_max_joltage(buffer, 12);
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day3_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day4 ${SOURCES})
banan_include_headers(aoc2025_day4 ban)
banan_link_library(aoc2025_day4 libc)
install(TARGETS aoc2025_day4 OPTIONAL)

View File

@ -1,125 +0,0 @@
#include <BAN/Vector.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using Grid = BAN::Vector<BAN::Vector<bool>>;
static Grid parse_grid(FILE* fp)
{
Grid grid;
MUST(grid.emplace_back());
char ch;
while ((ch = fgetc(fp)) != EOF)
{
switch (ch)
{
case '.':
case '@':
MUST(grid.back().push_back(ch == '@'));
break;
case '\n':
MUST(grid.emplace_back());
break;
}
}
while (grid.back().empty())
grid.pop_back();
return grid;
}
static i32 count_neighborgs(const Grid& grid, size_t x, size_t y)
{
i32 count = 0;
for (i32 yoff = -1; yoff <= 1; yoff++)
{
for (i32 xoff = -1; xoff <= 1; xoff++)
{
if (yoff == 0 && xoff == 0)
continue;
if (y + yoff >= grid.size())
continue;
if (x + xoff >= grid[y + yoff].size())
continue;
count += grid[y + yoff][x + xoff];
}
}
return count;
}
i64 part1(FILE* fp)
{
i32 result = 0;
auto grid = parse_grid(fp);
for (size_t y = 0; y < grid.size(); y++)
for (size_t x = 0; x < grid[y].size(); x++)
if (grid[y][x] && count_neighborgs(grid, x, y) < 4)
result++;
return result;
}
i64 part2(FILE* fp)
{
i32 result = 0;
auto grid = parse_grid(fp);
for (;;)
{
const auto old_result = result;
for (size_t y = 0; y < grid.size(); y++)
{
for (size_t x = 0; x < grid[y].size(); x++)
{
if (!grid[y][x] || count_neighborgs(grid, x, y) >= 4)
continue;
grid[y][x] = false;
result++;
}
}
if (result == old_result)
break;
}
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day4_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day5 ${SOURCES})
banan_include_headers(aoc2025_day5 ban)
banan_link_library(aoc2025_day5 libc)
install(TARGETS aoc2025_day5 OPTIONAL)

View File

@ -1,106 +0,0 @@
#include <BAN/Vector.h>
#include <BAN/Sort.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
struct Range
{
u64 min;
u64 max;
};
static BAN::Vector<Range> parse_ranges(FILE* fp)
{
BAN::Vector<Range> ranges;
u64 min, max;
ungetc('\n', fp);
while (fscanf(fp, "\n%" SCNu64 "-%" SCNu64, &min, &max) == 2)
MUST(ranges.emplace_back(min, max));
return ranges;
}
i64 part1(FILE* fp)
{
auto ranges = parse_ranges(fp);
i64 result = 0;
u64 value;
while (fscanf(fp, "%" SCNu64, &value) == 1)
{
bool is_fresh = false;
for (const auto range : ranges)
if (range.min <= value && value <= range.max)
is_fresh = true;
result += is_fresh;
}
return result;
}
i64 part2(FILE* fp)
{
auto ranges = parse_ranges(fp);
BAN::sort::sort(ranges.begin(), ranges.end(),
[](auto lhs, auto rhs) -> bool
{
return lhs.min < rhs.min;
}
);
for (size_t i = 0; i < ranges.size() - 1; i++)
{
auto& lhs = ranges[i];
auto& rhs = ranges[i + 1];
if (lhs.min > rhs.max || rhs.min > lhs.max)
continue;
lhs.min = BAN::Math::min(lhs.min, rhs.min);
lhs.max = BAN::Math::max(lhs.max, rhs.max);
ranges.remove(i + 1);
i--;
}
i64 result = 0;
for (auto range : ranges)
result += range.max - range.min + 1;
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day5_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day6 ${SOURCES})
banan_include_headers(aoc2025_day6 ban)
banan_link_library(aoc2025_day6 libc)
install(TARGETS aoc2025_day6 OPTIONAL)

View File

@ -1,152 +0,0 @@
#include <BAN/String.h>
#include <BAN/Vector.h>
#include <ctype.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
i64 part1(FILE* fp)
{
struct Operation
{
BAN::Vector<i64> values;
char op;
};
BAN::Vector<Operation> operations;
BAN::String line;
char line_buffer[128];
while (fgets(line_buffer, sizeof(line_buffer), fp))
{
MUST(line.append(line_buffer));
if (line.back() != '\n')
continue;
line.pop_back();
auto parts = MUST(line.sv().split(' '));
if (operations.size() < parts.size())
MUST(operations.resize(parts.size()));
if (isdigit(parts[0][0]))
{
for (size_t i = 0; i < parts.size(); i++)
MUST(operations[i].values.push_back(atoll(parts[i].data())));
line.clear();
}
else
{
for (size_t i = 0; i < parts.size(); i++)
operations[i].op = parts[i][0];
break;
}
}
i64 result = 0;
for (const auto& operation : operations)
{
i64 value;
switch (operation.op)
{
case '+':
value = 0;
for (auto val : operation.values)
value += val;
break;
case '*':
value = 1;
for (auto val : operation.values)
value *= val;
break;
default:
ASSERT_NOT_REACHED();
}
result += value;
}
return result;
}
i64 part2(FILE* fp)
{
BAN::Vector<BAN::String> lines;
MUST(lines.emplace_back());
char line_buffer[128];
while (fgets(line_buffer, sizeof(line_buffer), fp))
{
MUST(lines.back().append(line_buffer));
if (lines.back().back() != '\n')
continue;
lines.back().pop_back();
MUST(lines.emplace_back());
}
while (lines.back().empty())
lines.pop_back();
i64 result = 0;
char op = 0;
i64 current = 0;
for (size_t i = 0; i < lines.front().size(); i++)
{
if (lines.back()[i] != ' ')
{
result += current;
op = lines.back()[i];
current = (op == '+') ? 0 : 1;
}
i64 value = 0;
bool all_space = true;
for (size_t j = 0; j < lines.size() - 1; j++)
{
if (isdigit(lines[j][i]))
value = (value * 10) + (lines[j][i] - '0');
all_space = all_space && lines[j][i] == ' ';
}
if (all_space)
continue;
current = (op == '+') ? current + value : current * value;
}
return result + current;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day6_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day7 ${SOURCES})
banan_include_headers(aoc2025_day7 ban)
banan_link_library(aoc2025_day7 libc)
install(TARGETS aoc2025_day7 OPTIONAL)

View File

@ -1,131 +0,0 @@
#include <BAN/String.h>
#include <BAN/Vector.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
static BAN::Vector<BAN::String> parse_lines(FILE* fp)
{
BAN::Vector<BAN::String> lines;
MUST(lines.emplace_back());
char line_buffer[128];
while (fgets(line_buffer, sizeof(line_buffer), fp))
{
MUST(lines.back().append(line_buffer));
if (lines.back().back() != '\n')
continue;
lines.back().pop_back();
MUST(lines.emplace_back());
}
while (lines.back().empty())
lines.pop_back();
return lines;
}
i64 part1(FILE* fp)
{
i32 result = 0;
auto lines = parse_lines(fp);
for (char& ch : lines.front())
if (ch == 'S')
ch = '|';
for (size_t y = 0; y < lines.size() - 1; y++)
{
for (size_t x = 0; x < lines[y].size(); x++)
{
if (lines[y][x] != '|')
continue;
switch (lines[y + 1][x])
{
case '.':
lines[y + 1][x] = '|';
break;
case '^':
lines[y + 1][x - 1] = '|';
lines[y + 1][x + 1] = '|';
result++;
break;
}
}
}
return result;
}
i64 part2(FILE* fp)
{
auto lines = parse_lines(fp);
const size_t h = lines.size();
const size_t w = lines.front().size();
BAN::Vector<i64> timelines;
MUST(timelines.resize(w * h));
const auto get_char_value = [](char ch) { return ch == '.' ? 0 : ch == 'S' ? 1 : -1; };
for (size_t y = 0; y < h; y++)
for (size_t x = 0; x < w; x++)
timelines[y * w + x] = get_char_value(lines[y][x]);
for (size_t y = 1; y < h; y++)
{
for (size_t x = 0; x < w; x++)
{
if (timelines[(y - 1) * w + x] < 0)
;
else if (timelines[y * w + x] >= 0)
timelines[y * w + x] += timelines[(y - 1) * w + x];
else
{
timelines[y * w + x - 1] += timelines[(y - 1) * w + x];
timelines[y * w + x + 1] += timelines[(y - 1) * w + x];
}
}
}
i64 result = 0;
for (size_t x = 0; x < w; x++)
if (auto value = timelines[(h - 1) * w + x]; value > 0)
result += value;
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day7_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day8 ${SOURCES})
banan_include_headers(aoc2025_day8 ban)
banan_link_library(aoc2025_day8 libc)
install(TARGETS aoc2025_day8 OPTIONAL)

View File

@ -1,179 +0,0 @@
#include <BAN/HashSet.h>
#include <BAN/Heap.h>
#include <BAN/Vector.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
struct Point
{
i64 x, y, z;
constexpr bool operator==(const Point& other) const
{
return x == other.x && y == other.y && z == other.z;
}
};
static BAN::Vector<Point> parse_points(FILE* fp)
{
BAN::Vector<Point> points;
i64 x, y, z;
while (fscanf(fp, "%" SCNi64 ",%" SCNi64 ",%" SCNi64, &x, &y, &z) == 3)
MUST(points.emplace_back(x, y, z));
return points;
}
struct PointPair
{
Point a, b;
constexpr i64 dist() const
{
return (a.x - b.x) * (a.x - b.x)
+ (a.y - b.y) * (a.y - b.y)
+ (a.z - b.z) * (a.z - b.z);
}
constexpr bool operator>(const PointPair& other) const
{
return dist() > other.dist();
}
};
static BAN::Vector<PointPair> build_point_pair_heap(const BAN::Vector<Point>& points)
{
BAN::Vector<PointPair> pairs;
MUST(pairs.reserve(points.size() * (points.size() + 1) / 2));
for (size_t i = 0; i < points.size(); i++)
for (size_t j = i + 1; j < points.size(); j++)
MUST(pairs.push_back({ points[i], points[j] }));
BAN::make_heap(pairs.begin(), pairs.end(), BAN::greater<PointPair> {});
return pairs;
}
using Circuit = BAN::Vector<Point>;
static BAN::Vector<Circuit> build_circuits(const BAN::Vector<Point>& points)
{
BAN::Vector<Circuit> circuits;
MUST(circuits.reserve(points.size()));
for (size_t i = 0; i < points.size(); i++)
MUST(circuits.emplace_back(1, points[i]));
return circuits;
}
static void combine_circuits_with_points(BAN::Vector<Circuit>& circuits, const Point& a, const Point& b)
{
size_t a_index = SIZE_MAX;
size_t b_index = SIZE_MAX;
for (size_t i = 0; i < circuits.size(); i++)
{
if (circuits[i].contains(a))
a_index = i;
if (circuits[i].contains(b))
b_index = i;
}
if (a_index == b_index)
return;
MUST(circuits[a_index].reserve(circuits[a_index].size() + circuits[b_index].size()));
for (auto point : circuits[b_index])
MUST(circuits[a_index].push_back(point));
circuits.remove(b_index);
}
i64 part1(FILE* fp)
{
auto points = parse_points(fp);
auto pairs = build_point_pair_heap(points);
auto circuits = build_circuits(points);
for (size_t i = 0; i < 1000; i++)
{
const auto [a, b] = pairs.front();
BAN::pop_heap(pairs.begin(), pairs.end() - i, BAN::greater<PointPair> {});
combine_circuits_with_points(circuits, a, b);
}
const auto size_comp =
[](const auto& a, const auto& b)
{
return a.size() < b.size();
};
BAN::make_heap(circuits.begin(), circuits.end(), size_comp);
i64 result = 1;
for (size_t i = 0; i < 3; i++)
{
result *= circuits.front().size();
BAN::pop_heap(circuits.begin(), circuits.end() - i, size_comp);
}
return result;
}
i64 part2(FILE* fp)
{
auto points = parse_points(fp);
auto pairs = build_point_pair_heap(points);
auto circuits = build_circuits(points);
for (size_t i = 0; i < pairs.size(); i++)
{
const auto [a, b] = pairs.front();
BAN::pop_heap(pairs.begin(), pairs.end() - i, BAN::greater<PointPair> {});
combine_circuits_with_points(circuits, a, b);
if (circuits.size() == 1)
return a.x * b.x;
}
ASSERT_NOT_REACHED();
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day8_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_day9 ${SOURCES})
banan_include_headers(aoc2025_day9 ban)
banan_link_library(aoc2025_day9 libc)
install(TARGETS aoc2025_day9 OPTIONAL)

View File

@ -1,188 +0,0 @@
#include <BAN/HashMap.h>
#include <BAN/Sort.h>
#include <BAN/Vector.h>
#include <inttypes.h>
#include <stdio.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
struct Point
{
i64 x, y;
};
static BAN::Vector<Point> parse_points(FILE* fp)
{
BAN::Vector<Point> points;
i64 x, y;
while (fscanf(fp, "%" SCNi64 ",%" SCNi64, &x, &y) == 2)
MUST(points.emplace_back(x, y));
return points;
}
i64 part1(FILE* fp)
{
auto points = parse_points(fp);
i64 result = 0;
for (size_t i = 0; i < points.size(); i++)
{
for (size_t j = i + 1; j < points.size(); j++)
{
const i64 w = BAN::Math::abs(points[i].x - points[j].x) + 1;
const i64 h = BAN::Math::abs(points[i].y - points[j].y) + 1;
result = BAN::Math::max(result, w * h);
}
}
return result;
}
static BAN::Vector<i64> compress_coordinates(BAN::Vector<Point>& points)
{
BAN::HashMap<i64, i64> coord_map;
MUST(coord_map.reserve(points.size() * 4));
for (size_t i = 0; i < points.size(); i++)
{
MUST(coord_map.emplace_or_assign(points[i].x));
MUST(coord_map.emplace_or_assign(points[i].y));
}
BAN::Vector<i64> coords;
MUST(coords.reserve(coord_map.size()));
for (auto [coord, _] : coord_map)
MUST(coords.push_back(coord));
BAN::sort::sort(coords.begin(), coords.end());
for (size_t i = 0; i < coords.size(); i++)
coord_map[coords[i]] = i;
for (auto& point : points)
{
point.x = coord_map[point.x];
point.y = coord_map[point.y];
}
return coords;
}
i64 part2(FILE* fp)
{
auto points = parse_points(fp);
auto index2coord = compress_coordinates(points);
const size_t grid_size = index2coord.size();
BAN::Vector<bool> grid;
MUST(grid.resize(grid_size * grid_size, false));
for (size_t i = 0; i < points.size(); i++)
{
const auto curr = points[i];
const auto next = points[(i + 1) % points.size()];
ASSERT((curr.x == next.x) != (curr.y == next.y));
const i64 minx = BAN::Math::min(curr.x, next.x);
const i64 maxx = BAN::Math::max(curr.x, next.x);
const i64 miny = BAN::Math::min(curr.y, next.y);
const i64 maxy = BAN::Math::max(curr.y, next.y);
const i64 dx = (minx != maxx);
const i64 dy = (miny != maxy);
for (i64 x = minx, y = miny; x <= maxx && y <= maxy; x += dx, y += dy)
grid[y * grid_size + x] = true;
}
for (size_t y = 0; y < grid_size; y++)
{
bool is_inside = false;
for (size_t x = 0; x < grid_size; x++)
{
if (!grid[y * grid_size + x])
grid[y * grid_size + x] = is_inside;
else if (x + 1 >= grid_size || !grid[y * grid_size + x + 1])
is_inside = !is_inside;
else
{
const bool from_below1 = (y + 1 < grid_size) && grid[(y + 1) * grid_size + x];
while (x + 1 < grid_size && grid[y * grid_size + x + 1])
x++;
const bool from_below2 = (y + 1 < grid_size) && grid[(y + 1) * grid_size + x];
if (from_below1 != from_below2)
is_inside = !is_inside;
}
}
}
const auto is_usable_area =
[&grid, grid_size](const Point& a, const Point& b) -> bool
{
const i64 minx = BAN::Math::min(a.x, b.x);
const i64 maxx = BAN::Math::max(a.x, b.x);
const i64 miny = BAN::Math::min(a.y, b.y);
const i64 maxy = BAN::Math::max(a.y, b.y);
for (i64 x = minx; x <= maxx; x++)
if (!grid[miny * grid_size + x] || !grid[maxy * grid_size + x])
return false;
for (i64 y = miny; y <= maxy; y++)
if (!grid[y * grid_size + minx] || !grid[y * grid_size + maxy])
return false;
return true;
};
i64 result = 0;
for (size_t i = 0; i < points.size(); i++)
{
for (size_t j = i + 1; j < points.size(); j++)
{
const auto& a = points[i];
const auto& b = points[j];
if (!is_usable_area(a, b))
continue;
const i64 w = BAN::Math::abs(index2coord[a.x] - index2coord[b.x]) + 1;
const i64 h = BAN::Math::abs(index2coord[a.y] - index2coord[b.y]) + 1;
result = BAN::Math::max(result, w * h);
}
}
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2025/day9_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -1,9 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(aoc2025_full ${SOURCES})
banan_include_headers(aoc2025_full ban)
banan_link_library(aoc2025_full libc)
install(TARGETS aoc2025_full OPTIONAL)

View File

@ -1,22 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main()
{
for (int i = 1; i <= 25; i++)
{
char command[128];
sprintf(command, "/bin/aoc2025/aoc2025_day%d", i);
struct stat st;
if (stat(command, &st) == -1)
continue;
printf("day%d\n", i);
system(command);
}
return 0;
}

View File

@ -1,15 +0,0 @@
#!/bin/bash
if [[ -z $1 ]]; then
echo Please specify day number >& 2
exit 1
fi
if [[ ! -d day$1 ]]; then
cp -r day-template day$1
sed -i "s/day-template/day$1/g" day$1/*
fi
if [[ ! -f input/day$1_input.txt ]]; then
wget --no-cookies --header "Cookie: session=$AOC_SESSION" https://adventofcode.com/2025/day/$1/input -O input/day$1_input.txt
fi

View File

@ -1 +0,0 @@
day*_input.txt

View File

@ -32,11 +32,6 @@ struct init_funcs_t
extern "C" char** environ; extern "C" char** environ;
#define DUMP_BACKTRACE 1 #define DUMP_BACKTRACE 1
#define DEMANGLE_BACKTRACE 0
#if DEMANGLE_BACKTRACE
#include <cxxabi.h>
#endif
static void __dump_backtrace(int, siginfo_t*, void*); static void __dump_backtrace(int, siginfo_t*, void*);
@ -141,20 +136,8 @@ static void __dump_symbol(int fd, const void* address)
return; return;
} }
#if DEMANGLE_BACKTRACE
int status;
char* demangled = abi::__cxa_demangle(dli.dli_sname, nullptr, nullptr, &status);
const char* symbol_name = status ? dli.dli_sname : demangled;
#else
const char* symbol_name = dli.dli_sname;
#endif
const uintptr_t uptr_saddr = reinterpret_cast<uintptr_t>(dli.dli_saddr); const uintptr_t uptr_saddr = reinterpret_cast<uintptr_t>(dli.dli_saddr);
dprintf(fd, " 0x%08" PRIxPTR " (%s) %s+0x%" PRIxPTR "\n", uptr_addr - uptr_fbase, dli.dli_fname, symbol_name, uptr_addr - uptr_saddr); dprintf(fd, " 0x%08" PRIxPTR " (%s) %s+0x%" PRIxPTR "\n", uptr_addr - uptr_fbase, dli.dli_fname, symbol_name, uptr_addr - uptr_saddr);
#if DEMANGLE_BACKTRACE
free(demangled);
#endif
} }
static void __dump_backtrace(int sig, siginfo_t* info, void* context) static void __dump_backtrace(int sig, siginfo_t* info, void* context)
@ -163,7 +146,6 @@ static void __dump_backtrace(int sig, siginfo_t* info, void* context)
[](int signal) -> const char* [](int signal) -> const char*
{ {
switch (signal) { switch (signal) {
case SIGABRT: return "SIGABRT";
case SIGBUS: return "SIGBUS"; case SIGBUS: return "SIGBUS";
case SIGFPE: return "SIGFPE"; case SIGFPE: return "SIGFPE";
case SIGILL: return "SIGILL"; case SIGILL: return "SIGILL";
@ -1016,6 +998,7 @@ long sysconf(int name)
POSIX_CASE(MQ_OPEN_MAX) POSIX_CASE(MQ_OPEN_MAX)
POSIX_CASE(MQ_PRIO_MAX) POSIX_CASE(MQ_PRIO_MAX)
POSIX_CASE(NGROUPS_MAX) POSIX_CASE(NGROUPS_MAX)
POSIX_CASE(OPEN_MAX)
POSIX_CASE(PRIORITIZED_IO) POSIX_CASE(PRIORITIZED_IO)
POSIX_CASE(PRIORITY_SCHEDULING) POSIX_CASE(PRIORITY_SCHEDULING)
POSIX_CASE(RAW_SOCKETS) POSIX_CASE(RAW_SOCKETS)
@ -1103,8 +1086,6 @@ long sysconf(int name)
XOPEN_CASE(VERSION) XOPEN_CASE(VERSION)
#undef XOPEN_CASE #undef XOPEN_CASE
case _SC_OPEN_MAX: return OPEN_MAX;
case _SC_PAGE_SIZE: case _SC_PAGE_SIZE:
case _SC_PAGESIZE: return getpagesize(); case _SC_PAGESIZE: return getpagesize();