Rust Day 1 Optimizations
This commit is contained in:
parent
de2e672007
commit
bfa1b624f8
2 changed files with 49 additions and 39 deletions
|
@ -1,4 +1,4 @@
|
||||||
pub(crate) fn part_1(input: &'static str) -> u64 {
|
pub(crate) fn part_1(input: &'static str) -> u32 {
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
|
@ -6,9 +6,7 @@ pub(crate) fn part_1(input: &'static str) -> u64 {
|
||||||
let first_digit = digits.next().expect("At least 1 digit should be present");
|
let first_digit = digits.next().expect("At least 1 digit should be present");
|
||||||
let last_digit = digits.last().unwrap_or(first_digit);
|
let last_digit = digits.last().unwrap_or(first_digit);
|
||||||
|
|
||||||
format!("{first_digit}{last_digit}")
|
(((first_digit as u32) - ('0' as u32)) * 10) + ((last_digit as u32) - ('0' as u32))
|
||||||
.parse::<u64>()
|
|
||||||
.expect("Two digits should make a number")
|
|
||||||
})
|
})
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +1,64 @@
|
||||||
|
use std::cmp::Reverse;
|
||||||
|
|
||||||
const DIGIT_PATTERNS: [&str; 10] = [
|
const DIGIT_PATTERNS: [&str; 10] = [
|
||||||
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub(crate) fn part_2(input: &'static str) -> u64 {
|
#[cfg_attr(test, derive(Debug))]
|
||||||
|
struct DigitIndices {
|
||||||
|
digit: usize,
|
||||||
|
first_index: usize,
|
||||||
|
last_index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn part_2(input: &'static str) -> usize {
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
let mut digit_indices = DIGIT_PATTERNS
|
let digit_indices = DIGIT_PATTERNS
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(number, pattern)| {
|
.filter_map(|(digit, pattern)| {
|
||||||
let first_index_digit = line.find(&number.to_string());
|
// SAFETY: Generating a char from a number like this is guaranteed to be in ASCII range
|
||||||
let first_index_str = line.find(pattern);
|
let first_index_digit = line
|
||||||
let first_index = match (first_index_str, first_index_digit) {
|
.find(unsafe {
|
||||||
(Some(lhs), Some(rhs)) => Some(usize::min(lhs, rhs)),
|
char::from_u32(digit as u32 + b'0' as u32).unwrap_unchecked()
|
||||||
(None, idx) => idx,
|
})
|
||||||
(idx, None) => idx,
|
.map(Reverse);
|
||||||
};
|
let first_index_str = line.find(pattern).map(Reverse);
|
||||||
|
let Reverse(first_index) = Option::max(first_index_digit, first_index_str)?;
|
||||||
|
|
||||||
let last_index_digit = line.rfind(&number.to_string());
|
// SAFETY: Generating a char from a number like this is guaranteed to be in ASCII range
|
||||||
|
let last_index_digit = line.rfind([unsafe {
|
||||||
|
char::from_u32(digit as u32 + b'0' as u32).unwrap_unchecked()
|
||||||
|
}]);
|
||||||
let last_index_str = line.rfind(pattern);
|
let last_index_str = line.rfind(pattern);
|
||||||
let last_index = match (last_index_str, last_index_digit) {
|
let last_index = Option::max(last_index_digit, last_index_str)?;
|
||||||
(Some(lhs), Some(rhs)) => Some(usize::max(lhs, rhs)),
|
|
||||||
(None, idx) => idx,
|
|
||||||
(idx, None) => idx,
|
|
||||||
};
|
|
||||||
|
|
||||||
(number, first_index, last_index)
|
Some(DigitIndices {
|
||||||
|
digit,
|
||||||
|
first_index,
|
||||||
|
last_index,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
digit_indices.sort_unstable_by(|a, b| match (a.1, b.1) {
|
// SAFETY: Each line is guaranteed to have at least one digit
|
||||||
(Some(_), None) => std::cmp::Ordering::Less,
|
let first_digit = unsafe {
|
||||||
(None, Some(_)) => std::cmp::Ordering::Greater,
|
digit_indices
|
||||||
(None, None) => std::cmp::Ordering::Equal,
|
.iter()
|
||||||
(Some(lhs), Some(rhs)) => lhs.cmp(&rhs),
|
.min_by_key(|val| val.first_index)
|
||||||
});
|
.unwrap_unchecked()
|
||||||
// SAFETY: Slice is guaranteed to be length 10
|
}
|
||||||
let first_digit = unsafe { digit_indices.first().unwrap_unchecked() }.0;
|
.digit;
|
||||||
digit_indices.sort_unstable_by(|a, b| match (a.2, b.2) {
|
let last_digit = unsafe {
|
||||||
(Some(_), None) => std::cmp::Ordering::Less,
|
digit_indices
|
||||||
(None, Some(_)) => std::cmp::Ordering::Greater,
|
.iter()
|
||||||
(None, None) => std::cmp::Ordering::Equal,
|
.max_by_key(|val| val.last_index)
|
||||||
(Some(lhs), Some(rhs)) => rhs.cmp(&lhs),
|
.unwrap_unchecked()
|
||||||
});
|
}
|
||||||
let last_digit = unsafe { digit_indices.first().unwrap_unchecked() }.0;
|
.digit;
|
||||||
format!("{first_digit}{last_digit}")
|
|
||||||
.parse::<u64>()
|
(first_digit * 10) + last_digit
|
||||||
.expect("digits are guaranteed to create a valid number")
|
|
||||||
})
|
})
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue