Compare commits

28 Commits

Author SHA1 Message Date
60e78353d7 2025 day 4 p1 2025-12-14 12:43:52 +01:00
b90bcb0c9d 2025 day 3 p1 2025-12-14 08:00:30 +01:00
7fb1f4f778 2025 day 2 p1 2025-12-11 13:57:49 +01:00
abecf6cfb7 Add function in cmake to create targets 2025-12-09 16:12:19 +01:00
432a5b1f7c force solution
Change-Id: I1421c6279597b9cb040dfcafb6984a3730503d10
2025-12-09 10:36:14 +01:00
14ec3ca2da 2025D01P1: done 2025-12-09 04:20:27 +01:00
d106e7541d Prepare day01 2025
Change-Id: Id3c46f5f552db5a0ba200dedc1ea4e4434932982
2025-12-08 11:43:38 +01:00
49d82b8f90 prep for 2025 2025-12-03 16:26:25 +01:00
c238e9b4fb aoc: 2024 bk 2025-12-02 09:13:23 +01:00
da8a4cc5de aoc24: day17 cpu 2024-12-18 21:53:42 +01:00
5810fe22e9 aoc24: day17 started 2024-12-17 18:01:49 +01:00
5c7da45fe1 aoc24: day16 create graph 2024-12-16 21:17:17 +01:00
9c840a7c8f aoc24: add day16 2024-12-16 16:43:34 +01:00
1108b8c65b aoc24: day07a complete 2024-12-16 04:03:02 +01:00
7ae660566e aoc24: add day11 2024-12-11 08:08:46 +01:00
521b3dc806 aoc24: add day10 2024-12-10 17:45:40 +01:00
c175b4ebc4 aoc24: day05 filter invalid 2024-12-09 15:16:11 +01:00
ec9028c5f5 aoc24: add day07-08 2024-12-09 02:15:47 +01:00
aaff50eae9 aoc24: day05a add back 2024-12-09 01:30:49 +01:00
57d9bdf0f3 aoc24: day06a complete 2024-12-09 01:27:55 +01:00
a35123500e aoc24: Add README.md 2024-12-09 00:12:55 +01:00
5a02b90f85 aoc24: day04b complete 2024-12-08 23:58:15 +01:00
a1d5d359f2 aoc24: day02b complete 2024-12-08 22:35:49 +01:00
5c692fe727 aoc24: day05a complete 2024-12-06 12:13:39 +01:00
8df8cbb0e4 aoc24: day05a split sections
rules and updates
2024-12-05 16:38:03 +01:00
1c6bbc6cef aoc24: day03b complete 2024-12-03 21:20:47 +01:00
9e68114169 aoc24: day03a complete 2024-12-03 20:56:46 +01:00
c685dcddfb aoc24: day03 tokenizer 2024-12-03 16:43:38 +01:00
21 changed files with 880 additions and 2307 deletions

35
2025/CMakeLists.txt Normal file
View File

@@ -0,0 +1,35 @@
find_package(fmt REQUIRED)
find_package(utf8cpp REQUIRED)
find_package(ctre REQUIRED)
function(add_day_executables)
foreach(src IN LISTS ARGN)
get_filename_component(name "${src}" NAME_WE)
add_executable(${name} "${src}")
target_include_directories(${name} PUBLIC "${PROJECT_SOURCE_DIR}")
target_compile_features(${name} PRIVATE cxx_std_23)
target_link_libraries(${name}
PRIVATE
${PLATFORM_LINK_LIBRARIES}
fmt
utf8cpp
ctre
)
target_compile_definitions(${name} PRIVATE ${PLATFORM_DEFINITIONS})
target_compile_options(${name} PRIVATE ${BASE_OPTIONS})
source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES "${src}")
endforeach()
endfunction()
add_day_executables(
"day01.cpp"
"day02.cpp"
"day03.cpp"
"day04.cpp"
)

127
2025/day01.cpp Normal file
View File

