Spyke

Replies

Comment on

🌟 - 2023 DAY 6 SOLUTIONS -🌟

Rust

Feedback welcome! Feel like I'm getting the hand of Rust more and more.

use regex::Regex;
pub fn part_1(input: &str) {
    let lines: Vec<&str> = input.lines().collect();
    let time_data = number_string_to_vec(lines[0]);
    let distance_data = number_string_to_vec(lines[1]);

    // Zip time and distance into a single iterator
    let data_iterator = time_data.iter().zip(distance_data.iter());

    let mut total_possible_wins = 1;
    for (time, dist_req) in data_iterator {
        total_possible_wins *= calc_possible_wins(*time, *dist_req)
    }
    println!("part possible wins: {:?}", total_possible_wins);
}

pub fn part_2(input: &str) {
    let lines: Vec<&str> = input.lines().collect();
    let time_data = number_string_to_vec(&lines[0].replace(" ", ""));
    let distance_data = number_string_to_vec(&lines[1].replace(" ", ""));

    let total_possible_wins = calc_possible_wins(time_data[0], distance_data[0]);
    println!("part 2 possible wins: {:?}", total_possible_wins);
}

pub fn calc_possible_wins(time: u64, dist_req: u64) -> u64 {
    let mut ways_to_win: u64 = 0;

    // Second half is a mirror of the first half, so only calculate first part
    for push_time in 1..=time / 2 {
        // If a push_time crosses threshold the following ones will too so break loop
        if push_time * (time - push_time) > dist_req {
            // There are (time+1) options (including 0).
            // Subtract twice the minimum required push time, also removing the longest push times
            ways_to_win += time + 1 - 2 * push_time;
            break;
        }
    }
    ways_to_win
}

fn number_string_to_vec(input: &str) -> Vec {
    let regex_number = Regex::new(r"\d+").unwrap();
    let numbers: Vec = regex_number
        .find_iter(input)
        .filter_map(|m| m.as_str().parse().ok())
        .collect();
    numbers
}