Untitled

 avatar
unknown
rust
2 years ago
8.4 kB
6
Indexable
use std::str::Split;

const ROW_LENGTH: usize = 140;
const ROW_COUNT: usize = 140;

pub fn day3(data: String){
    let mut lines = data.split("\n");
    let mut slots = get_slots(lines);

    let mut num_finished: bool = false;
    let mut current_num: Vec<Slot> = Vec::new();
    let mut gears: Vec<GearConnection> = Vec::new();
    let mut result = 0;
    let mut gear_score: i32 = 0;

    for y in 0..ROW_COUNT{
        for x in 0..ROW_LENGTH{
            let slot = slots[get_idx(x, y)];

            // Not currently building a number
            if !slot.is_num && num_finished {
                continue;
            }
            else if !slot.is_num && !num_finished{
                num_finished = true;
                let connected = is_connected_number(&current_num, &slots);
                let gear_connection = is_connected_gear(&current_num, &slots);
                let mut number = 0;
                if connected{
                    let mut count = current_num.len();
                    
                    for s in current_num.clone(){
                        match count {
                            3 => {
                                number += s.number * 100;
                            }
                            2 => {
                                number += s.number * 10;
                            }
                            1 => {
                                number += s.number;
                            }
                            _ => {}
                        }
                        count -= 1;
                    }
                    result += number;
                    
                }

                if gear_connection.0 {
                    let mut found = false;
                    for mut g in &mut gears{
                        if g.gear.x == gear_connection.1 && g.gear.y == gear_connection.2{
                            g.connected_nums.push(number);
                            found = true;
                        }
                    }
                    if !found{
                        let mut g = GearConnection { gear: slots[get_idx(gear_connection.1, gear_connection.2)], connected_nums: Vec::new(), ratio: 0 };
                        g.connected_nums.push(number);
                        gears.push(g);
                    }
                }
                current_num.clear();
            }
            else{
                current_num.push(slot.clone());
                num_finished = false;
            }

        }
    }
    println!("Part 1 Result: {result}");

    for mut gear in gears{
        if gear.connected_nums.len() == 2{
            gear.ratio = gear.connected_nums[0] * gear.connected_nums[1];
            gear_score += gear.ratio;
        }
    }

    println!("Part 2 Result: {gear_score}");
}

struct GearConnection{
    gear: Slot,
    connected_nums: Vec<i32>,
    ratio: i32,
}


fn is_connected_gear(number: &Vec<Slot>, slots: &Vec<Slot>) -> (bool, usize, usize){
    for n in number{
        if n.x != 0{
            // Left
            if slots[get_idx(n.x - 1, n.y)].is_gear{
                return (true, n.x - 1, n.y);
            }
            // Top left
            if n.y != 0 {
                if slots[get_idx(n.x - 1, n.y - 1)].is_gear{
                    return (true, n.x - 1, n.y - 1);
                }
            }
            // Bot left
            if n.y != ROW_LENGTH-1 {
                if slots[get_idx(n.x - 1, n.y + 1)].is_gear{
                    return (true, n.x - 1, n.y + 1);
                }
            }
        }
        if n.x != ROW_LENGTH {
            // Right
            if slots[get_idx(n.x + 1, n.y)].is_gear{
                return (true, n.x + 1, n.y);
            }
            // Top right
            if n.y != 0 {
                if slots[get_idx(n.x + 1, n.y - 1)].is_gear{
                    return (true, n.x + 1, n.y - 1);
                }
            }
            // Bot right
            if n.y != ROW_LENGTH-1 {
                if slots[get_idx(n.x + 1, n.y + 1)].is_gear{
                    return (true, n.x + 1, n.y + 1);
                }
            }
        }

        if n.y != 0 {
            // Top
            if slots[get_idx(n.x, n.y - 1)].is_gear{
                return (true, n.x, n.y - 1);
            }
        }
        if n.y != ROW_COUNT-1 {
            // Bot
            if slots[get_idx(n.x, n.y + 1)].is_gear{
                return (true, n.x, n.y + 1);
            }
        }
       
    }

    return (false, 0, 0);
}


fn is_connected_number(number: &Vec<Slot>, slots: &Vec<Slot>) -> bool{
    let mut connected = false;

    for n in number{
        if n.x != 0{
            // Left
            if !slots[get_idx(n.x - 1, n.y)].is_num && !slots[get_idx(n.x - 1, n.y)].is_blank{
                connected = true;
            }
            // Top left
            if n.y != 0 {
                if !slots[get_idx(n.x - 1, n.y - 1)].is_num && !slots[get_idx(n.x - 1, n.y - 1)].is_blank{
                    connected = true;
                }
            }
            // Bot left
            if n.y != ROW_LENGTH-1 {
                if !slots[get_idx(n.x - 1, n.y + 1)].is_num && !slots[get_idx(n.x - 1, n.y + 1)].is_blank{
                    connected = true;
                }
            }
        }
        if n.x != ROW_LENGTH {
            // Right
            if !slots[get_idx(n.x + 1, n.y)].is_num && !slots[get_idx(n.x + 1, n.y)].is_blank{
                connected = true;
            }
            // Top right
            if n.y != 0 {
                if !slots[get_idx(n.x + 1, n.y - 1)].is_num && !slots[get_idx(n.x + 1, n.y - 1)].is_blank{
                    connected = true;
                }
            }
            // Bot right
            if n.y != ROW_LENGTH-1 {
                if !slots[get_idx(n.x + 1, n.y + 1)].is_num && !slots[get_idx(n.x + 1, n.y + 1)].is_blank{
                    connected = true;
                }
            }
        }

        if n.y != 0 {
            // Top
            if !slots[get_idx(n.x, n.y - 1)].is_num && !slots[get_idx(n.x, n.y - 1)].is_blank{
                connected = true;
            }
        }
        if n.y != ROW_COUNT-1 {
            // Bot
            if !slots[get_idx(n.x, n.y + 1)].is_num && !slots[get_idx(n.x, n.y + 1)].is_blank{
                connected = true;
            }
        }
       
    }

    return connected;
}


fn get_slots(lines: Split<&str>) -> Vec<Slot>{
    let mut slots: Vec<Slot> = Vec::new();

    for (y, line) in lines.enumerate(){
        for (x, symbol) in line.chars().enumerate(){
            if symbol.is_ascii_digit() {
                let slot = Slot{
                    x,
                    y,
                    is_num: true,
                    is_blank: false,
                    number: symbol.to_digit(10).unwrap() as i32,
                    is_gear: false,
                };
                slots.push(slot);
                continue;
            }
            else if symbol != '.' {
                let mut gear = false;
                if symbol == '*' {
                    gear = true;
                }
                let slot = Slot{
                    x,
                    y,
                    is_num: false,
                    is_blank: false,
                    number: -1,
                    is_gear: gear,
                };
                slots.push(slot);
                continue;
            }
            else{
                let slot = Slot{
                    x,
                    y,
                    is_num: false,
                    is_blank: true,
                    number: -1,
                    is_gear: false,
                };
                slots.push(slot);
                continue;
            }
        }
    }

    return slots;
}

fn get_idx(x: usize, y: usize) -> usize{
    return (y * ROW_LENGTH) + x;
}


#[derive(Clone)]
#[derive(Debug, Copy)]
struct Slot {
    x: usize,
    y: usize,
    is_num: bool,
    is_blank: bool,
    number: i32,
    is_gear: bool,
}
Editor is loading...
Leave a Comment