@@ -0,0 +1,127 @@
#include <span>
#include <algorithm>
#include <ranges>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "fmt/std.h"
#include "aoc/types.hpp"
#include "aoc/utils.hpp"
using namespace std::string_view_literals;
using namespace aoc::types;
// simple pipe for std::string by value
template <typename F>
auto operator|(std::string s, F&& f) -> decltype(auto) {
return std::forward<F>(f)(std::move(s));
}
auto ltrim(std::string s) -> std::string {
s.erase(
std::begin(s),
std::find_if(s.begin(), s.end(), [](char ch) {
return !std::isspace(static_cast<char>(ch));
}));
return s;
}
auto rtrim(std::string s) -> std::string {
s.erase(
std::find_if(s.rbegin(), s.rend(), [](char ch) {
return !std::isspace(static_cast<char>(ch));
}).base(),
s.end());
return s;
}
auto trim(std::string s) -> std::string {
return ltrim(rtrim(std::move(s)));
}
// starts at 50
[[maybe_unused]]constexpr auto raw_str = R"(
L68
L30
R48
L5
R60
L55
L1
L99
R14
L82
)";
auto map_char_to_rotdir(char c) -> i32 {
switch (c) {
case 'L': return -1;
case 'R':
default: return 1;
}
}
static auto entry([[maybe_unused]]std::span<char const*> const& args) -> void {
// std::string str{raw_str};
auto str = aoc::read_text("./input.txt").value_or("");
str = str | trim;
auto rot_vec = str | std::views::split("\n"sv) | std::views::transform([](auto const& str) {
return i32(std::stoi(std::string{++std::begin(str), std::end(str)})) * map_char_to_rotdir(*std::begin(str));
}) | std::ranges::to<std::vector>();
i32 start = 50;
i32 zero_cross = 0;
// auto sum = std::ranges::fold_left(rot_vec, 0, [&](auto a, auto t) {
// auto const p = start;
// start = (100 + p - t) % 100;
//
// zero_cross += (std::abs((p - t + 1) % 100) + std::abs(t)) / 100;
//
// fmt::print("pos: {}, next: {}, t: {}\n", p, start, t);
//
// if (start == 0) {
// a += 1;
// }
//
// return a;
// });
auto sum = std::ranges::fold_left(rot_vec, 0, [&](auto a, auto t) {
auto const dir = t < 0 ? -1 : 1;
auto const steps = std::abs(t);
for (i32 i = 0; i < steps; ++i) {
auto next = start + dir;
if (next < 0) next = 99;
next = next % 100;
if (next % 100 == 0)
++zero_cross;
start = next;
}
if (start % 100 == 0) {
++a;
if (zero_cross > 0)
zero_cross -= 1;
}
return a;
});
fmt::print("res: {}, {} sum = {}\n", sum, zero_cross, sum + zero_cross);
}
auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int {
try {
entry({argv, std::next(argv, argc)});
} catch (std::exception const& e) {
fmt::print(stderr, "{}\n", e.what());
return 1;
}
return 0;
}

90
2025/day02.cpp Normal file
View File

@@ -0,0 +1,90 @@
#include <span>
#include <algorithm>
#include <ranges>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "fmt/std.h"
#include "aoc/types.hpp"
#include "aoc/utils.hpp"
using namespace std::string_view_literals;
using namespace aoc::types;
// starts at 50
[[maybe_unused]]constexpr auto raw_str = R"(
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,
1698522-1698528,446443-446449,38593856-38593862,565653-565659,
824824821-824824827,2121212118-2121212124
)";
static auto entry([[maybe_unused]]std::span<char const*> const& args) -> void {
// std::string str{raw_str};
auto str = aoc::read_text("./input.txt").value_or("");
str = aoc::trim(str);
auto ids_str = str | std::views::split(","sv) | std::views::transform([](auto const& str) {
std::vector<u64> range{};
range.resize(2);
// std::ranges::transform(
// aoc::trim(std::string{std::begin(str), std::end(str)}) | std::views::split("-"sv),
// std::begin(range),
// [](auto const& value) {
// return aoc::trim(std::string{std::begin(value), std::end(value)});
// });
std::ranges::transform(
aoc::trim(std::string{std::begin(str), std::end(str)}) | std::views::split("-"sv),
std::begin(range),
[](auto const& value) {
return u64(std::stoul(aoc::trim(std::string{std::begin(value), std::end(value)})));
});
return range;
}) | std::ranges::to<std::vector>();
auto is_valid_id = [](u64 id) {
auto const str = fmt::format("{}", id);
if (str.size() % 2 != 0) return true;
bool is_invalid = true;
for (usize i = 0; i < str.size() / 2; ++i) {
if (str[i] != str[str.size() / 2 + i]) {
is_invalid = false;
continue;
}
}
return !is_invalid;
};
u64 sum = 0;
for (auto const& id : ids_str) {
u64 const start = id[0];
u64 const end = id[1];
fmt::print("{} -> {}: ", id[0], id[1]);
for (u64 i = start; i <= end; ++i) {
if (!is_valid_id(i)) {
fmt::print("{}, ", i);
sum += i;
}
}
fmt::print("\n");
}
fmt::print("res: {}\n", sum);
}
auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int {
try {
entry({argv, std::next(argv, argc)});
} catch (std::exception const& e) {
fmt::print(stderr, "{}\n", e.what());
return 1;
}
return 0;
}

73
2025/day03.cpp Normal file
View File

