generated from janezicmatej/aoc-template
	feat: create repo from template
This commit is contained in:
		
							
								
								
									
										4
									
								
								.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					[alias]
 | 
				
			||||||
 | 
					scaffold = "run -p scaffold --release --quiet --"
 | 
				
			||||||
 | 
					download = "run -p download --release --quiet --"
 | 
				
			||||||
 | 
					solve = "run --bin"
 | 
				
			||||||
							
								
								
									
										2
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					TOKEN=secret
 | 
				
			||||||
 | 
					YEAR=2024
 | 
				
			||||||
							
								
								
									
										16
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# Generated by Cargo
 | 
				
			||||||
 | 
					# will have compiled files and executables
 | 
				
			||||||
 | 
					debug/
 | 
				
			||||||
 | 
					target/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# These are backup files generated by rustfmt
 | 
				
			||||||
 | 
					**/*.rs.bk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# aoc-template
 | 
				
			||||||
 | 
					# env vars
 | 
				
			||||||
 | 
					.env
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# downloaded inputs
 | 
				
			||||||
 | 
					/data/inputs/*
 | 
				
			||||||
 | 
					!/data/inputs/.keep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										1128
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1128
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										24
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					[workspace.package]
 | 
				
			||||||
 | 
					description = "template for advent of code"
 | 
				
			||||||
 | 
					readme = "README.md"
 | 
				
			||||||
 | 
					version = "48.0.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					license = "MIT"
 | 
				
			||||||
 | 
					authors = ["Matej Janežič <janezic.mj@gmail.com>"]
 | 
				
			||||||
 | 
					repository = "https://git.janezic.dev/janezicmatej/aoc-template.git"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[workspace]
 | 
				
			||||||
 | 
					members = ["utils/download", "utils/scaffold"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "aoc"
 | 
				
			||||||
 | 
					description.workspace = true
 | 
				
			||||||
 | 
					readme.workspace = true
 | 
				
			||||||
 | 
					version.workspace = true
 | 
				
			||||||
 | 
					edition.workspace = true
 | 
				
			||||||
 | 
					license.workspace = true
 | 
				
			||||||
 | 
					authors.workspace = true
 | 
				
			||||||
 | 
					repository.workspace = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2023 Matej Janežič
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
							
								
								
									
										32
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					# Advent-of-Code 2024
 | 
				
			||||||
 | 
					*This is a dumbed down version of [fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust) with some extra features*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Project overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Project structure
 | 
				
			||||||
 | 
					- `data/` :
 | 
				
			||||||
 | 
					    - `examples/`: example files go here; you can push this as test are run in ci
 | 
				
			||||||
 | 
					    - `inputs/`: this directory is gitignored, input files go here
 | 
				
			||||||
 | 
					- `src/` :
 | 
				
			||||||
 | 
					    - `bin/`:
 | 
				
			||||||
 | 
					        - `<day>.rs`: solution files 
 | 
				
			||||||
 | 
					    - `lib.rs`: library entrypoint, reusable code goes here
 | 
				
			||||||
 | 
					    - `template.rs`: contains template code
 | 
				
			||||||
 | 
					- `utils/`: binary packages with convenience scripts structured using cargo workspaces
 | 
				
			||||||
 | 
					- `.env.example`: example dotenv file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Cli
 | 
				
			||||||
 | 
					- `cargo scaffold <day>`: prepare solution files for `day`
 | 
				
			||||||
 | 
					- `cargo download <day>`: download input file for `day`
 | 
				
			||||||
 | 
					- `cargo solve <day>`: run solution against input for `day`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*Run `cargo build --workspace --release` once so scaffold and download packages get compiled, otherwise they will have to be compiled on first run.*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### dotenv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set `TOKEN` to AoC session Cookie
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### FAQ
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### How are your commits numbered in ascending order?
 | 
				
			||||||
 | 
					[https://westling.dev/b/extremely-linear-git](https://westling.dev/b/extremely-linear-git)
 | 
				
			||||||
							
								
								
									
										0
									
								
								data/examples/.keep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								data/examples/.keep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								data/inputs/.keep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								data/inputs/.keep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								src/bin/.keep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/bin/.keep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					pub mod template;
 | 
				
			||||||
							
								
								
									
										56
									
								
								src/template.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/template.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file contains template code.
 | 
				
			||||||
 | 
					 * There is no need to edit this file unless you want to change template functionality.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use std::env;
 | 
				
			||||||
 | 
					use std::fs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const ANSI_ITALIC: &str = "\x1b[3m";
 | 
				
			||||||
 | 
					pub const ANSI_BOLD: &str = "\x1b[1m";
 | 
				
			||||||
 | 
					pub const ANSI_RESET: &str = "\x1b[0m";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use std::fmt::Display;
 | 
				
			||||||
 | 
					use std::time::Duration;
 | 
				
			||||||
 | 
					use std::time::Instant;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn time_solution<T>(func: impl FnOnce(&str) -> Option<T>, input: &str) -> Option<(T, Duration)> {
 | 
				
			||||||
 | 
					    let timer = Instant::now();
 | 
				
			||||||
 | 
					    let result = func(input);
 | 
				
			||||||
 | 
					    let elapsed = timer.elapsed();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result.map(|result| (result, elapsed))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn print_result<T: Display>(func: impl FnOnce(&str) -> Option<T>, input: &str, part: u8) {
 | 
				
			||||||
 | 
					    match time_solution(func, input) {
 | 
				
			||||||
 | 
					        Some((result, elapsed)) => {
 | 
				
			||||||
 | 
					            println!(
 | 
				
			||||||
 | 
					                "{}Part {}{}: {} {}(elapsed: {:.2?}){}",
 | 
				
			||||||
 | 
					                ANSI_BOLD, part, ANSI_RESET, result, ANSI_ITALIC, elapsed, ANSI_RESET
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        None => {
 | 
				
			||||||
 | 
					            println!("{}Part {}{}: not solved.", ANSI_BOLD, part, ANSI_RESET)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[macro_export]
 | 
				
			||||||
 | 
					macro_rules! solution {
 | 
				
			||||||
 | 
					    ($day:expr) => {
 | 
				
			||||||
 | 
					        fn main() {
 | 
				
			||||||
 | 
					            let input = aoc::template::read_file("inputs", $day);
 | 
				
			||||||
 | 
					            aoc::template::print_result(part_one, &input, 1);
 | 
				
			||||||
 | 
					            aoc::template::print_result(part_two, &input, 2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[must_use]
 | 
				
			||||||
 | 
					pub fn read_file(folder: &str, day: u8) -> String {
 | 
				
			||||||
 | 
					    let cwd = env::current_dir().unwrap();
 | 
				
			||||||
 | 
					    let filepath = cwd.join("data").join(folder).join(format!("{day:02}.txt"));
 | 
				
			||||||
 | 
					    let f = fs::read_to_string(filepath);
 | 
				
			||||||
 | 
					    f.expect("could not open input file").trim().to_string()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								utils/download/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								utils/download/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "download"
 | 
				
			||||||
 | 
					description.workspace = true
 | 
				
			||||||
 | 
					readme.workspace = true
 | 
				
			||||||
 | 
					version.workspace = true
 | 
				
			||||||
 | 
					edition.workspace = true
 | 
				
			||||||
 | 
					license.workspace = true
 | 
				
			||||||
 | 
					authors.workspace = true
 | 
				
			||||||
 | 
					repository.workspace = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					reqwest = { version = "0.11.22", features = ["blocking"] }
 | 
				
			||||||
 | 
					dotenvy = "0.15.6"
 | 
				
			||||||
 | 
					pico-args = "0.5.0"
 | 
				
			||||||
							
								
								
									
										64
									
								
								utils/download/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								utils/download/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					use dotenvy::dotenv;
 | 
				
			||||||
 | 
					use reqwest::blocking::Client;
 | 
				
			||||||
 | 
					use reqwest::header;
 | 
				
			||||||
 | 
					use std::{env, fs::OpenOptions, io::Write, process};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn parse_args() -> Result<u8, pico_args::Error> {
 | 
				
			||||||
 | 
					    let mut args = pico_args::Arguments::from_env();
 | 
				
			||||||
 | 
					    args.free_from_str()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let day: u8 = match parse_args() {
 | 
				
			||||||
 | 
					        Ok(day) => day,
 | 
				
			||||||
 | 
					        Err(_) => {
 | 
				
			||||||
 | 
					            eprintln!("Need to specify a day (as integer). example: `cargo download 7`");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    dotenv().ok();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let day_padded = format!("{day:02}");
 | 
				
			||||||
 | 
					    let token = env::var("TOKEN").expect("$TOKEN is not set");
 | 
				
			||||||
 | 
					    let year = env::var("YEAR")
 | 
				
			||||||
 | 
					        .expect("$YEAR is not set")
 | 
				
			||||||
 | 
					        .parse::<u32>()
 | 
				
			||||||
 | 
					        .expect("$YEAR must be a number");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut headers = header::HeaderMap::new();
 | 
				
			||||||
 | 
					    let mut session_header = header::HeaderValue::from_str(format!("session={token}").as_str())
 | 
				
			||||||
 | 
					        .expect("Error building cookie header");
 | 
				
			||||||
 | 
					    session_header.set_sensitive(true);
 | 
				
			||||||
 | 
					    headers.insert(header::COOKIE, session_header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let client = Client::builder().default_headers(headers).build().unwrap();
 | 
				
			||||||
 | 
					    let res = client
 | 
				
			||||||
 | 
					        .get(format!("https://adventofcode.com/{year}/day/{day}/input"))
 | 
				
			||||||
 | 
					        .send()
 | 
				
			||||||
 | 
					        .unwrap()
 | 
				
			||||||
 | 
					        .text()
 | 
				
			||||||
 | 
					        .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let input_path = format!("data/inputs/{day_padded}.txt");
 | 
				
			||||||
 | 
					    let mut file = match OpenOptions::new()
 | 
				
			||||||
 | 
					        .write(true)
 | 
				
			||||||
 | 
					        .create(true)
 | 
				
			||||||
 | 
					        .open(&input_path)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Ok(file) => file,
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create module file: {e}");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match file.write_all(res.as_bytes()) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Downloaded input file \"{}\"", &input_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to write module contents: {e}");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								utils/scaffold/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								utils/scaffold/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "scaffold"
 | 
				
			||||||
 | 
					description.workspace = true
 | 
				
			||||||
 | 
					readme.workspace = true
 | 
				
			||||||
 | 
					version.workspace = true
 | 
				
			||||||
 | 
					edition.workspace = true
 | 
				
			||||||
 | 
					license.workspace = true
 | 
				
			||||||
 | 
					authors.workspace = true
 | 
				
			||||||
 | 
					repository.workspace = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					reqwest = { version = "0.11.22", features = ["blocking"] }
 | 
				
			||||||
 | 
					dotenvy = "0.15.6"
 | 
				
			||||||
 | 
					pico-args = "0.5.0"
 | 
				
			||||||
							
								
								
									
										103
									
								
								utils/scaffold/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								utils/scaffold/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file contains template code.
 | 
				
			||||||
 | 
					 * There is no need to edit this file unless you want to change template functionality.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					use std::{
 | 
				
			||||||
 | 
					    fs::{File, OpenOptions},
 | 
				
			||||||
 | 
					    io::Write,
 | 
				
			||||||
 | 
					    process,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MODULE_TEMPLATE: &str = r#"pub fn part_one(input: &str) -> Option<u32> {
 | 
				
			||||||
 | 
					    None
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn part_two(input: &str) -> Option<u32> {
 | 
				
			||||||
 | 
					    None
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					aoc::solution!(DAY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod tests {
 | 
				
			||||||
 | 
					    use super::*;
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_part_one() {
 | 
				
			||||||
 | 
					        assert_eq!(part_one(&aoc::template::read_file("examples", DAY)), None);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_part_two() {
 | 
				
			||||||
 | 
					        assert_eq!(part_two(&aoc::template::read_file("examples", DAY)), None);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					"#;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn parse_args() -> Result<u8, pico_args::Error> {
 | 
				
			||||||
 | 
					    let mut args = pico_args::Arguments::from_env();
 | 
				
			||||||
 | 
					    args.free_from_str()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn safe_create_file(path: &str) -> Result<File, std::io::Error> {
 | 
				
			||||||
 | 
					    OpenOptions::new().write(true).create_new(true).open(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn create_file(path: &str) -> Result<File, std::io::Error> {
 | 
				
			||||||
 | 
					    OpenOptions::new().write(true).create(true).open(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let day = match parse_args() {
 | 
				
			||||||
 | 
					        Ok(day) => day,
 | 
				
			||||||
 | 
					        Err(_) => {
 | 
				
			||||||
 | 
					            eprintln!("Need to specify a day (as integer). example: `cargo scaffold 7`");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let day_padded = format!("{day:02}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let input_path = format!("data/inputs/{day_padded}.txt");
 | 
				
			||||||
 | 
					    let example_path = format!("data/examples/{day_padded}.txt");
 | 
				
			||||||
 | 
					    let module_path = format!("src/bin/{day_padded}.rs");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut file = match safe_create_file(&module_path) {
 | 
				
			||||||
 | 
					        Ok(file) => file,
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create module file: {e}");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match file.write_all(MODULE_TEMPLATE.replace("DAY", &day.to_string()).as_bytes()) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Created module file \"{}\"", &module_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to write module contents: {e}");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match create_file(&input_path) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Created empty input file \"{}\"", &input_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create input file: {e}");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match create_file(&example_path) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Created empty example file \"{}\"", &example_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create example file: {e}");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println!("---");
 | 
				
			||||||
 | 
					    println!("Type `cargo solve {}` to run your solution.", &day_padded);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user