refactor(day01): more idiomatic, cleaner, optimal (because fun!)

This commit is contained in:
swaits committed 2023-12-01 19:45:00 -07:00
1 parent 16d8a196e5
commit 34af78c853
1 file changed
+23 -39
+23 -39
View File
@@ -9,23 +9,18 @@ inventory::submit! {
}
fn first_and_last_digit(s: &str) -> usize {
// Find the first character in the string that is an ASCII digit
let first = s
.chars()
.find(|c| c.is_ascii_digit()) // Use find to get an Option containing the first digit character
.unwrap() // Unwrap the Option, panicking if no digit is found
.to_digit(10) // Convert the character to a digit in base 10
.unwrap() as usize; // Convert the digit to a usize
// Find the first ASCII digit in the string
let first = s.chars().filter_map(|c| c.to_digit(10)).next().unwrap() as usize; // Safe to use unwrap as a digit is always present
// Find the last character in the string that is an ASCII digit
// Find the last ASCII digit in the string
let last = s
.chars()
.rfind(|c| c.is_ascii_digit()) // Use rfind to get an Option containing the last digit character
.unwrap() // Unwrap the Option, panicking if no digit is found
.to_digit(10) // Convert the character to a digit in base 10
.unwrap() as usize; // Convert the digit to a usize
.rev() // Reverse the iteration for the last digit
.filter_map(|c| c.to_digit(10))
.next()
.unwrap() as usize; // Safe to use unwrap here as well
// Return the result
// Combine the first and last digits to form a new number
first * 10 + last
}
@@ -35,34 +30,23 @@ lazy_static! {
}
fn first_and_last_digit_regex(s: &str) -> usize {
// Initialize variables to keep track of the positions and values of the first and last digits.
let mut first_start = usize::MAX;
let mut last_end = 0;
let mut first_digit = String::new();
let mut last_digit = String::new();
// Find the first digit in the string by testing against each sice from [0..] to [n-1..]
let first_digit = s
.char_indices()
.find_map(|(index, _)| REGEX.find(&s[index..]).map(|mat| mat.as_str().to_string()))
.unwrap(); // Safe to use unwrap because a digit is always expected
// Iterate over each character index in the string.
for (index, _) in s.char_indices() {
// Check if there is a digit at the current index or beyond.
if let Some(mat) = REGEX.find(&s[index..]) {
// Calculate the start and end positions of the matched digit.
let match_start = index + mat.start();
let match_end = index + mat.end();
// Iterate from the end of the string, checking each slice for the last match
let last_digit = s
.char_indices()
.rev()
.find_map(|(index, _)| {
// Check if the slice from this index to the end of the string matches the regex
REGEX.find(&s[index..]).map(|mat| mat.as_str().to_string())
})
.unwrap(); // Safe to use unwrap as a digit is always expected
// If the current match starts before any previously found digit, it's the new first digit.
if match_start < first_start {
first_start = match_start;
first_digit = mat.as_str().to_string();
}
// If the current match ends after any previously found digit, it's the new last digit.
if match_end > last_end {
last_end = match_end;
last_digit = mat.as_str().to_string();
}
}
}
// Convert the first and last digit strings to their numeric values and return the result
// Convert the found digits to numbers and calculate the result
digit_value(&first_digit) * 10 + digit_value(&last_digit)
}