@@ -0,0 +1,73 @@
#include <span>
#include <algorithm>
#include <ranges>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "fmt/std.h"
#include "aoc/types.hpp"
#include "aoc/utils.hpp"
using namespace std::string_view_literals;
using namespace aoc::types;
// starts at 50
[[maybe_unused]]constexpr auto raw_str = R"(
987654321111111
811111111111119
234234234234278
818181911112111
)";
static auto entry([[maybe_unused]]std::span<char const*> const& args) -> void {
// std::string str{raw_str};
auto str = aoc::read_text("./input.txt").value_or("");
str = aoc::trim(str);
fmt::print("INPUT\n");
fmt::print("⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼\n");
fmt::print("{}\n", str);
fmt::print("{}\n", std::string(80, '-'));
auto jolts_str = str | std::views::split("\n"sv) | std::views::transform([](auto const& str) {
return aoc::trim(std::string{std::begin(str), std::end(str)});
}) | std::ranges::to<std::vector>();
std::vector<u64> jolts{};
jolts.reserve(jolts_str.size());
for (auto const& jolt : jolts_str) {
u64 largest = 0;
for (usize i = 0; i < jolt.size(); ++i) {
for (usize j = i + 1; j < jolt.size(); ++j) {
auto const value = std::stoull(fmt::format("{}{}", jolt[i], jolt[j]));
if (value > largest) largest = value;
}
}
jolts.push_back(largest);
}
for (auto const& jolt : jolts) {
fmt::print("{}\n", jolt);
}
auto sum = std::ranges::fold_left(jolts, u64(0), [&](auto a, auto v) {
return a + v;
});
fmt::print("res: {}\n", sum);
}
auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int {
try {
entry({argv, std::next(argv, argc)});
} catch (std::exception const& e) {
fmt::print(stderr, "{}\n", e.what());
return 1;
}
return 0;
}

83
2025/day04.cpp Normal file
View File

@@ -0,0 +1,83 @@
#include <span>
#include <algorithm>
#include <ranges>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "fmt/std.h"
#include "aoc/types.hpp"
#include "aoc/utils.hpp"
using namespace std::string_view_literals;
using namespace aoc::types;
// starts at 50
[[maybe_unused]]constexpr auto raw_str = R"(
..@@.@@@@.
@@@.@.@.@@
@@@@@.@.@@
@.@@@@..@.
@@.@@@@.@@
.@@@@@@@.@
.@.@.@.@@@
@.@@@.@@@@
.@@@@@@@@.
@.@.@@@.@.
)";
static auto entry([[maybe_unused]]std::span<char const*> const& args) -> void {
// std::string str{raw_str};
auto str = aoc::read_text("./input.txt").value_or("");
str = aoc::trim(str);
fmt::print("INPUT\n");
fmt::print("⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼⎽⎼⎻⎺⎻⎼\n");
fmt::print("{}\n", str);
fmt::print("{}\n", std::string(80, '-'));
auto grid = str | std::views::split("\n"sv) | std::views::transform([](auto const& str) {
return aoc::trim(std::string{std::begin(str), std::end(str)}) |
std::views::transform([](auto const& ch) { return ch; }) |
std::ranges::to<std::vector>();
}) | std::ranges::to<std::vector>();
u64 access = 0;
for (isize i = 0; i < isize(grid.size()); ++i) {
for (isize j = 0; j < isize(grid[i].size()); ++j) {
auto const v = grid[i][j];
if (v == '.') continue;
u64 sum = 0;
if (i - 1 >= 0 && j - 1 >= 0 && grid[i - 1][j - 1] == '@') ++sum;
if (i - 1 >= 0 && grid[i - 1][j] == '@') ++sum;
if (i - 1 >= 0 && j + 1 < isize(grid[i].size()) && grid[i - 1][j + 1] == '@') ++sum;
if (j - 1 >= 0 && grid[i][j - 1] == '@') ++sum;
if (j + 1 < isize(grid[i].size()) && grid[i][j + 1] == '@') ++sum;
if (i + 1 < isize(grid.size()) && j - 1 >= 0 && grid[i + 1][j - 1] == '@') ++sum;
if (i + 1 < isize(grid.size()) && grid[i + 1][j] == '@') ++sum;
if (i + 1 < isize(grid.size()) && j + 1 < isize(grid[i].size()) && grid[i + 1][j + 1] == '@') ++sum;
if (sum < 4) {
// fmt::print("{},{}: {}\n", i, j, sum);
++access;
}
}
}
fmt::print("res: {}\n", access);
}
auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int {
try {
entry({argv, std::next(argv, argc)});
} catch (std::exception const& e) {
fmt::print(stderr, "{}\n", e.what());
return 1;
}
return 0;
}

View File

