feat(day01): day 1 solutions and initial commit
This commit is contained in:
7 files changed
+1243
No files matched your search
@@ -0,0 +1,93 @@
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::utils::digit_value;
|
||||
use crate::Day;
|
||||
|
||||
inventory::submit! {
|
||||
Day { number: 1, run }
|
||||
}
|
||||
|
||||
fn first_and_last_digit(s: &str) -> usize {
|
||||
let first = s
|
||||
.chars()
|
||||
.find(|c| c.is_ascii_digit())
|
||||
.unwrap()
|
||||
.to_digit(10)
|
||||
.unwrap() as usize;
|
||||
let last = s
|
||||
.chars()
|
||||
.rfind(|c| c.is_ascii_digit())
|
||||
.unwrap()
|
||||
.to_digit(10)
|
||||
.unwrap() as usize;
|
||||
|
||||
first * 10 + last
|
||||
}
|
||||
|
||||
fn day01_part1(input: &str) -> usize {
|
||||
input.lines().map(first_and_last_digit).sum()
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref REGEX: Regex =
|
||||
Regex::new(r"(?P<digit>zero|one|two|three|four|five|six|seven|eight|nine|\d)").unwrap();
|
||||
}
|
||||
|
||||
fn first_and_last_digit_regex(s: &str) -> usize {
|
||||
let mut first_start = usize::MAX;
|
||||
let mut last_end = 0;
|
||||
let mut first_digit = String::new();
|
||||
let mut last_digit = String::new();
|
||||
|
||||
for (index, _) in s.char_indices() {
|
||||
if let Some(mat) = REGEX.find(&s[index..]) {
|
||||
let match_start = index + mat.start();
|
||||
let match_end = index + mat.end();
|
||||
|
||||
if match_start < first_start {
|
||||
first_start = match_start;
|
||||
first_digit = mat.as_str().to_string();
|
||||
}
|
||||
if match_end > last_end {
|
||||
last_end = match_end;
|
||||
last_digit = mat.as_str().to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let first_digit_val = digit_value(&first_digit);
|
||||
let last_digit_val = digit_value(&last_digit);
|
||||
|
||||
first_digit_val * 10 + last_digit_val
|
||||
}
|
||||
|
||||
fn day01_part2(input: &str) -> usize {
|
||||
input.lines().map(first_and_last_digit_regex).sum()
|
||||
}
|
||||
|
||||
const INPUT: &str = include_str!("../data/day01.dat");
|
||||
|
||||
fn run() {
|
||||
println!("{}", day01_part1(INPUT));
|
||||
println!("{}", day01_part2(INPUT));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_day01_part1() {
|
||||
let input = "1abc2\npqr3stu8vwx\na1b2c3d4e5f\ntreb7uchet";
|
||||
assert_eq!(day01_part1(input), 142);
|
||||
assert_eq!(day01_part1(INPUT), 54597);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_day01_part2() {
|
||||
let input="two1nine\neightwothree\nabcone2threexyz\nxtwone3four\n4nineeightseven2\nzoneight234\n7pqrstsixteen";
|
||||
assert_eq!(day01_part2(input), 281);
|
||||
assert_eq!(day01_part2(INPUT), 54504);
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
pub mod utils;
|
||||
|
||||
// HACK: include build.rs generated file which declares modules for every dayXX.rs file found
|
||||
include!("days_mod.inc");
|
||||
|
||||
// a struct for a single day's implementation, includes its day number and the function to run
|
||||
#[derive(Debug)]
|
||||
pub struct Day {
|
||||
pub number: usize,
|
||||
pub run: fn(),
|
||||
}
|
||||
|
||||
// collects all the days registered in the inventory
|
||||
inventory::collect!(Day);
|
||||
|
||||
// main takes one argument: 'all' or a day number
|
||||
//
|
||||
// if no argument is provided, runs the latest day
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
match args.get(1).map(String::as_str) {
|
||||
Some("all") => run_all_days(),
|
||||
Some(day_str) if day_str.parse::<usize>().is_ok() => {
|
||||
run_specific_day(day_str.parse::<usize>().unwrap())
|
||||
}
|
||||
None => run_latest_day(),
|
||||
_ => println!("Invalid input. Please specify a day or 'all'."),
|
||||
}
|
||||
}
|
||||
|
||||
// runs the day's function, if it exists
|
||||
fn run_day(day_option: Option<&Day>) {
|
||||
match day_option {
|
||||
Some(day_module) => {
|
||||
println!("Running Day: {}", day_module.number);
|
||||
(day_module.run)();
|
||||
}
|
||||
None => println!("Day is not implemented yet."),
|
||||
}
|
||||
}
|
||||
|
||||
// runs the day with the given number
|
||||
fn run_specific_day(day: usize) {
|
||||
let day_module = inventory::iter::<Day>().find(|d| d.number == day);
|
||||
run_day(day_module);
|
||||
}
|
||||
|
||||
// runs all the days in the inventory
|
||||
fn run_all_days() {
|
||||
for day_module in inventory::iter::<Day>() {
|
||||
run_day(Some(day_module));
|
||||
}
|
||||
}
|
||||
|
||||
// run the day in the inventory with the highest number
|
||||
fn run_latest_day() {
|
||||
let latest_day = inventory::iter::<Day>().max_by_key(|d| d.number);
|
||||
run_day(latest_day);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#[inline]
|
||||
pub fn digit_value(matched: &str) -> usize {
|
||||
match matched {
|
||||
"1" | "one" => 1,
|
||||
"2" | "two" => 2,
|
||||
"3" | "three" => 3,
|
||||
"4" | "four" => 4,
|
||||
"5" | "five" => 5,
|
||||
"6" | "six" => 6,
|
||||
"7" | "seven" => 7,
|
||||
"8" | "eight" => 8,
|
||||
"9" | "nine" => 9,
|
||||
"0" | "zero" => 0,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user