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
# @see https://old.reddit.com/r/adventofcode/comments/k99rod/sharing_input_data_were_we_requested_not_to/gf2ukkf/?context=3
inputs
!inputs/.keep
/src/inputs
!/src/inputs/.keep

View File

@ -3,7 +3,7 @@ name = "aoc"
version = "0.1.0"
authors = ["Felix Spöttel <1682504+fspoettel@users.noreply.github.com>"]
edition = "2021"
default-run = "aoc"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[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>
# output:
# Created module `src/solutions/day01.rs`
# Created input file `src/inputs/day01.txt`
# Created example file `src/examples/day01.txt`
# Linked new module in `src/main.rs`
# Linked new module in `src/solutions/mod.rs`
# Done! 🎄
# Created module "src/bin/01.rs"
# Created empty input file "src/inputs/01.txt"
# Created empty example file "src/examples/01.txt"
# ---
# 🎄 Type `cargo run --bin 01` to run your solution.
```
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
@ -50,27 +49,26 @@ Every solution file has _unit tests_ referencing the example input file. You can
./scripts/download.sh <day>
# output:
# Invoking `aoc` cli...
# Loaded session cookie from "/home/foo/.adventofcode.session".
# Loaded session cookie from "/home/felix/.adventofcode.session".
# Downloading input for day 1, 2021...
# Saving puzzle input to "/tmp/..."...
# Saving puzzle input to "/tmp/tmp.MBdcAdL9Iw/input"...
# 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.
> 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
```sh
# example: `cargo run 1`
cargo run <day>
# example: `cargo run --bin 01`
cargo run --bin <day>
# output:
# Running `target/debug/aoc 1`
# ----
#
# Running `target/debug/01`
# 🎄 Part 1 🎄
#
# 6 (elapsed: 37.03µs)
@ -78,11 +76,17 @@ cargo run <day>
# 🎄 Part 2 🎄
#
# 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

View File

@ -16,7 +16,7 @@ fi
day=$(echo $1 | sed 's/^0*//');
day_padded=`printf %02d $day`;
filename="day$day_padded";
filename="$day_padded";
input_path="src/inputs/$filename.txt";
tmp_dir=$(mktemp -d);
@ -24,15 +24,9 @@ tmp_file_path="$tmp_dir/input";
aoc download --day $day --file $tmp_file_path;
cat $tmp_file_path > $input_path;
echo "Wrote input to \"$input_path\"...";
cat <<EOF
_==_ _
_,(",)|_|
\/. \-|
__( : )|_ Done!
EOF
echo "---"
echo "🎄 Successfully wrote input to \"$input_path\"!"
# 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

View File

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

View File

@ -1,13 +1,41 @@
use std::env;
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 {
let cwd = env::current_dir().unwrap();
let filepath = cwd
.join("src")
.join(folder)
.join(format!("day{:02}.txt", day));
let filepath = cwd.join("src").join(folder).join(format!("{:02}.txt", day));
let f = fs::read_to_string(filepath);
f.expect("could not open input file")

View File

@ -1,74 +1,26 @@
use crate::solutions::*;
use aoc::read_file;
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!("----");
}};
}
use aoc::{ANSI_BOLD, ANSI_RESET};
use std::process::Command;
fn main() {
let args: Vec<String> = env::args().collect();
let day: u8 = args[1].clone().parse().unwrap();
let input = read_file("inputs", day);
(1..=25).for_each(|day| {
let day = format!("{:02}", day);
match day {
1 => solve_day!(day01, &input),
2 => solve_day!(day02, &input),
3 => solve_day!(day03, &input),
4 => solve_day!(day04, &input),
5 => solve_day!(day05, &input),
6 => solve_day!(day06, &input),
7 => solve_day!(day07, &input),
8 => solve_day!(day08, &input),
9 => solve_day!(day09, &input),
10 => solve_day!(day10, &input),
11 => solve_day!(day11, &input),
12 => solve_day!(day12, &input),
13 => solve_day!(day13, &input),
14 => solve_day!(day14, &input),
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),
}
let cmd = Command::new("cargo")
.args(&["run", "--release", "--bin", &day])
.output()
.unwrap();
let output = String::from_utf8(cmd.stdout).unwrap();
println!("----------");
println!("{}| Day {} |{}", ANSI_BOLD, day, ANSI_RESET);
println!("----------");
println!(
"{}",
if !output.is_empty() {
output
} else {
"Not solved.".to_string()
}
);
});
}