@@ -3,126 +3,17 @@ project(aoc VERSION 0.0.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Group CMake targets inside a folder set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Group CMake targets inside a folder
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Generate compile_commands.json for language servers set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Generate compile_commands.json for language servers
include(FetchContent) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
FetchContent_Declare( include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/platform.cmake")
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.1.0
)
list(APPEND FETCH_CONTENTS fmt)
FetchContent_Declare(
utf8cpp
GIT_REPOSITORY https://github.com/nemtrif/utfcpp.git
GIT_TAG v4.0.5
)
list(APPEND FETCH_CONTENTS utf8cpp)
FetchContent_Declare(
stb
GIT_REPOSITORY https://github.com/mononerv/stb.git
GIT_TAG 698c6fb9889c71494b49c9187d249af5fc87b211
)
list(APPEND FETCH_CONTENTS stb)
# Turn off BUILD_TESTING globally to prevent CTest from being included in CTRE
set(BUILD_TESTING OFF CACHE BOOL "Disable testing globally" FORCE)
# Set the CTRE_BUILD_TESTS option before including the CTRE library
set(CTRE_BUILD_TESTS OFF CACHE BOOL "Build ctre Tests" FORCE)
FetchContent_Declare(
ctre
GIT_REPOSITORY https://github.com/hanickadot/compile-time-regular-expressions.git
GIT_TAG v3.9.0
)
list(APPEND FETCH_CONTENTS ctre)
FetchContent_MakeAvailable(${FETCH_CONTENTS}) add_subdirectory("2025")
find_package(Threads REQUIRED)
# Group dependencies in Visual Studio and Xcode
if (CMAKE_GENERATOR MATCHES "Visual Studio" OR CMAKE_GENERATOR MATCHES "Xcode")
set_target_properties(fmt PROPERTIES FOLDER deps)
set_target_properties(stb PROPERTIES FOLDER deps)
endif()
set(BASE_DEFINITIONS "ASIO_STANDALONE")
if (APPLE)
message("Platform Apple")
list(APPEND BASE_DEFINITIONS
"AOC_PLATFORM=Apple"
)
set(IS_UNIX true)
elseif (UNIX AND NOT APPLE AND NOT EMSCRIPTEN) # Linux, BSD, Solaris, Minix
message("Platform Unix")
list(APPEND BASE_DEFINITIONS
"AOC_PLATFORM=Linux"
)
set(IS_UNIX true)
elseif (WIN32)
message("Platform Windows")
list(APPEND BASE_DEFINITIONS
"AOC_PLATFORM=Windows"
)
else()
message(FATAL_ERROR "Unkown platform!")
endif()
# Compiler specific options
if (NOT MSVC)
set(BASE_OPTIONS
"-Wall"
"-Wextra"
"-Wconversion"
"-Wpedantic"
"-Wshadow"
"-Werror"
# fmt warnings
"-Wno-unknown-attributes"
)
else()
set(BASE_OPTIONS
"/W4"
"/WX"
"/utf-8"
"/Zc:__cplusplus"
#"/fsanitize=address" # Doesn't work without Visual Studio
)
endif()
set(HEADERS
aoc/aoc.hpp
)
set(SOURCES "")
add_library(aoclib OBJECT ${HEADERS} ${SOURCES})
target_include_directories(aoclib
PUBLIC
${PROJECT_SOURCE_DIR}
PRIVATE
${PROJECT_SOURCE_DIR}/aoc
)
target_compile_features(aoclib PRIVATE cxx_std_23)
target_compile_options(aoclib PRIVATE ${BASE_OPTIONS})
target_compile_definitions(aoclib
PRIVATE
${BASE_DEFINITIONS}
)
target_link_libraries(aoclib
PUBLIC
fmt
utf8cpp
ctre
stb::stb
Threads::Threads
)
source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES})
set(HEADERS "")
set(SOURCES aoc.cpp)
add_executable(aoc ${HEADERS} ${SOURCES})
target_include_directories(aoc PRIVATE ${PROJECT_SOURCE_DIR})
target_compile_features(aoc PRIVATE cxx_std_23)
target_compile_options(aoc PRIVATE ${BASE_OPTIONS})
target_compile_definitions(aoc PRIVATE ${BASE_DEFINITIONS})
target_link_libraries(aoc
PRIVATE
aoclib
)
source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES})
# set(HEADERS "")
# set(SOURCES "aoc.cpp")
# add_executable(aoc ${HEADERS} ${SOURCES})
# target_include_directories(aoc PUBLIC ${PROJECT_SOURCE_DIR})
# target_compile_features(aoc PRIVATE cxx_std_23)
# target_link_libraries(aoc PRIVATE ${PLATFORM_LINK_LIBRARIES})
# target_compile_definitions(aoc PRIVATE ${PLATFORM_DEFINITIONS})
# target_compile_options(aoc PRIVATE ${BASE_OPTIONS})
# source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${HEADERS} ${SOURCES})

View File

@@ -14,12 +14,6 @@ This project has support for different languages.
There are different ways to setup this project, using `ninja` or Visual Studio. There are different ways to setup this project, using `ninja` or Visual Studio.
To use `miniaudio` to play audio on host machine use the flag `-DUSE_MINIAUDIO=ON`.
```sh
cmake -S . -Bbuild -GNinja -DCMAKE_BUILD_TYPE=Debug
```
Use `ninja` to build. Use `ninja` to build.

142
aoc.cpp
View File

