Complete second part of 2023 day 1
This commit is contained in:
parent
314ef30c27
commit
ea8a68be2a
@ -1,5 +1,7 @@
|
|||||||
# Day 1: Trebuchet?!
|
# Day 1: Trebuchet?!
|
||||||
|
|
||||||
|
## Part 1
|
||||||
|
|
||||||
Something is wrong with global snow production, and you've been selected to take a look.
|
Something is wrong with global snow production, and you've been selected to take a look.
|
||||||
The Elves have even given you a map; on it, they've used stars to mark the top fifty
|
The Elves have even given you a map; on it, they've used stars to mark the top fifty
|
||||||
locations that are likely to be having problems.
|
locations that are likely to be having problems.
|
||||||
@ -40,3 +42,24 @@ In this example, the calibration values of these four lines are 12, 38, 15, and
|
|||||||
Adding these together produces 142.
|
Adding these together produces 142.
|
||||||
|
|
||||||
Consider your entire calibration document. **What is the sum of all of the calibration values?**
|
Consider your entire calibration document. **What is the sum of all of the calibration values?**
|
||||||
|
|
||||||
|
## Part 2
|
||||||
|
|
||||||
|
Your calculation isn't quite right. It looks like some of the digits are actually spelled out
|
||||||
|
with letters: one, two, three, four, five, six, seven, eight, and nine also count as valid "digits".
|
||||||
|
|
||||||
|
Equipped with this new information, you now need to find the real first and last digit on each line. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
two1nine
|
||||||
|
eightwothree
|
||||||
|
abcone2threexyz
|
||||||
|
xtwone3four
|
||||||
|
4nineeightseven2
|
||||||
|
zoneight234
|
||||||
|
7pqrstsixteen
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces *281*.
|
||||||
|
|
||||||
|
**What is the sum of all of the calibration values?**
|
||||||
|
@ -1,24 +1,78 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
fn word_to_digit(s: &str) -> char {
|
||||||
fn get_lines(raw: &str) -> Vec<Vec<char>> {
|
match s {
|
||||||
raw.split('\n').map(|line| line.chars().collect()).collect()
|
"one" | "1" => '1',
|
||||||
|
"two" | "2" => '2',
|
||||||
|
"three" | "3" => '3',
|
||||||
|
"four" | "4" => '4',
|
||||||
|
"five" | "5" => '5',
|
||||||
|
"six" | "6" => '6',
|
||||||
|
"seven" | "7" => '7',
|
||||||
|
"eight" | "8" => '8',
|
||||||
|
"nine" | "9" => '9',
|
||||||
|
_ => '0',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_lines(raw: &Vec<Vec<char>>) -> Vec<VecDeque<char>> {
|
fn line_to_digits(line: &str) -> VecDeque<char> {
|
||||||
raw.iter()
|
let numbers = Vec::from([
|
||||||
.map(|line| {
|
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "1", "2", "3", "4",
|
||||||
let line: Vec<char> = line
|
"5", "6", "7", "8", "9", "0",
|
||||||
.into_iter()
|
]);
|
||||||
.filter(|c| c.is_digit(10))
|
|
||||||
.map(|c| c.to_owned())
|
let mut digits: VecDeque<char> = VecDeque::new();
|
||||||
|
|
||||||
|
// Find the numbers/number words in the line
|
||||||
|
let first_matches: Vec<(usize, &str)> = numbers
|
||||||
|
.iter()
|
||||||
|
.map(|search| line.match_indices(*search).collect::<Vec<(usize, &str)>>())
|
||||||
|
.filter(|search| search.len() > 0)
|
||||||
|
.map(|search| search[0])
|
||||||
.collect();
|
.collect();
|
||||||
VecDeque::from(line)
|
|
||||||
|
let last_matches: Vec<(usize, &str)> = numbers
|
||||||
|
.iter()
|
||||||
|
.map(|search| line.rmatch_indices(*search).collect::<Vec<(usize, &str)>>())
|
||||||
|
.filter(|search| search.len() > 0)
|
||||||
|
.map(|search| search[0])
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Find the matches of the string in order,
|
||||||
|
// and return the cleaned up matches
|
||||||
|
for min in 0..line.len() {
|
||||||
|
if let Some(m) = first_matches.iter().find(|m| m.0 == min) {
|
||||||
|
digits.push_back(word_to_digit(m.1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for max in (0..line.len()).rev() {
|
||||||
|
if let Some(m) = last_matches.iter().find(|m| m.0 == max) {
|
||||||
|
digits.push_back(word_to_digit(m.1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
digits
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_lines(raw: &str, words: bool) -> Vec<VecDeque<char>> {
|
||||||
|
raw.split('\n')
|
||||||
|
.map(|line| {
|
||||||
|
if words {
|
||||||
|
line_to_digits(line)
|
||||||
|
} else {
|
||||||
|
line.chars()
|
||||||
|
.filter(|c| c.is_digit(10))
|
||||||
|
.collect::<VecDeque<char>>()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_values(raw: &mut Vec<VecDeque<char>>) -> Vec<usize> {
|
fn get_values(raw: &mut Vec<VecDeque<char>>) -> Vec<usize> {
|
||||||
raw.iter_mut()
|
raw.iter_mut()
|
||||||
|
.filter(|line| line.len() > 0)
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
let first = match line.pop_front() {
|
let first = match line.pop_front() {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
@ -41,9 +95,37 @@ fn sum(raw: Vec<usize>) -> usize {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let file_str = include_str!("input.txt");
|
let file_str = include_str!("input.txt");
|
||||||
let lines = get_lines(file_str);
|
let mut lines = get_lines(file_str, false);
|
||||||
let mut lines = filter_lines(&lines);
|
|
||||||
let values = get_values(&mut lines);
|
let values = get_values(&mut lines);
|
||||||
|
|
||||||
println!("Total: {}", sum(values));
|
println!("Part 1 Total: {}", sum(values));
|
||||||
|
|
||||||
|
let mut lines = get_lines(file_str, true);
|
||||||
|
let values = get_values(&mut lines);
|
||||||
|
|
||||||
|
println!("Part 2 Total: {}", sum(values));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_first_result() {
|
||||||
|
let file_str = include_str!("input.txt");
|
||||||
|
let mut lines = get_lines(file_str, false);
|
||||||
|
let values = get_values(&mut lines);
|
||||||
|
|
||||||
|
assert_eq!(sum(values), 54990);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_second_example_values() {
|
||||||
|
let example = "two1nine\neightwothree\nabcone2threexyz\nxtwone3four\n4nineeightseven2\nzoneight234\n7pqrstsixteen";
|
||||||
|
let mut lines = get_lines(example, true);
|
||||||
|
let values = get_values(&mut lines);
|
||||||
|
|
||||||
|
assert_eq!(values, Vec::from([29, 83, 13, 24, 42, 14, 76]));
|
||||||
|
assert_eq!(sum(values), 281);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user