Compare commits

..

11 Commits

Author SHA1 Message Date
bc3ea85dae Adds cargo and adds nix to editor config.
Some checks failed
Continuous Integration / Continuous Integration (push) Failing after 1m2s
2025-12-11 16:34:08 -08:00
ee116e4c52 Adds Flake.nix and .envrc
Some checks failed
Continuous Integration / Continuous Integration (push) Has been cancelled
2025-12-11 16:32:15 -08:00
Felix Spöttel
c89b57bb47 fix: fmt 2025-11-26 14:19:56 +01:00
Felix Spöttel
4bf768288d chore: bump AOC_YEAR to 2025 2025-11-26 14:16:22 +01:00
Felix Spöttel
a939163268 feat: update to rust edition 2024 2025-11-26 14:14:49 +01:00
Felix Spöttel
b67460e2b9 fix: clippy warning 2025-11-24 19:29:12 +01:00
Tristan Guichaoua
ead6e2ccf7 Make Day::new const and remove Day::__new_unchecked (#73) 2025-11-22 10:15:59 +01:00
Felix Spöttel
012c8e1286 Merge pull request #75 from penelopeysm/main 2024-12-11 13:26:22 +01:00
Penelope Yong
1f140f6047 Fix a README typo 2024-12-11 11:41:45 +00:00
Penelope Yong
8d92a20cde Remove warning in README 2024-12-11 11:38:45 +00:00
Penelope Yong
6d4f9b50c8 Use u64 to represent solution
Some puzzles have solutions which are too large for `u32`s.
2024-12-11 11:34:34 +00:00
18 changed files with 136 additions and 45 deletions

View File

@@ -9,4 +9,4 @@ all = "run --quiet --release -- all"
time = "run --quiet --release -- time" time = "run --quiet --release -- time"
[env] [env]
AOC_YEAR = "2024" AOC_YEAR = "2025"

View File

@@ -15,3 +15,7 @@ trim_trailing_whitespace = false
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[*.nix]
indent_size = 2

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

3
.gitignore vendored
View File

@@ -28,3 +28,6 @@ dhat-heap.json
# Benchmarks # Benchmarks
data/timings.json data/timings.json
# Direnv stuff
.direnv/

4
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[package]] [[package]]
name = "addr2line" name = "addr2line"
@@ -19,7 +19,7 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "advent_of_code" name = "advent_of_code"
version = "0.11.0" version = "0.12.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"dhat", "dhat",

View File

@@ -1,8 +1,8 @@
[package] [package]
name = "advent_of_code" name = "advent_of_code"
version = "0.11.0" version = "0.12.0"
authors = ["Felix Spöttel <1682504+fspoettel@users.noreply.github.com>"] authors = ["Felix Spöttel <1682504+fspoettel@users.noreply.github.com>"]
edition = "2021" edition = "2024"
default-run = "advent_of_code" default-run = "advent_of_code"
publish = false publish = false

View File