@@ -1,142 +0,0 @@
#include <fstream>
#include <vector>
#include <algorithm>
#include <ranges>
#include <numeric>
#include <cmath>
#include <utility>
#include "fmt/format.h"
using levels_t = std::vector<std::int32_t>;
using reports_t = std::vector<levels_t>;
auto main([[maybe_unused]]int argc, [[maybe_unused]]char const* argv[]) -> int {
// constexpr auto filename = "./dat/24/ex/02.txt";
constexpr auto filename = "./tmp.txt";
std::ifstream strm{filename, std::ios::in | std::ios::binary};
if (!strm.is_open()) {
fmt::print("Error opening file: {}\n", filename);
return 1;
}
reports_t reports{};
levels_t tmp{};
std::string str{};
while (strm) {
auto const c = char(strm.peek());
if (std::isdigit(c)) {
str += char(strm.get());
continue;
}
if (c == ' ' && !str.empty()) {
tmp.emplace_back(std::stoi(str));
str.clear();
}
if (c == '\n' && !str.empty()) {
tmp.emplace_back(std::stoi(str));
reports.emplace_back(std::move(tmp));
str.clear();
}
strm.get();
}
auto diff = reports | std::views::transform([](auto const& levels) {
return levels | std::views::adjacent_transform<2>([](auto const& a, auto const& b) {
return b - a;
});
});
// condition: all increasing or all decreasing.
auto incdec = diff | std::views::filter([](auto const& levels) {
auto const n = std::ranges::all_of(levels, [](auto v) { return v < 0; });
auto const p = std::ranges::all_of(levels, [](auto v) { return v > 0; });
return n || p;
});
// condition: Any two adjacent levels differ by at least one and at most three.
auto adjdiff = incdec | std::views::filter([](auto const& levels){
return std::ranges::all_of(levels, [](auto v) {
return std::abs(v) <= 3;
});
});
auto const safe_reports = std::ranges::distance(adjdiff);
fmt::print("Part A: {}\n", safe_reports);
auto lefts = std::views::zip(diff, reports) | std::views::filter([](auto const& pair) {
auto const& [d, l] = pair;
auto const n = std::ranges::all_of(d, [](auto v) { return v < 0; });
auto const p = std::ranges::all_of(d, [](auto v) { return v > 0; });
return !(n || p);
}) | std::views::transform([](auto const& pair) {
auto const& [d, l] = pair;
return l;
});
auto masks = diff | std::views::filter([](auto const& vec) {
auto const n = std::ranges::all_of(vec, [](auto v) { return v < 0; });
auto const p = std::ranges::all_of(vec, [](auto v) { return v > 0; });
return !(n || p);
}) | std::views::transform([](auto const& vec) {
auto const p = std::count_if(std::begin(vec), std::end(vec), [](auto const& v) { return v >= 0; });
auto const n = std::count_if(std::begin(vec), std::end(vec), [](auto const& v) { return v < 0; });
auto mask = vec | std::views::transform([&](auto const& v) {
if (p > n) return v >= 0 ? 1 : 0;
else return v < 0 ? 1 : 0;
}) | std::ranges::to<std::vector>();
mask.push_back(1);
return mask;
});
auto const remain_reports = std::views::zip(masks, lefts)
| std::views::filter([](auto const& pair) {
auto const& [mask, level] = pair;
auto const n = std::count_if(std::begin(mask), std::end(mask), [](auto const& v) { return v == 0; });
return n == 1;
})
| std::views::transform([](auto const& pair){
auto const& [mask, level] = pair;
return std::views::zip(mask, level) | std::views::filter([](auto const& pair) {
auto const& [m, v] = pair;
return m == 1;
}) | std::views::transform([](auto const& pair) {
auto const& [m, v] = pair;
return v;
}) | std::ranges::to<std::vector>();
})
| std::ranges::to<std::vector>();
auto rem_diff = remain_reports | std::views::transform([](auto const& vec) {
return vec | std::views::adjacent_transform<2>([](auto const& a, auto const& b) { return b - a; });
});
auto safe_rems_vec = rem_diff | std::views::transform([](auto const& vec) {
return vec | std::views::filter([](auto const& a) {
return std::abs(a) <= 3;
}) | std::ranges::to<std::vector>();
}) | std::ranges::to<std::vector>();
auto safe_rems = safe_rems_vec | std::views::filter([](auto const& vec) {
return vec.size() > 0;
}) | std::views::filter([](auto const& vec) {
auto const n = std::ranges::all_of(vec, [](auto v) { return v < 0; });
auto const p = std::ranges::all_of(vec, [](auto v) { return v > 0; });
return n || p;
});
auto const safe_reports_rem = std::ranges::distance(safe_rems);
// for (auto rep : safe_rems) {
// for (auto v : rep) {
// fmt::print("{} ", v);
// }
// fmt::print("\n");
// }
fmt::print("Part B: {}\n", safe_reports + safe_reports_rem);
return 0;
}

View File

View File

@@ -1,7 +0,0 @@
#ifndef AOC_AOC_HPP
#define AOC_AOC_HPP
namespace aoc {
}
#endif // !AOC_AOC_HPP

