Implement safe cracking logic and setup development environment

- Added a new `main.cpp` file with logic to parse dial rotations from a file and execute safe cracking based on the parsed data.
- Introduced a `DialRotation` struct to represent the direction and distance of dial rotations.
- Implemented `parseRotations` function to read and parse input from a specified file, returning a vector of `DialRotation` or an error message.
- Created `executeSafeCrack` function to process the dial rotations and print the current state of the dial.
- Added `.clang-format` and `.clang-tidy` configuration files for code formatting and linting.
- Set up a Dockerfile for a development container with necessary tools and dependencies.
- Configured VS Code settings and tasks for building, formatting, and running clang-tidy.
- Added a script to run clang-tidy on the source files, ensuring code quality.
This commit is contained in:
Feiko Wielsma 2025-12-01 21:01:09 +00:00
parent c093e8a4bf
commit 38eca3b747
11 changed files with 4654 additions and 3 deletions

3
.clang-format Normal file
View file

@ -0,0 +1,3 @@
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 120

4
.clang-tidy Normal file
View file

@ -0,0 +1,4 @@
Checks: '-*,modernize-*,readability-*,bugprone-*,performance-*'
WarningsAsErrors: ''
HeaderFilterRegex: '.*'
FormatStyle: file

23
.devcontainer/Dockerfile Normal file
View file

@ -0,0 +1,23 @@
FROM xianpengshen/clang-tools:21
# Install development tools (cmake, ninja, build essentials)
USER root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
cmake \
ninja-build \
build-essential \
git \
python3 \
python3-pip \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Create workspace folder (VS Code devcontainer convention)
ARG WORKSPACE_FOLDER=/workspaces/aoc25
RUN mkdir -p ${WORKSPACE_FOLDER} && chown -R root:root ${WORKSPACE_FOLDER}
WORKDIR ${WORKSPACE_FOLDER}
ENV SHELL=/bin/bash
CMD ["bash"]

View file

@ -0,0 +1,20 @@
{
"name": "aoc25-clang21",
"build": {
"dockerfile": "Dockerfile"
},
"workspaceFolder": "/workspaces/aoc25",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/aoc25,type=bind,consistency=cached",
"settings": {
"C_Cpp.default.compilerPath": "/usr/bin/clang++-21",
"C_Cpp.default.intelliSenseMode": "linux-clang-x64",
"clang-format.executable": "/usr/bin/clang-format-21"
},
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools",
"llvm-vs-code-extensions.vscode-clangd",
"xaver.clang-format"
],
"postCreateCommand": "cmake -S . -B build || true"
}

9
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,9 @@
{
"editor.formatOnSave": true,
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"cmake.configureOnOpen": false,
"cmake.generator": "Ninja",
"clangd.arguments": [
"--compile-commands-dir=build"
]
}

33
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,33 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "CMake: Configure",
"type": "shell",
"command": "cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
"problemMatcher": []
},
{
"label": "CMake: Build",
"type": "shell",
"command": "cmake --build build -- -j",
"problemMatcher": []
},
{
"label": "Clang-Format: Format Workspace",
"type": "shell",
"command": "bash -lc \"find . -name \"*.cpp\" -o -name \"*.hpp\" -o -name \"*.h\" | xargs -r clang-format -i\"",
"problemMatcher": []
},
{
"label": "Clang-Tidy: Run",
"type": "shell",
"command": "./scripts/run-clang-tidy.sh",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"problemMatcher": []
}
]
}

View file

@ -1,4 +1,9 @@
cmake_minimum_required(VERSION 3.10.0)
# Set compilers before project() to ensure they're used
set(CMAKE_C_COMPILER /usr/bin/clang-21)
set(CMAKE_CXX_COMPILER /usr/bin/clang++-21)
project(aoc25 VERSION 0.1.0 LANGUAGES C CXX)
# Per-day subprojects (example: day1)

View file

@ -1,2 +1,11 @@
add_executable(day1 main.cpp)
set_target_properties(day1 PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON)
set_target_properties(day1 PROPERTIES CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON)
# Use GCC 15's libstdc++ with Clang 21
target_compile_options(day1 PRIVATE --gcc-toolchain=/usr)
add_custom_command(TARGET day1 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/day1_input
$<TARGET_FILE_DIR:day1>/day1_input
COMMENT "Copying day1_input to build directory"
)

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,76 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <expected>
#include <print>
int main(int, char**){
std::cout << "Hello, from aoc25 day1!\n";
struct DialRotation {
char direction;
int distance;
};
auto parseRotations(const std::string& filename) -> std::expected<std::vector<DialRotation>, std::string> {
std::ifstream inputF {filename};
if (!inputF){
return std::unexpected{"Some file open error.\n"};
}
std::vector<DialRotation> dialRotations{};
DialRotation curDial{};
while ( inputF >> curDial.direction >> curDial.distance)
{
//std::println("{} : {}", curDial.direction, curDial.distance);
dialRotations.push_back(curDial);
}
return std::move(dialRotations);
}
constexpr int dialStart = 50;
constexpr int maxDial = 100 ;
auto executeSafeCrack(const std::vector<DialRotation>& dialRotations){
int dial {dialStart};
int countZero {};
for (const auto& curDial : dialRotations){
if(curDial.direction == 'L'){
dial -= curDial.distance % maxDial;
if (dial < 0){
dial += maxDial;
}
}
else{
dial += curDial.distance % maxDial;
if (dial > maxDial - 1){
dial -= maxDial;
}
}
std::println("{} : {:3}, Dial now at: {:5}", curDial.direction, curDial.distance, dial);
if (dial == 0){
countZero++;
}
if (dial < 0){
break;
}
if (dial > maxDial){
break;
}
}
std::print("Zeros: {}", countZero);
}
auto main(int, char**) -> int {
std::cout << "Hello, from aoc25 day1!!\n";
auto retval = parseRotations("day1_input");
if(retval)
{
executeSafeCrack(*retval);
}
else{
std::print("{}\n", retval.error());
}
return 0;
}

28
scripts/run-clang-tidy.sh Normal file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
BUILD_DIR=build
if [ ! -f "${BUILD_DIR}/compile_commands.json" ]; then
echo "compile_commands.json not found; running cmake configure..."
cmake -S . -B "${BUILD_DIR}" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
fi
if ! command -v clang-tidy >/dev/null 2>&1; then
echo "clang-tidy not found in PATH"
exit 1
fi
# Prefer files tracked by git; fallback to find
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
FILES=$(git ls-files '*.cpp' '*.cxx' '*.cc' '*.h' '*.hpp' || true)
else
FILES=$(find . -iname "*.cpp" -o -iname "*.cc" -o -iname "*.cxx" -o -iname "*.h" -o -iname "*.hpp")
fi
if [ -z "${FILES}" ]; then
echo "No source files found for clang-tidy"
exit 0
fi
for f in ${FILES}; do
echo "Running clang-tidy on ${f}"
clang-tidy "${f}" -p "${BUILD_DIR}" || true
done