@@ -282,14 +282,10 @@ You can pass the report a tool like [dh-view](https://nnethercote.github.io/dh_v
- [itertools](https://crates.io/crates/itertools): Extends iterators with extra methods and adaptors. Frequently useful for aoc puzzles. - [itertools](https://crates.io/crates/itertools): Extends iterators with extra methods and adaptors. Frequently useful for aoc puzzles.
- [regex](https://crates.io/crates/regex): Official regular expressions implementation for Rust. - [regex](https://crates.io/crates/regex): Official regular expressions implementation for Rust.
A curated list of popular crates can be found on [blessred.rs](https://blessed.rs/crates). A curated list of popular crates can be found on [blessed.rs](https://blessed.rs/crates).
Do you have aoc-specific crate recommendations? [Share them!](https://github.com/fspoettel/advent-of-code-rust/edit/main/README.md) Do you have aoc-specific crate recommendations? [Share them!](https://github.com/fspoettel/advent-of-code-rust/edit/main/README.md)
## Common pitfalls
- **Integer overflows:** This template uses 32-bit integers by default because it is generally faster - for example when packed in large arrays or structs - than using 64-bit integers everywhere. For some problems, solutions for real input might exceed 32-bit integer space. While this is checked and panics in `debug` mode, integers [wrap](https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-overflow) in `release` mode, leading to wrong output when running your solution.
## Footnotes ## Footnotes
[^1]: The session cookie might expire after a while (~1 month) which causes the downloads to fail. To fix this issue, refresh the `.adventofcode.session` file. [^1]: The session cookie might expire after a while (~1 month) which causes the downloads to fail. To fix this issue, refresh the `.adventofcode.session` file.

61
flake.lock generated Normal file
View File

@@ -0,0 +1,61 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1765311797,
"narHash": "sha256-mSD5Ob7a+T2RNjvPvOA1dkJHGVrNVl8ZOrAwBjKBDQo=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "09eb77e94fa25202af8f3e81ddc7353d9970ac1b",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"utils": "utils"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

31
flake.nix Normal file
View File

@@ -0,0 +1,31 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-25.11";
utils.url = "github:numtide/flake-utils";
};
outputs =
{
self,
nixpkgs,
utils,
}:
utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
in
{
devShell =
with pkgs;
mkShell {
buildInputs = [
rustc
cargo
clippy
rustfmt
];
};
}
);
}

View File

@@ -1,5 +1,5 @@
use advent_of_code::template::commands::{all, download, read, scaffold, solve, time}; use advent_of_code::template::commands::{all, download, read, scaffold, solve, time};
use args::{parse, AppArguments}; use args::{AppArguments, parse};
#[cfg(feature = "today")] #[cfg(feature = "today")]
use advent_of_code::template::Day; use advent_of_code::template::Day;

View File

@@ -1,10 +1,10 @@
advent_of_code::solution!(%DAY_NUMBER%); advent_of_code::solution!(%DAY_NUMBER%);
pub fn part_one(input: &str) -> Option<u32> { pub fn part_one(input: &str) -> Option<u64> {
None None
} }
pub fn part_two(input: &str) -> Option<u32> { pub fn part_two(input: &str) -> Option<u64> {
None None
} }

View File

@@ -1,9 +1,11 @@
use crate::template::{aoc_cli, Day}; use crate::template::{Day, aoc_cli};
use std::process; use std::process;
pub fn handle(day: Day) { pub fn handle(day: Day) {
if aoc_cli::check().is_err() { if aoc_cli::check().is_err() {
eprintln!("command \"aoc\" not found or not callable. Try running \"cargo install aoc-cli\" to install it."); eprintln!(
"command \"aoc\" not found or not callable. Try running \"cargo install aoc-cli\" to install it."
);
process::exit(1); process::exit(1);
} }

View File

@@ -1,10 +1,12 @@
use std::process; use std::process;
use crate::template::{aoc_cli, Day}; use crate::template::{Day, aoc_cli};
pub fn handle(day: Day) { pub fn handle(day: Day) {
if aoc_cli::check().is_err() { if aoc_cli::check().is_err() {
eprintln!("command \"aoc\" not found or not callable. Try running \"cargo install aoc-cli\" to install it."); eprintln!(
"command \"aoc\" not found or not callable. Try running \"cargo install aoc-cli\" to install it."
);
process::exit(1); process::exit(1);
} }

View File

@@ -2,7 +2,7 @@ use std::collections::HashSet;
use crate::template::run_multi::run_multi; use crate::template::run_multi::run_multi;
use crate::template::timings::Timings; use crate::template::timings::Timings;
use crate::template::{all_days, readme_benchmarks, Day}; use crate::template::{Day, all_days, readme_benchmarks};
pub fn handle(day: Option<Day>, run_all: bool, store: bool) { pub fn handle(day: Option<Day>, run_all: bool, store: bool) {
let stored_timings = Timings::read_from_file(); let stored_timings = Timings::read_from_file();

View File

@@ -24,19 +24,13 @@ pub struct Day(u8);
impl Day { impl Day {
/// Creates a [`Day`] from the provided value if it's in the valid range, /// Creates a [`Day`] from the provided value if it's in the valid range,
/// returns [`None`] otherwise. /// returns [`None`] otherwise.
pub fn new(day: u8) -> Option<Self> { pub const fn new(day: u8) -> Option<Self> {
if day == 0 || day > 25 { if day == 0 || day > 25 {
return None; return None;
} }
Some(Self(day)) Some(Self(day))
} }
// Not part of the public API
#[doc(hidden)]
pub const fn __new_unchecked(day: u8) -> Self {
Self(day)
}
/// Converts the [`Day`] into an [`u8`]. /// Converts the [`Day`] into an [`u8`].
pub fn into_inner(self) -> u8 { pub fn into_inner(self) -> u8 {
self.0 self.0
@@ -137,24 +131,19 @@ impl Iterator for AllDays {
/// Creates a [`Day`] value in a const context. /// Creates a [`Day`] value in a const context.
#[macro_export] #[macro_export]
macro_rules! day { macro_rules! day {
($day:expr) => {{ ($day:expr) => {
const _ASSERT: () = assert!( const {
$day != 0 && $day <= 25, $crate::template::Day::new($day)
concat!( .expect("invalid day number, expecting a value between 1 and 25")
"invalid day number `", }
$day, };
"`, expecting a value between 1 and 25"
),
);
$crate::template::Day::__new_unchecked($day)
}};
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
#[cfg(feature = "test_lib")] #[cfg(feature = "test_lib")]
mod tests { mod tests {
use super::{all_days, Day}; use super::{Day, all_days};
#[test] #[test]
fn all_days_iterator() { fn all_days_iterator() {

View File

@@ -2,8 +2,8 @@
/// The approach taken is similar to how `aoc-readme-stars` handles this. /// The approach taken is similar to how `aoc-readme-stars` handles this.
use std::{fs, io}; use std::{fs, io};
use crate::template::timings::Timings;
use crate::template::Day; use crate::template::Day;
use crate::template::timings::Timings;
static MARKER: &str = "<!--- benchmarking table --->"; static MARKER: &str = "<!--- benchmarking table --->";
@@ -99,7 +99,7 @@ pub fn update(timings: Timings) -> Result<(), Error> {
#[cfg(feature = "test_lib")] #[cfg(feature = "test_lib")]
mod tests { mod tests {
use super::{update_content, MARKER}; use super::{MARKER, update_content};
use crate::{day, template::timings::Timing, template::timings::Timings}; use crate::{day, template::timings::Timing, template::timings::Timings};
fn get_mock_timings() -> Timings { fn get_mock_timings() -> Timings {

View File

@@ -1,6 +1,6 @@
use std::{collections::HashSet, io}; use std::{collections::HashSet, io};
use crate::template::{Day, ANSI_BOLD, ANSI_ITALIC, ANSI_RESET}; use crate::template::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET, Day};
use super::{ use super::{
all_days, all_days,
@@ -67,7 +67,7 @@ pub fn get_path_for_bin(day: Day) -> String {
/// All solutions live in isolated binaries. /// All solutions live in isolated binaries.
/// This module encapsulates interaction with these binaries, both invoking them as well as parsing the timing output. /// This module encapsulates interaction with these binaries, both invoking them as well as parsing the timing output.
pub mod child_commands { pub mod child_commands {
use super::{get_path_for_bin, Error}; use super::{Error, get_path_for_bin};
use crate::template::Day; use crate::template::Day;
use std::{ use std::{
io::{BufRead, BufReader}, io::{BufRead, BufReader},
@@ -174,7 +174,7 @@ pub mod child_commands {
.split(" samples)") .split(" samples)")
.next()? .next()?
.split('(') .split('(')
.last()? .next_back()?
.split('@') .split('@')
.next()? .next()?
.trim(); .trim();

View File

@@ -1,13 +1,13 @@
/// Encapsulates code that interacts with solution functions. /// Encapsulates code that interacts with solution functions.
use std::fmt::Display; use std::fmt::Display;
use std::hint::black_box; use std::hint::black_box;
use std::io::{stdout, Write}; use std::io::{Write, stdout};
use std::process::Output; use std::process::Output;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::{cmp, env, process}; use std::{cmp, env, process};
use crate::template::ANSI_BOLD; use crate::template::ANSI_BOLD;
use crate::template::{aoc_cli, Day, ANSI_ITALIC, ANSI_RESET}; use crate::template::{ANSI_ITALIC, ANSI_RESET, Day, aoc_cli};
pub fn run_part<I: Copy, T: Display>(func: impl Fn(I) -> Option<T>, input: I, day: Day, part: u8) { pub fn run_part<I: Copy, T: Display>(func: impl Fn(I) -> Option<T>, input: I, day: Day, part: u8) {
let part_str = format!("Part {part}"); let part_str = format!("Part {part}");
@@ -156,7 +156,9 @@ fn submit_result<T: Display>(
} }
if aoc_cli::check().is_err() { if aoc_cli::check().is_err() {
eprintln!("command \"aoc\" not found or not callable. Try running \"cargo install aoc-cli\" to install it."); eprintln!(
"command \"aoc\" not found or not callable. Try running \"cargo install aoc-cli\" to install it."
);
process::exit(1); process::exit(1);
} }