41
aoc/types.hpp Normal file
View File

@@ -0,0 +1,41 @@
#ifndef AOC_TYPES_HPP
#define AOC_TYPES_HPP
#include <type_traits>
#include <cstddef>
#include <limits>
#include <numbers>
#include <memory>
#include <system_error>
#include <expected>
#include <fstream>
#include <ranges>
#include <vector>
namespace aoc {
namespace types {
using f32 = float;
using f64 = double;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using usize = std::size_t;
using isize = std::ptrdiff_t;
using i8 = std::int8_t;
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using c8 = char;
using c16 = char16_t;
using c32 = char32_t;
}
using namespace aoc::types;
}
#endif // !AOC_TYPES_HPP

107
aoc/utils.hpp Normal file
View File

@@ -0,0 +1,107 @@
#ifndef AOC_UTILS_HPP
#define AOC_UTILS_HPP
#include <type_traits>
#include <cstddef>
#include <limits>
#include <numbers>
#include <memory>
#include <system_error>
#include <expected>
#include <fstream>
#include <ranges>
#include <vector>
#include <string>
#include "aoc/types.hpp"
namespace aoc {
template <typename T>
concept Integral = std::is_integral<T>::value;
// Aliases
namespace nums = std::numbers;
template <typename T>
using lim = std::numeric_limits<T>;
inline constexpr auto pi = std::numbers::pi;
template <typename T>
inline constexpr auto pi_v = std::numbers::pi_v<T>;
struct error {
std::string msg;
std::error_code err;
};
inline auto make_error(std::string const& str, std::errc ec) -> std::unexpected<error> {
return std::unexpected(error{str, std::make_error_code(ec)});
}
inline auto read_text(std::string const& path) -> std::expected<std::string, aoc::error> {
std::fstream strm(path, std::ios::in | std::ios::binary);
if (!strm.is_open())
return aoc::make_error(path, std::errc::no_such_file_or_directory);
return std::string{
std::istreambuf_iterator<c8>(strm),
std::istreambuf_iterator<c8>()
};
}
// ranges and view aliases
template <typename T>
using vec = std::vector<T>;
inline constexpr auto split = std::views::split;
[[maybe_unused]]constexpr auto map_to_str = std::views::transform([](auto const& str) {
return std::string(std::begin(str), std::end(str));
});
[[maybe_unused]]constexpr auto map_to_sv = std::views::transform([](auto const& str) {
return std::string_view(std::begin(str), std::end(str));
});
[[maybe_unused]]constexpr auto filter_non_empty = std::views::filter([](auto const& str) {
return !str.empty();
});
template <class F>
struct pipe {
F f;
};
template <class F>
pipe(F) -> pipe<F>;
template <class F>
auto operator|(std::string s, pipe<F> p) -> decltype(auto) {
return p.f(std::move(s));
}
inline auto ltrim(std::string s) -> std::string {
s.erase(
std::begin(s),
std::find_if(s.begin(), s.end(), [](char ch) {
return !std::isspace(static_cast<char>(ch));
}));
return s;
}
inline auto rtrim(std::string s) -> std::string {
s.erase(
std::find_if(s.rbegin(), s.rend(), [](char ch) {
return !std::isspace(static_cast<char>(ch));
}).base(),
s.end());
return s;
}
inline auto trim(std::string s) -> std::string {
return ltrim(rtrim(std::move(s)));
}
}
#endif // !AOC_UTILS_HPP

74
cmake/Findctre.cmake Normal file
View File

