2023-12-29: Learning Rust through Advent of Code
I completed day one of the 2023 advent of code in rust to try learning the language.
The main reason I’m interested in rust is because I’m happy being a python developer, and see a trend of rust being used to create durable “cores” for python projects as seen in in pydantic 2.0 and ruff. A synthesis of the two language seems like the best of two worlds since python truly is a joy to write. Plus I’d like to explore embedded programming in rust.
Completing the challenge took me longer than I would have liked, even with ChatGPT help. I started by generating a list of digits and replacing the values, but this missed strings like "threeight" -> "38"
where eight
would be matched to 8
when finding the last digit. So I started coding in anger and made a really dumb solution where I hardcoded all the number matches and reversed the string. It worked and that’s all I really wanted.
From here on I’d like to see how I can reduce the memory footprint and runtime as a practice in benchmarking software. How would things be improved by using &str
instead of String
? Does using u8
vs u32
where appropriate actually do anything?
Enjoy the solution below.
use crate::adventofcode::utils::get_aoc_input;
use std::error::Error;
fn walk_and_find_digit(input: String, backward: bool) -> u32 {
let mut current_str: String = input;
if backward {
current_str = current_str.chars().rev().collect();
}
while !current_str.is_empty() {
for &(word, digit) in NUMBER_WORDS.iter() {
let match_word: String;
if backward {
match_word = word.chars().rev().collect();
} else {
match_word = word.to_string()
}
if current_str.starts_with(&match_word) {
return digit;
}
}
current_str = (¤t_str[1..]).to_string()
}
0
}
static NUMBER_WORDS: &[(&str, u32)] = &[
("1", 1),
("2", 2),
("3", 3),
("4", 4),
("5", 5),
("6", 6),
("7", 7),
("8", 8),
("9", 9),
("one", 1),
("two", 2),
("three", 3),
("four", 4),
("five", 5),
("six", 6),
("seven", 7),
("eight", 8),
("nine", 9),
];
/// Given a string, convert any english words in the strings into numbers.
/// Ie, "twone" -> "2ne"
///
pub fn p2() -> Result<u32, Box<dyn Error>> {
let input_lines = get_aoc_input(2023, 1)?;
let mut total_sum: u32 = 0;
for line in input_lines {
let first_digit = walk_and_find_digit(line.clone(), false);
let last_digit = walk_and_find_digit(line.clone(), true);
let computed_number = first_digit * 10 + last_digit;
println!(
"{}: {} {} -> {}",
line, first_digit, last_digit, computed_number
);
total_sum += computed_number;
}
println!("P2 Total sum of calibration values: {}", total_sum);
if total_sum != 55130 {
panic!("P2 FAILED")
}
Ok(total_sum)
}
todo: add more css padding on the code block above 👆