advent_of_code::solution!(1); fn parse(input: &str) -> Vec { input .lines() .filter_map(|l| { let v: Vec<&str> = l.matches(char::is_numeric).collect(); if !v.is_empty() { let tens = v[0].parse::().unwrap() * 10; let ones = v[v.len() - 1].parse::().unwrap(); Some(tens + ones) } else { None } }) .collect() } pub fn part_one(input: &str) -> Option { let lines = parse(input); Some(lines.iter().sum()) } pub fn part_two(input: &str) -> Option { Some(sub_letters_for_digits(input).iter().sum()) } fn char_to_num(c: char) -> Option { 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 { 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 { if c.is_ascii_digit() { char_to_num(c) } else { letter_digit_at(line, index) } } fn sub_letters_for_digits(input: &str) -> Vec { 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::*; #[test] fn test_part_one() { let result = part_one(&advent_of_code::template::read_file("examples", DAY)); assert_eq!(result, Some(142)); } #[test] fn test_part_two() { let result = part_two(&advent_of_code::template::read_file_part( "examples", DAY, 2, )); assert_eq!(result, Some(281)); } }