use std::{vec, fs}; #[derive(Copy, Clone, Debug)] struct Coord(u32, u32, u32); fn main() { let mut numbers: Vec = vec![]; let mut array: Vec> = vec![]; let f = fs::read_to_string("input").unwrap(); // Convert file to array for line in f.lines() { let xline: Vec = line.chars().collect(); array.push(xline); } // No longer mutable let array = array; // Make an array the same size for the purpose of number coord tracking and matching // initialize it with -1 for nothing there let mut numarray: Vec> = vec![vec![-1; array[0].len()]; array.len()]; // Find Numbers let mut num = false; let mut numcoords = Coord(0, 0, 0); let mut yidx = 0; for y in array.clone() { let mut xidx = 0; for x in y { match x.to_string().parse::() { Ok(_) => { // if num is not set, start recording the number if !num { numcoords = Coord(yidx, xidx, 0); num = true; } }, Err(_) => { // if we were making a number if num { num = false; // handle number being at the end of the line // and xidx wraps back to 0 if xidx == 0 { numcoords = Coord(numcoords.0, numcoords.1, (array[0].len() -1) as u32); } else { numcoords = Coord(numcoords.0, numcoords.1, xidx - 1); } numbers.push(range_to_number(numcoords, &array)); // Set numarray coords to the numidx let numidx = numbers.len() - 1; for i in numcoords.1..=numcoords.2 { numarray[numcoords.0 as usize][i as usize] = numidx as i32; } } }, } xidx += 1; } yidx += 1; } // Search for all symbols that are not numbers or '.' and search around them in numarray for anything not -1 const AROUND: [(i8, i8); 8] = [ (0, 1), (1, 1), (1, 0), (-1, 0), (-1, -1), (0, -1), (1, -1), (-1, 1), ]; let mut outvec = vec![]; let mut yidx = 0; for y in array { let mut xidx = 0; for c in y { let ctest = match c.to_string().parse::() { Ok(_) => true, Err(_) => false, }; // if ctest is a number or '.', then continue if ctest || c == '.' { xidx += 1; continue } // Character is a symbol for pos in AROUND { let i = match numarray.get(u32_calc(yidx, pos.0)) { Some(n) => { match n.get(u32_calc(xidx, pos.1)) { Some(n) => n, None => &-1, } }, None => continue }; if i > &-1 { outvec.push(*i) } } xidx += 1; } yidx += 1; } // Get only a single of each number and add them all up outvec.sort(); outvec.dedup_by_key(|i| {*i}); let outvec: Vec = outvec.iter().map(|i| { match numbers.get(*i as usize) { Some(n) => *n, None => 0, } }).collect(); // Add It Up let mut final_num = 0; for x in outvec { final_num += x; } println!("{}", final_num); } fn u32_calc(x: u32, y: i8) -> usize { // nothing should matter if x is greater than 0 if x < 1 && y == -1 { 0 } else { (x as i64 + y as i64) as usize } } fn range_to_number(coords: Coord, array: &Vec>) -> u32 { let mut outstring = "".to_string(); for i in coords.1..=coords.2 { outstring.push(*array.get(coords.0 as usize).unwrap().get(i as usize).unwrap()) } outstring.parse().unwrap() }