Files
aoccpp2025/day1.cpp
2025-12-03 15:32:55 -05:00

133 lines
3.2 KiB
C++

//
// Created by Grant Horner on 12/1/25.
//
#include <cassert>
#include <charconv>
#include <ranges>
#include <fstream>
#include <sstream>
#include "doctest.h"
enum Direction {
L = 'L',
R = 'R',
};
struct Instruction {
Direction direction;
uint32_t amount;
};
Instruction parse_instruction(std::string_view line) {
assert(!line.empty());
const auto direction = static_cast<Direction>(line[0]);
uint32_t amount;
std::from_chars(&line[1], line.data() + line.size(), amount);
return Instruction{direction, amount};
}
template<>
struct std::formatter<Instruction> : std::formatter<string_view> {
static auto format(const Instruction &i, std::format_context &ctx) {
return std::format_to(ctx.out(), "Instruction[direction: {}, amount: {}]", static_cast<char>(i.direction),
i.amount);
}
};
const std::string sample =
"L68\n"
"L30\n"
"R48\n"
"L5\n"
"R60\n"
"L55\n"
"L1\n"
"L99\n"
"R14\n"
"L82\n";
uint64_t spin2(int &value, Instruction i) {
uint64_t spins = i.amount / 100;
int amount_to_spin = i.amount % 100;
if (i.direction == L) {
amount_to_spin *= -1;
}
value += amount_to_spin;
if (value == 0) {
spins++;
} else if (value < 0) {
spins++;
value = 100 + value;
} else if (100 < value) {
spins++;
value = value - 100;
}
return spins;
}
bool spin(int &value, Instruction i) {
value += static_cast<int>(i.amount) * (i.direction == L ? -1 : 1);
value %= 100;
return value == 0;
}
uint32_t solve_first(const std::string &input) {
int value = 50;
uint32_t spins = 0;
for (const auto instr:
std::views::split(input, '\n')
| std::views::transform([](auto s) { return std::string_view(s); })
| std::views::filter([](const std::string_view s) { return !s.empty(); })
| std::views::transform(parse_instruction)
) {
if (spin(value, instr)) {
spins++;
}
// std::println("Total spins: {}, instruction: {}, value: {}", spins, instr, value);
}
return spins;
}
TEST_SUITE_BEGIN("Day 1");
TEST_CASE("puzzle 1") {
CHECK(solve_first(sample) == 3);
std::ifstream input("day1input.txt");
CHECK(input.is_open());
std::stringstream buffer;
buffer << input.rdbuf();
CHECK(solve_first(buffer.str()) == 1158);
}
uint32_t solve_second(const std::string &input) {
int value = 50;
uint32_t spins = 0;
for (const auto instr:
std::views::split(input, '\n')
| std::views::transform([](auto s) { return std::string_view(s); })
| std::views::filter([](const std::string_view s) { return !s.empty(); })
| std::views::transform(parse_instruction)
) {
spins += spin2(value, instr);
// std::println("Total spins: {}, instruction: {}, value: {}", spins, instr, value);
}
return spins;
}
TEST_CASE("puzzle 2") {
CHECK(solve_second(sample) == 6);
std::ifstream input("day1input.txt");
CHECK(input.is_open());
std::stringstream buffer;
buffer << input.rdbuf();
CHECK(solve_second(buffer.str()) == 6860);
}
TEST_SUITE_END();