finish day 1
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
cmake-*
|
||||||
|
day1.dSYM
|
||||||
|
.idea
|
||||||
13
CMakeLists.txt
Normal file
13
CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
cmake_minimum_required(VERSION 4.0)
|
||||||
|
project(cpp)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
||||||
|
|
||||||
|
add_library(cpp STATIC
|
||||||
|
doctest.h
|
||||||
|
run_tests.cpp
|
||||||
|
day1.cpp)
|
||||||
|
|
||||||
|
add_executable(cpp_tests run_tests.cpp)
|
||||||
|
target_link_libraries(cpp_tests PRIVATE cpp)
|
||||||
129
day1.cpp
Normal file
129
day1.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
//
|
||||||
|
// 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_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);
|
||||||
|
}
|
||||||
4659
day1input.txt
Normal file
4659
day1input.txt
Normal file
File diff suppressed because it is too large
Load Diff
7
run_tests.cpp
Normal file
7
run_tests.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
//
|
||||||
|
// Created by Grant Horner on 12/1/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||||
|
#include "doctest.h"
|
||||||
|
#include "day1.cpp"
|
||||||
Reference in New Issue
Block a user