1
0
Fork 0
advent-of-code/2023/src/day01.rs

138 lines
3.3 KiB
Rust

use aoc_runner_derive::aoc;
fn parse(input: &str) -> Vec<u32> {
input
.lines()
.filter_map(|l| {
let v: Vec<&str> = l.matches(char::is_numeric).collect();
if !v.is_empty() {
let tens = v[0].parse::<u32>().unwrap() * 10;
let ones = v[v.len() - 1].parse::<u32>().unwrap();
Some(tens + ones)
} else {
None
}
})
.collect()
}
#[aoc(day1, part1)]
fn part1_sum(input: &str) -> u32 {
let lines = parse(input);
lines.iter().sum()
}
#[aoc(day1, part2)]
fn part2_sum(input: &str) -> u32 {
sub_letters_for_digits(input).iter().sum()
}
fn char_to_num(c: char) -> Option<u32> {
match c {
'0' => Some(0),
'1' => Some(1),
'2' => Some(2),
'3' => Some(3),
'4' => Some(4),
'5' => Some(5),
'6' => Some(6),
'7' => Some(7),
'8' => Some(8),
'9' => Some(9),
_ => None,
}
}
const DIGITS: [&'static str; 10] = [
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
];
fn letter_digit_at(line: &str, index: usize) -> Option<u32> {
for (dindex, d) in DIGITS.iter().enumerate() {
if index + d.len() > line.len() {
continue;
}
let index2 = index + d.len();
let substring: &str = line[index..index2].as_ref();
if *d == substring {
return Some(dindex as u32);
}
}
None
}
fn digit_for_char(line: &str, index: usize, c: char) -> Option<u32> {
if c.is_ascii_digit() {
char_to_num(c)
} else {
letter_digit_at(line, index)
}
}
fn sub_letters_for_digits(input: &str) -> Vec<u32> {
input
.lines()
.filter_map(|line| {
if !line.is_empty() {
let mut first_digit = 0;
let mut second_digit = 0;
for (index, c) in line.chars().enumerate() {
if let Some(digit) = digit_for_char(line, index, c) {
first_digit = digit;
break;
}
}
for (index, c) in line.chars().rev().enumerate() {
if let Some(digit) = digit_for_char(line, line.len() - index - 1, c) {
second_digit = digit;
break;
}
}
let num = first_digit * 10 + second_digit;
Some(num)
} else {
None
}
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
const SAMPLE_DATA: &'static str = r#"
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
"#;
#[test]
fn sample_data() {
let expected = [12, 38, 15, 77];
let data = parse(SAMPLE_DATA);
assert_eq!(data, expected);
let part1 = part1_sum(SAMPLE_DATA);
assert_eq!(part1, 142);
}
const SAMPLE_DATA2: &'static str = r#"
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen
"#;
#[test]
fn sample_data_part2() {
let data = sub_letters_for_digits(SAMPLE_DATA2);
assert_eq!(data, [29, 83, 13, 24, 42, 14, 76]);
let part2 = part2_sum(SAMPLE_DATA2);
assert_eq!(part2, 281);
}
}