@@ -0,0 +1,74 @@
if (DEFINED _FINDCTRE_INCLUDED)
unset(ctre_FOUND CACHE)
unset(ctre_DIR CACHE)
unset(ctre_INCLUDE_DIR CACHE)
unset(ctre_LIBRARIES CACHE)
unset(ctre_VERSION CACHE)
return()
endif()
set(_FINDCTRE_INCLUDED TRUE)
find_package(ctre QUIET)
if (NOT ctre_FOUND)
message(STATUS "ctre not found. Fetching via FetchContent...")
include(FetchContent)
find_program(GIT_EXECUTABLE git)
if (GIT_EXECUTABLE)
set(CTRE_FETCH_METHOD "GIT")
else()
set(CTRE_FETCH_METHOD "ZIP")
endif()
if (CTRE_FETCH_METHOD STREQUAL "GIT")
FetchContent_Declare(
ctre
GIT_REPOSITORY https://github.com/hanickadot/compile-time-regular-expressions.git
GIT_TAG v3.10.0
)
else()
FetchContent_Declare(
ctre
URL https://github.com/hanickadot/compile-time-regular-expressions/archive/refs/tags/v3.10.0.zip
)
endif()
# Turn off BUILD_TESTING globally to prevent CTest from being included in CTRE
set(BUILD_TESTING OFF CACHE BOOL "Disable testing globally" FORCE)
# Set the CTRE_BUILD_TESTS option before including the CTRE library
set(CTRE_BUILD_TESTS OFF CACHE BOOL "Build ctre Tests" FORCE)
FetchContent_MakeAvailable(ctre)
else()
message(STATUS "ctre found.")
# Ensure we have a usable target
if (NOT TARGET ctre::ctre)
if (TARGET ctre)
add_library(ctre::ctre ALIAS ctre)
else()
message(FATAL_ERROR "ctre was found, but no CMake target 'ctre' or 'ctre::ctre' exists.")
endif()
endif()
# Populate the standard variables
set(ctre_FOUND TRUE)
set(ctre_LIBRARIES ctre::ctre)
get_target_property(_ctre_inc ctre::ctre INTERFACE_INCLUDE_DIRECTORIES)
set(ctre_INCLUDE_DIR "${_ctre_inc}")
endif()
if (NOT TARGET ctre::ctre)
if (TARGET ctre)
add_library(ctre::ctre ALIAS ctre)
else()
message(FATAL_ERROR "Could not find or fetch ctre; no target ctre or ctre::ctre available")
endif()
endif()
set(ctre_FOUND TRUE)
set(ctre_LIBRARIES ctre::ctre)
set(ctre_VERSION "${ctre_VERSION}") # this comes from the ctre project
get_target_property(_ctre_inc ctre::ctre INTERFACE_INCLUDE_DIRECTORIES)
set(ctre_INCLUDE_DIR "${_ctre_inc}")

70
cmake/Findfmt.cmake Normal file
View File

@@ -0,0 +1,70 @@
if (DEFINED _FINDFMT_INCLUDED)
unset(fmt_FOUND CACHE)
unset(fmt_DIR CACHE)
unset(fmt_INCLUDE_DIR CACHE)
unset(fmt_LIBRARIES CACHE)
unset(fmt_VERSION CACHE)
return()
endif()
set(_FINDFMT_INCLUDED TRUE)
find_package(fmt QUIET)
if (NOT fmt_FOUND)
message(STATUS "fmt not found. Fetching via FetchContent...")
include(FetchContent)
find_program(GIT_EXECUTABLE git)
if (GIT_EXECUTABLE)
set(FMT_FETCH_METHOD "GIT")
else()
set(FMT_FETCH_METHOD "ZIP")
endif()
if (FMT_FETCH_METHOD STREQUAL "GIT")
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 12.0.0
)
else()
FetchContent_Declare(
fmt
URL https://github.com/fmtlib/fmt/releases/download/12.0.0/fmt-12.0.0.zip
)
endif()
FetchContent_MakeAvailable(fmt)
else()
message(STATUS "fmt found.")
# Ensure we have a usable target
if (NOT TARGET fmt::fmt)
if (TARGET fmt)
add_library(fmt::fmt ALIAS fmt)
else()
message(FATAL_ERROR "fmt was found, but no CMake target 'fmt' or 'fmt::fmt' exists.")
endif()
endif()
# Populate the standard variables
set(fmt_FOUND TRUE)
set(fmt_LIBRARIES fmt::fmt)
get_target_property(_fmt_inc fmt::fmt INTERFACE_INCLUDE_DIRECTORIES)
set(fmt_INCLUDE_DIR "${_fmt_inc}")
endif()
if (NOT TARGET fmt::fmt)
if (TARGET fmt)
add_library(fmt::fmt ALIAS fmt)
else()
message(FATAL_ERROR "Could not find or fetch fmt; no target fmt or fmt::fmt available")
endif()
endif()
set(fmt_FOUND TRUE)
set(fmt_LIBRARIES fmt::fmt)
set(fmt_VERSION "${fmt_VERSION}") # this comes from the fmt project
get_target_property(_fmt_inc fmt::fmt INTERFACE_INCLUDE_DIRECTORIES)
set(fmt_INCLUDE_DIR "${_fmt_inc}")

70
cmake/Findutf8cpp.cmake Normal file
View File

