Code review/Idiomatic Rust (Advent of Code)

New Rustacean here.
I try to learn and grasp Rust idioms by solving Advent of Code puzzle.

WARNING Spoiler: This post contains spoiler for Advent Of Code 2018 - day 01!

Short description part one:
The first part consists in parsing a list of integers (one for each line) and sum them.
example: "1\n2\n3" => 6

Short description part two:
The second part consists in parsing the same list of integers, add them one by one (repeating endlessly if necessary), and find the first number appearing twice.
example: "1\n2\n-2" => 1

Full puzzle description and full code implementation is available at AoC_2018_01

I solved the puzzle and i would like to get a code review of my solution. I am interested in idiomatic Rust.

My solutions:

/// Result type
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

/// Solution for puzzle part one.
pub fn part_one(input: &str) -> Result<i32> {
    let frequency = input
        .trim()
        .lines()
        .filter_map(|x| x.parse::<i32>().ok())
        .sum();
    Ok(frequency)
}

/// Solution for puzzle part two.
pub fn part_two(input: &str) -> Result<i32> {
    let mut iter = input.trim().lines().cycle();
    let mut frequency = 0;
    let mut set = HashSet::new();
    set.insert(frequency);
    loop {
        let change = iter.next().unwrap().parse::<i32>().unwrap();
        frequency += change;
        if set.contains(&frequency) {
            break Ok(frequency);
        } else {
            set.insert(frequency);
        }
    }
}

Thanks for your help.

Both solutions seem fine to me.

If you are into immutability, you could simplify the second one somewhat using the standard try_fold() iterator method:

pub fn part_two(input: &str) -> Result<i32> {
    let r = input
        .trim()
        .lines()
        .cycle()
        .try_fold((HashSet::new(), 0), |(mut set, frequency), s| {
            if set.contains(&frequency) {
                Err((set, frequency))
            } else {
                let change = s.parse::<i32>().unwrap();
                set.insert(frequency);
                Ok((set, frequency + change))
            }
        });

    Ok(r.unwrap_err().1)
}

If you like eta-reduction, but not the turbofish, you might replace the filter_map() part in the first one with

.map(i32::from_str)
.filter_map(Result::ok)

But now that's really a tiny detail, and viewing either modification as an improvement or a complication will ultimately depend on your taste.

Thanks for your answer, I never used try_fold need to dive in the documentation. Thanks for your not so tiny detail :grinning:

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.