feat: use `cargo --bin` instead of solutions crate

This commit is contained in:
Felix Spöttel 2021-12-29 14:36:48 +01:00
parent 4449f5bc94
commit 681c03ad89
9 changed files with 100 additions and 132 deletions

4
.gitignore vendored
View File

@ -16,5 +16,5 @@ target/
# Advent of Code # Advent of Code
# @see https://old.reddit.com/r/adventofcode/comments/k99rod/sharing_input_data_were_we_requested_not_to/gf2ukkf/?context=3 # @see https://old.reddit.com/r/adventofcode/comments/k99rod/sharing_input_data_were_we_requested_not_to/gf2ukkf/?context=3
inputs /src/inputs
!inputs/.keep !/src/inputs/.keep

View File

@ -3,7 +3,7 @@ name = "aoc"
version = "0.1.0" version = "0.1.0"
authors = ["Felix Spöttel <1682504+fspoettel@users.noreply.github.com>"] authors = ["Felix Spöttel <1682504+fspoettel@users.noreply.github.com>"]
edition = "2021" edition = "2021"
default-run = "aoc"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release] [profile.release]

View File

@ -33,15 +33,14 @@ Generated with the [advent-of-code-rust](https://github.com/fspoettel/advent-of-
./scripts/scaffold.sh <day> ./scripts/scaffold.sh <day>
# output: # output:
# Created module `src/solutions/day01.rs` # Created module "src/bin/01.rs"
# Created input file `src/inputs/day01.txt` # Created empty input file "src/inputs/01.txt"
# Created example file `src/examples/day01.txt` # Created empty example file "src/examples/01.txt"
# Linked new module in `src/main.rs` # ---
# Linked new module in `src/solutions/mod.rs` # 🎄 Type `cargo run --bin 01` to run your solution.
# Done! 🎄
``` ```
Every solution file has _unit tests_ referencing the example input file. You can use these tests to develop and debug your solution. When editing a solution file, `rust-analyzer` will display buttons for these actions above the unit tests. Every solution has _unit tests_ referencing the _example_ file. Use these tests to develop and debug your solution. When editing a solution, `rust-analyzer` will display buttons for these actions above the unit tests.
### Download inputs for a day ### Download inputs for a day
@ -50,27 +49,26 @@ Every solution file has _unit tests_ referencing the example input file. You can
./scripts/download.sh <day> ./scripts/download.sh <day>
# output: # output:
# Invoking `aoc` cli... # Loaded session cookie from "/home/felix/.adventofcode.session".
# Loaded session cookie from "/home/foo/.adventofcode.session".
# Downloading input for day 1, 2021... # Downloading input for day 1, 2021...
# Saving puzzle input to "/tmp/..."... # Saving puzzle input to "/tmp/tmp.MBdcAdL9Iw/input"...
# Done! # Done!
# Wrote input to `src/inputs/day01.txt`... # ---
# Done! 🎄 # 🎄 Successfully wrote input to "src/inputs/01.txt"!
``` ```
Puzzle inputs are not checked into git. [See here](https://old.reddit.com/r/adventofcode/comments/k99rod/sharing_input_data_were_we_requested_not_to/gf2ukkf/?context=3) why. Puzzle inputs are not checked into git. [See here](https://old.reddit.com/r/adventofcode/comments/k99rod/sharing_input_data_were_we_requested_not_to/gf2ukkf/?context=3) why.
> This script does not support downloading inputs for previous years. If you want to use this template for a previous aoc, [use the underlying `aoc-cli` binary directly](https://github.com/scarvalhojr/aoc-cli/#download-puzzle-input) or download your inputs manually.
### Run solutions for a day ### Run solutions for a day
```sh ```sh
# example: `cargo run 1` # example: `cargo run --bin 01`
cargo run <day> cargo run --bin <day>
# output: # output:
# Running `target/debug/aoc 1` # Running `target/debug/01`
# ----
#
# 🎄 Part 1 🎄 # 🎄 Part 1 🎄
# #
# 6 (elapsed: 37.03µs) # 6 (elapsed: 37.03µs)
@ -78,11 +76,17 @@ cargo run <day>
# 🎄 Part 2 🎄 # 🎄 Part 2 🎄
# #
# 9 (elapsed: 33.18µs) # 9 (elapsed: 33.18µs)
#
# ----
``` ```
To run an optimized version for benchmarking, use the `--release` flag or the alias `cargo rr <day>`. To run an optimized version for benchmarking, use the `--release` flag or the alias `cargo rr --bin <day>`.
### Run all solutions
```sh
cargo run
```
To run an optimized version for benchmarking, use the `--release` flag or the alias `cargo rr`.
### Run all solutions against example input ### Run all solutions against example input

View File

@ -16,7 +16,7 @@ fi
day=$(echo $1 | sed 's/^0*//'); day=$(echo $1 | sed 's/^0*//');
day_padded=`printf %02d $day`; day_padded=`printf %02d $day`;
filename="day$day_padded"; filename="$day_padded";
input_path="src/inputs/$filename.txt"; input_path="src/inputs/$filename.txt";
tmp_dir=$(mktemp -d); tmp_dir=$(mktemp -d);
@ -24,15 +24,9 @@ tmp_file_path="$tmp_dir/input";
aoc download --day $day --file $tmp_file_path; aoc download --day $day --file $tmp_file_path;
cat $tmp_file_path > $input_path; cat $tmp_file_path > $input_path;
echo "Wrote input to \"$input_path\"..."; echo "---"
echo "🎄 Successfully wrote input to \"$input_path\"!"
cat <<EOF
_==_ _
_,(",)|_|
\/. \-|
__( : )|_ Done!
EOF
# Make sure it gets removed even if the script exits abnormally. # Make sure it gets removed even if the script exits abnormally.
trap "exit 1" HUP INT PIPE QUIT TERM trap "exit 1" HUP INT PIPE QUIT TERM
trap 'rm -rf "$tmp_dir"' EXIT trap 'rm -rf "$tmp_dir"' EXIT

View File

@ -10,15 +10,17 @@ fi
day=$(echo $1 | sed 's/^0*//'); day=$(echo $1 | sed 's/^0*//');
day_padded=`printf %02d $day`; day_padded=`printf %02d $day`;
filename="day$day_padded"; filename="$day_padded";
input_path="src/inputs/$filename.txt"; input_path="src/inputs/$filename.txt";
example_path="src/examples/$filename.txt"; example_path="src/examples/$filename.txt";
module_path="src/solutions/$filename.rs"; module_path="src/bin/$filename.rs";
touch $module_path; touch $module_path;
cat > $module_path <<EOF cat > $module_path <<EOF
use aoc::{solve_day, read_file};
pub fn part_one(input: &str) -> u32 { pub fn part_one(input: &str) -> u32 {
0 0
} }
@ -27,6 +29,10 @@ pub fn part_two(input: &str) -> u32 {
0 0
} }
fn main() {
solve_day!(&read_file("inputs", DAYNUM), part_one, part_two)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -34,43 +40,27 @@ mod tests {
#[test] #[test]
fn test_part_one() { fn test_part_one() {
use aoc::read_file; use aoc::read_file;
let input = read_file("examples", day); let input = read_file("examples", DAYNUM);
assert_eq!(part_one(&input), 0); assert_eq!(part_one(&input), 0);
} }
#[test] #[test]
fn test_part_two() { fn test_part_two() {
use aoc::read_file; use aoc::read_file;
let input = read_file("examples", day); let input = read_file("examples", DAYNUM);
assert_eq!(part_two(&input), 0); assert_eq!(part_two(&input), 0);
} }
} }
EOF EOF
perl -pi -e "s,day,$day,g" $module_path; perl -pi -e "s,DAYNUM,$day,g" $module_path;
echo "Created module \"$module_path\""; echo "Created module \"$module_path\"";
touch $input_path; touch $input_path;
echo "Created input file \"$input_path\""; echo "Created empty input file \"$input_path\"";
touch $example_path; touch $example_path;
echo "Created example file \"$example_path\""; echo "Created empty example file \"$example_path\"";
echo "---"
line=" $day => solve_day!($filename, &input)," echo "🎄 Type \`cargo run --bin $day_padded\` to run your solution."
perl -pi -le "print '$line' if(/^*.day not solved/);" "src/main.rs";
echo "Linked new module in \"src/main.rs\"";
LINE="pub mod $filename;";
FILE="src/solutions/mod.rs";
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE";
echo "Linked new module in \"$FILE\"";
cat <<EOF
_==_ _
_,(",)|_|
\/. \-|
__( : )|_ Done!
EOF

View File

@ -1,13 +1,41 @@
use std::env; use std::env;
use std::fs; use std::fs;
pub static ANSI_ITALIC: &str = "\x1b[3m";
pub static ANSI_BOLD: &str = "\x1b[1m";
pub static ANSI_RESET: &str = "\x1b[0m";
#[macro_export]
macro_rules! solve_day {
($input:expr, $part_one:ident, $part_two:ident) => {{
use aoc::{ANSI_BOLD, ANSI_ITALIC, ANSI_RESET};
use std::fmt::Display;
use std::time::Instant;
fn print_result<T: Display>(func: impl FnOnce(&str) -> T, input: &str) {
let timer = Instant::now();
let result = func(input);
let time = timer.elapsed();
println!(
"{} {}(elapsed: {:.2?}){}",
result, ANSI_ITALIC, time, ANSI_RESET
);
}
println!("🎄 {}Part 1{} 🎄", ANSI_BOLD, ANSI_RESET);
println!("");
print_result($part_one, $input);
println!("");
println!("🎄 {}Part 2{} 🎄", ANSI_BOLD, ANSI_RESET);
println!("");
print_result($part_two, $input);
}};
}
pub fn read_file(folder: &str, day: u8) -> String { pub fn read_file(folder: &str, day: u8) -> String {
let cwd = env::current_dir().unwrap(); let cwd = env::current_dir().unwrap();
let filepath = cwd let filepath = cwd.join("src").join(folder).join(format!("{:02}.txt", day));
.join("src")
.join(folder)
.join(format!("day{:02}.txt", day));
let f = fs::read_to_string(filepath); let f = fs::read_to_string(filepath);
f.expect("could not open input file") f.expect("could not open input file")

View File

@ -1,74 +1,26 @@
use crate::solutions::*; use aoc::{ANSI_BOLD, ANSI_RESET};
use aoc::read_file; use std::process::Command;
use std::env;
use std::fmt::Display;
use std::time::Instant;
mod helpers;
mod solutions;
static ANSI_ITALIC: &str = "\x1b[3m";
static ANSI_BOLD: &str = "\x1b[1m";
static ANSI_RESET: &str = "\x1b[0m";
fn print_result<T: Display>(func: impl FnOnce(&str) -> T, input: &str) {
let timer = Instant::now();
let result = func(input);
let time = timer.elapsed();
println!(
"{} {}(elapsed: {:.2?}){}",
result, ANSI_ITALIC, time, ANSI_RESET
);
}
macro_rules! solve_day {
($day:path, $input:expr) => {{
use $day::*;
println!("----");
println!("");
println!("🎄 {}Part 1{} 🎄", ANSI_BOLD, ANSI_RESET);
println!("");
print_result(part_one, $input);
println!("");
println!("🎄 {}Part 2{} 🎄", ANSI_BOLD, ANSI_RESET);
println!("");
print_result(part_two, $input);
println!("");
println!("----");
}};
}
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); (1..=25).for_each(|day| {
let day: u8 = args[1].clone().parse().unwrap(); let day = format!("{:02}", day);
let input = read_file("inputs", day);
match day { let cmd = Command::new("cargo")
1 => solve_day!(day01, &input), .args(&["run", "--release", "--bin", &day])
2 => solve_day!(day02, &input), .output()
3 => solve_day!(day03, &input), .unwrap();
4 => solve_day!(day04, &input),
5 => solve_day!(day05, &input), let output = String::from_utf8(cmd.stdout).unwrap();
6 => solve_day!(day06, &input), println!("----------");
7 => solve_day!(day07, &input), println!("{}| Day {} |{}", ANSI_BOLD, day, ANSI_RESET);
8 => solve_day!(day08, &input), println!("----------");
9 => solve_day!(day09, &input), println!(
10 => solve_day!(day10, &input), "{}",
11 => solve_day!(day11, &input), if !output.is_empty() {
12 => solve_day!(day12, &input), output
13 => solve_day!(day13, &input), } else {
14 => solve_day!(day14, &input), "Not solved.".to_string()
15 => solve_day!(day15, &input), }
16 => solve_day!(day16, &input), );
17 => solve_day!(day17, &input), });
18 => solve_day!(day18, &input),
19 => solve_day!(day19, &input),
20 => solve_day!(day20, &input),
21 => solve_day!(day21, &input),
22 => solve_day!(day22, &input),
23 => solve_day!(day23, &input),
24 => solve_day!(day24, &input),
25 => solve_day!(day25, &input),
_ => println!("day not solved: {}", day),
}
} }