@@ -0,0 +1,70 @@
if (DEFINED _FINDUTF8CPP_INCLUDED)
unset(utf8cpp_FOUND CACHE)
unset(utf8cpp_DIR CACHE)
unset(utf8cpp_INCLUDE_DIR CACHE)
unset(utf8cpp_LIBRARIES CACHE)
unset(utf8cpp_VERSION CACHE)
return()
endif()
set(_FINDUTF8CPP_INCLUDED TRUE)
find_package(utf8cpp QUIET)
if (NOT utf8cpp_FOUND)
message(STATUS "utf8cpp not found. Fetching via FetchContent...")
include(FetchContent)
find_program(GIT_EXECUTABLE git)
if (GIT_EXECUTABLE)
set(UTF8CPP_FETCH_METHOD "GIT")
else()
set(UTF8CPP_FETCH_METHOD "ZIP")
endif()
if (UTF8CPP_FETCH_METHOD STREQUAL "GIT")
FetchContent_Declare(
utf8cpp
GIT_REPOSITORY https://github.com/nemtrif/utfcpp.git
GIT_TAG v4.0.6
)
else()
FetchContent_Declare(
utf8cpp
URL https://github.com/nemtrif/utfcpp/archive/refs/tags/v4.0.6.zip
)
endif()
FetchContent_MakeAvailable(utf8cpp)
else()
message(STATUS "utf8cpp found.")
# Ensure we have a usable target
if (NOT TARGET utf8cpp::utf8cpp)
if (TARGET utf8cpp)
add_library(utf8cpp::utf8cpp ALIAS utf8cpp)
else()
message(FATAL_ERROR "utf8cpp was found, but no CMake target 'utf8cpp' or 'utf8cpp::utf8cpp' exists.")
endif()
endif()
# Populate the standard variables
set(utf8cpp_FOUND TRUE)
set(utf8cpp_LIBRARIES utf8cpp::utf8cpp)
get_target_property(_utf8cpp_inc utf8cpp::utf8cpp INTERFACE_INCLUDE_DIRECTORIES)
set(utf8cpp_INCLUDE_DIR "${_utf8cpp_inc}")
endif()
if (NOT TARGET utf8cpp::utf8cpp)
if (TARGET utf8cpp)
add_library(utf8cpp::utf8cpp ALIAS utf8cpp)
else()
message(FATAL_ERROR "Could not find or fetch utf8cpp; no target utf8cpp or utf8cpp::utf8cpp available")
endif()
endif()
set(utf8cpp_FOUND TRUE)
set(utf8cpp_LIBRARIES utf8cpp::utf8cpp)
set(utf8cpp_VERSION "${utf8cpp_VERSION}") # this comes from the utf8cpp project
get_target_property(_utf8cpp_inc utf8cpp::utf8cpp INTERFACE_INCLUDE_DIRECTORIES)
set(utf8cpp_INCLUDE_DIR "${_utf8cpp_inc}")

98
cmake/platform.cmake Normal file
View File

@@ -0,0 +1,98 @@
# cmake/platform.cmake
# Platform detection + compiler options
if(DEFINED PLATFORM_CONFIG_INCLUDED)
return()
endif()
set(PLATFORM_CONFIG_INCLUDED TRUE)
# -------------------------------------------------------
# Platform detection
# -------------------------------------------------------
if(APPLE)
set(PLATFORM "macOS")
message(STATUS "Platform: ${PLATFORM}")
set(PLATFORM_LINK_LIBRARIES
"-framework Cocoa"
"-framework IOKit"
"-framework CoreVideo"
"-framework OpenGL"
)
elseif(UNIX AND NOT APPLE AND NOT EMSCRIPTEN) # Linux, BSD, etc.
set(PLATFORM "Linux")
message(STATUS "Platform: ${PLATFORM}")
set(PLATFORM_LINK_LIBRARIES
dl
m
GL
X11
)
elseif(WIN32)
set(PLATFORM "Windows")
message(STATUS "Platform: ${PLATFORM}")
set(PLATFORM_LINK_LIBRARIES
OpenGL32.lib
)
set(PLATFORM_DEFINITIONS
${PLATFORM_DEFINITIONS}
"_WIN32_WINNT=0x0A00"
)
elseif(EMSCRIPTEN)
set(PLATFORM "Emscripten")
message(STATUS "Platform: ${PLATFORM}")
# Emscripten specific flags (not the warnings; those are below)
add_compile_options(
-pthread
-fexceptions
-sUSE_PTHREADS=1
)
add_link_options(
-pthread
-fexceptions
-sUSE_PTHREADS=1
)
else()
message(FATAL_ERROR "Platform: Unknown!")
endif()
# -------------------------------------------------------
# Compiler specific options (BASE_OPTIONS)
# -------------------------------------------------------
if(NOT MSVC)
set(BASE_OPTIONS
-Wall
-Wextra
# -Werror
# fmt warnings
-Wno-deprecated-literal-operator
)
if(EMSCRIPTEN)
list(APPEND BASE_OPTIONS
# asio
-Wno-sign-conversion
-Wno-shadow
-Wno-shorten-64-to-32
-Wno-implicit-int-conversion
-Wno-unused-private-field
-Wno-deprecated-declarations
)
endif()
else()
set(BASE_OPTIONS
/W4
# /WX # warnings as errors (MSVC equivalent of -Werror)
/utf-8
/Zc:__cplusplus
#/fsanitize=address # Doesn't work without Visual Studio
)
endif()

View File

@@ -1,6 +0,0 @@
3 4
4 3
2 5
1 3
3 9
3 3

View File

@@ -1,6 +0,0 @@
7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +0,0 @@
project(
'aoc',
['cpp', 'c++']
version: '0.0.0',
default_options: [
'c_std=c2x',
'cpp_std=c++23'
]
)
executable(
'aoc',
[
'aoc.cpp'
],
include_directories: [
include_directories('.')
]
)