Skip to content

github: added token #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/cmake-single-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.DATA_PAT }}
submodules: recursive

- name: Configure CMake
Expand Down
15 changes: 10 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.20)
project(advent2024 LANGUAGES CXX)

option(DAY7_CONSTEXPR "Enables computing solution at compile-time" OFF)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_options(-Wall -Wextra -Wpedantic -O2)

Expand All @@ -20,6 +22,9 @@ add_challenge(day5)
### Day 7
add_challenge(day7)
target_compile_options(day7 PRIVATE -fconstexpr-ops-limit=3355443200)
if(DAY7_CONSTEXPR)
target_compile_options(day7 PRIVATE -DDAY7_CONSTEXPR)
endif()

# Read the content of the input file
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/data/2024/day7.txt FILE_CONTENT)
Expand All @@ -32,16 +37,16 @@ file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/data/2024/day7_constexpr.txt ${FILE_CONTE


add_challenge(day8)
add_challenge(day9)
# add_challenge(day9)
add_challenge(day10)
add_challenge(day11)
add_challenge(day12)
add_challenge(day13)
add_challenge(day14)
add_challenge(day15)
add_challenge(day16)
add_challenge(day17)
add_challenge(day18)
# add_challenge(day15)
# add_challenge(day16)
# add_challenge(day17)
# add_challenge(day18)
add_challenge(day19)
add_challenge(day24)
add_challenge(day25)
Expand Down
3 changes: 3 additions & 0 deletions include/common_headers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
#include "utils/input_parser.hpp"

#include <algorithm>
#include <array>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <charconv>
#include <vector>
#include <string>
#include <stdexcept>
#include <numeric>
#include <unordered_map>
2 changes: 1 addition & 1 deletion include/utils/numeric_algorithm.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <stdint.h>
#include <cstdint>
#include <cmath>

[[nodiscard]] constexpr size_t numOfDigits(uint64_t num) noexcept {
Expand Down
1 change: 1 addition & 0 deletions src/day1.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <vector>
Expand Down
1 change: 1 addition & 0 deletions src/day11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "utils/numeric_algorithm.hpp"

#include <cmath>
#include <cstdint>
#include <sstream>


Expand Down
192 changes: 192 additions & 0 deletions src/day13.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#include "common_headers.hpp"
#include <cmath>
#include <regex>

void printHelp()
{
std::cerr << "\nUsage:\n"
<< "The program requires 2 args: (part1, part2) and the path to the file."
<< "\nFor example, ./day7 part1 data/day7.txt";
}

using Matrix = std::vector<std::vector<long double>>;
using Vector = std::vector<long double>;

struct EquationParams final
{
Matrix coords;
Vector result;

void appendXY(std::pair<int64_t, int64_t> xy) {
coords.resize(2);
coords[0].push_back(xy.first);
coords[1].push_back(xy.second);
}

void setResult(std::pair<int64_t, int64_t> resultXY) {
result.push_back(resultXY.first);
result.push_back(resultXY.second);
}
};


void gaussianElimination(Matrix& A, Vector& b) {
int n = A.size();

for (int i = 0; i < n; ++i) {
// Partial pivoting
int maxRow = i;
for (int k = i + 1; k < n; ++k) {
if (std::abs(A[k][i]) > std::abs(A[maxRow][i])) {
maxRow = k;
}
}

// Swap rows in A and b
std::swap(A[i], A[maxRow]);
std::swap(b[i], b[maxRow]);

// Check for singularity
if (std::abs(A[i][i]) < 1e-10) {
throw std::runtime_error("Matrix is singular or nearly singular");
}

// Eliminate column i below the pivot
for (int k = i + 1; k < n; ++k) {
double factor = A[k][i] / A[i][i];
for (int j = i; j < n; ++j) {
A[k][j] -= factor * A[i][j];
}
b[k] -= factor * b[i];
}
}
}

Vector backSubstitution(const Matrix& A, const Vector& b) {
int n = A.size();
Vector x(n);

for (int i = n - 1; i >= 0; --i) {
x[i] = b[i];
for (int j = i + 1; j < n; ++j) {
x[i] -= A[i][j] * x[j];
}
x[i] /= A[i][i];
}

return x;
}

Vector solveLinearSystem(Matrix A, Vector b) {
gaussianElimination(A, b);
return backSubstitution(A, b);
}

bool checkResultCorrectness(const Vector& result, double upperBoundValue) {
for(auto r : result) {
if(!std::isfinite(r) || std::abs(std::trunc(std::round(r)) - r) > 0.0003 || r > upperBoundValue) {
if(r > 100) {
}
std::cerr << "\nsolution incorrect: " << r ;
return false;
}
}
return true;
}

size_t solveFirstPart(const std::vector<EquationParams>& equationParams) {
constexpr size_t costButtonA{3};
constexpr size_t costButtonB{1};
size_t tokens{};

for(const auto& equation : equationParams) {
Vector result = solveLinearSystem(equation.coords, equation.result);
if(checkResultCorrectness(result, 100)) {
tokens += static_cast<size_t>(std::round(result.at(0))) * costButtonA + static_cast<size_t>(std::round(result.at(1)) * costButtonB);
}
}
return tokens;
}

size_t solveSecondPart(const std::vector<EquationParams>& equationParams) {
constexpr size_t costButtonA{3};
constexpr size_t costButtonB{1};
size_t tokens{};

for(const auto& equation : equationParams) {
Vector result = solveLinearSystem(equation.coords, equation.result);
if(checkResultCorrectness(result, 10000000000000)) {
tokens += static_cast<size_t>(std::round(result.at(0))) * costButtonA + static_cast<size_t>(std::round(result.at(1)) * costButtonB);
}
}
return tokens;
}


[[nodiscard]] std::pair<int64_t, int64_t> parseXY(const std::string& input) {
std::pair<int64_t, int64_t> values{};

// Regular expression to match the input pattern
std::regex pattern(R"((\w+ \w+|\w+): X[+=](\-?\d+), Y[+=](\-?\d+))");
std::smatch matches;

std::string::const_iterator searchStart(input.cbegin());
std::regex_search(searchStart, input.cend(), matches, pattern);
// std::cerr << "\nx " << matches[2] << " y " << matches[3];
return std::pair{std::stoll(matches[2]), std::stoll(matches[3])};
}

[[nodiscard]] EquationParams parse(const std::string& buttonA, const std::string& buttonB, const std::string& result) {
EquationParams params;
params.appendXY(parseXY(buttonA));
params.appendXY(parseXY(buttonB));
params.setResult(parseXY(result));
return params;
}

[[nodiscard]] std::vector<EquationParams> parseEquationParams(const std::vector<std::string>& inputLines) {
std::vector<EquationParams> equationParams;
for(size_t i = 0; i + 3 <= inputLines.size();) {
if(inputLines[i].empty()) {
++i;
}
else {
equationParams.emplace_back(parse(inputLines[i], inputLines[i + 1], inputLines[i + 2]));
i += 3;
}
}
return equationParams;
}

int main(int argc, char* argv[])
{
if(argc != 3) {
printHelp();
return 1;
}

std::string_view task{argv[1]};
if(task != "part1" && task != "part2") {
std::cerr << "\nfirst arg can be either `part1` or `part2`\n";
printHelp();
return 1;
}

std::vector<std::string> inputVec;
readInput(argv[2], std::back_inserter(inputVec));
std::vector<EquationParams> equationParams = parseEquationParams(inputVec);


if(task == "part1") {
std::cout << solveFirstPart(equationParams);
}
else {
for(auto& param : equationParams) {
param.result[0] += 10000000000000;
param.result[1] += 10000000000000;
}
std::cout << solveSecondPart(equationParams);
}

return 0;
}
1 change: 1 addition & 0 deletions src/day1_part2.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <fstream>
#include <unordered_map>
Expand Down
83 changes: 83 additions & 0 deletions src/day2_part1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <algorithm>
#include <iostream>
#include <fstream>
#include <charconv>
#include <vector>
#include <stdexcept>

namespace {
void parseLevels(const std::string& report, std::vector<int>& out)
{
if(report.empty()) return;

const char *begin = &report[0];
const char * const end = &report[report.size()];
std::from_chars_result result{};
int val{};
while(begin != end) {
result = std::from_chars(begin, end, val);
if(result.ec != std::errc()) {
std::cerr << "\nreport: " << report;
throw std::logic_error{"Invalid report input string"};
}
begin = std::min(result.ptr + 1, end);
out.push_back(val);
}
}

[[nodiscard]] constexpr bool isLevelsSafe(int largelLevel, int smallerLevel) noexcept
{
const auto diff{largelLevel - smallerLevel};
return 1 <= diff && diff <= 3;
}


[[nodiscard]] bool isAscendingSafe(const std::vector<int>& levels) noexcept
{
return std::adjacent_find(levels.begin(), levels.end(), [](int smallerLevel, int largerLevel) {
return !isLevelsSafe(largerLevel, smallerLevel);
}) == levels.end();
}

[[nodiscard]] bool isDescendingSafe(const std::vector<int>& levels) noexcept
{
return std::adjacent_find(levels.rbegin(), levels.rend(), [](int smallerLevel, int largerLevel) {
return !isLevelsSafe(largerLevel, smallerLevel);
}) == levels.rend();
}

[[nodiscard]] bool isSafe(const std::vector<int>& levels) noexcept
{
if(levels.front() < levels.back()) {
return isAscendingSafe(levels);
}
return isDescendingSafe(levels);
}
} //< anonymous namespace

int main(int argc, char *argv[]) {
if(argc != 2) {
std::cerr << "\nUsage:\n"
<< "The program requires the path to the file.";
return 1;
}

std::ifstream ifile(argv[1]);
if(!ifile) {
std::cerr << "\nFile cannot be open";
return 1;
}

size_t count{};
std::string report;
std::vector<int> levels;
while(std::getline(ifile, report)) {
// std::cerr << "\nline " << report;
levels.clear();
parseLevels(report, levels);
count += isSafe(levels);
}
std::cout << count;

return 0;
}
3 changes: 3 additions & 0 deletions src/day4.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "common_headers.hpp"

#include <array>


/*
Part 1.
The task is to count the word `XMAS` horizontally, vertically, diagonally.
Expand Down
Loading