day3: problem 1 solution
This commit is contained in:
		
							
								
								
									
										161
									
								
								3/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								3/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::{BufRead, BufReader, Lines};
 | 
			
		||||
 | 
			
		||||
// --- Day 3: Gear Ratios ---
 | 
			
		||||
 | 
			
		||||
// You and the Elf eventually reach a gondola lift station; he says the gondola lift
 | 
			
		||||
// will take you up to the water source, but this is as far as he can bring you. You go
 | 
			
		||||
// inside.
 | 
			
		||||
 | 
			
		||||
// It doesn't take long to find the gondolas, but there seems to be a problem: they're
 | 
			
		||||
// not moving.
 | 
			
		||||
 | 
			
		||||
// "Aaah!"
 | 
			
		||||
 | 
			
		||||
// You turn around to see a slightly-greasy Elf with a wrench and a look of surprise.
 | 
			
		||||
// "Sorry, I wasn't expecting anyone! The gondola lift isn't working right now; it'll
 | 
			
		||||
// still be a while before I can fix it." You offer to help.
 | 
			
		||||
 | 
			
		||||
// The engineer explains that an engine part seems to be missing from the engine, but
 | 
			
		||||
// nobody can figure out which one. If you can add up all the part numbers in the engine
 | 
			
		||||
// schematic, it should be easy to work out which part is missing.
 | 
			
		||||
 | 
			
		||||
// The engine schematic (your puzzle input) consists of a visual representation of the
 | 
			
		||||
// engine. There are lots of numbers and symbols you don't really understand, but
 | 
			
		||||
// apparently any number adjacent to a symbol, even diagonally, is a "part number" and
 | 
			
		||||
// should be included in your sum. (Periods (.) do not count as a symbol.)
 | 
			
		||||
 | 
			
		||||
// Here is an example engine schematic:
 | 
			
		||||
 | 
			
		||||
// 467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592.....
 | 
			
		||||
// ......755. ...$.*.... .664.598..
 | 
			
		||||
 | 
			
		||||
// In this schematic, two numbers are not part numbers because they are not adjacent to
 | 
			
		||||
// a symbol: 114 (top right) and 58 (middle right). Every other number is adjacent to a
 | 
			
		||||
// symbol and so is a part number; their sum is 4361.
 | 
			
		||||
 | 
			
		||||
// BOILERPLATE
 | 
			
		||||
type InputIter = Lines<BufReader<File>>;
 | 
			
		||||
 | 
			
		||||
fn get_input() -> InputIter {
 | 
			
		||||
    let f = File::open("input").unwrap();
 | 
			
		||||
    let br = BufReader::new(f);
 | 
			
		||||
    br.lines()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    println!("Problem 1 solution: {}", problem1(get_input()));
 | 
			
		||||
    println!("Problem 2 solution: {}", problem2(get_input()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PARSING
 | 
			
		||||
 | 
			
		||||
// We will store the schematic as a 2D Vector of char
 | 
			
		||||
 | 
			
		||||
struct Pos(usize, usize);
 | 
			
		||||
 | 
			
		||||
// Outer Vec holds rows, so addressing is column then row
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
struct SchematicRow(Vec<char>);
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
struct Schematic(Vec<SchematicRow>);
 | 
			
		||||
 | 
			
		||||
impl From<&str> for SchematicRow {
 | 
			
		||||
    fn from(s: &str) -> Self {
 | 
			
		||||
        SchematicRow(s.chars().collect())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<InputIter> for Schematic {
 | 
			
		||||
    fn from(input: InputIter) -> Self {
 | 
			
		||||
        Self(input.map(|line| line.unwrap().as_str().into()).collect())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ADJACENCY_OFFSETS: &[(i64, i64)] = &[
 | 
			
		||||
    (-1, -1),
 | 
			
		||||
    (0, -1),
 | 
			
		||||
    (1, -1),
 | 
			
		||||
    (-1, 0),
 | 
			
		||||
    (1, 0),
 | 
			
		||||
    (-1, 1),
 | 
			
		||||
    (0, 1),
 | 
			
		||||
    (1, 1),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
// We assume the schematic is composed of equal length lines
 | 
			
		||||
impl Schematic {
 | 
			
		||||
    fn at(&self, pos: &Pos) -> char {
 | 
			
		||||
        self.0[pos.1].0[pos.0]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn adjacent_to_symbol(&self, pos: &Pos) -> bool {
 | 
			
		||||
        ADJACENCY_OFFSETS.iter().any(|(x_ofs, y_ofs)| {
 | 
			
		||||
            let adj_x = (pos.0 as i64) + x_ofs;
 | 
			
		||||
            let adj_y = (pos.1 as i64) + y_ofs;
 | 
			
		||||
 | 
			
		||||
            if adj_x < 0
 | 
			
		||||
                || adj_x >= self.0[pos.1].0.len() as i64
 | 
			
		||||
                || adj_y < 0
 | 
			
		||||
                || adj_y >= self.0.len() as i64
 | 
			
		||||
            {
 | 
			
		||||
                false
 | 
			
		||||
            } else {
 | 
			
		||||
                let adj_c = self.at(&Pos(adj_x as usize, adj_y as usize));
 | 
			
		||||
                adj_c != '.' && adj_c.is_ascii_punctuation()
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PROBLEM 1 solution
 | 
			
		||||
 | 
			
		||||
// Of course, the actual engine schematic is much larger. What is the sum of all of the
 | 
			
		||||
// part numbers in the engine schematic?
 | 
			
		||||
 | 
			
		||||
fn problem1_all_valid_part_numbers(schematic: &Schematic) -> Vec<u64> {
 | 
			
		||||
    let mut results = Vec::new();
 | 
			
		||||
 | 
			
		||||
    let mut cur_pos = Pos(0usize, 0usize);
 | 
			
		||||
 | 
			
		||||
    while cur_pos.1 < schematic.0.len() {
 | 
			
		||||
        while cur_pos.0 < schematic.0[0].0.len() {
 | 
			
		||||
            let c = schematic.at(&cur_pos);
 | 
			
		||||
            if c.is_digit(10) {
 | 
			
		||||
                let mut valid: bool = schematic.adjacent_to_symbol(&cur_pos);
 | 
			
		||||
                let mut num = c.to_digit(10).unwrap() as u64;
 | 
			
		||||
                loop {
 | 
			
		||||
                    if cur_pos.0 + 1 >= schematic.0[0].0.len() {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    cur_pos.0 += 1;
 | 
			
		||||
                    if schematic.at(&cur_pos).is_digit(10) {
 | 
			
		||||
                        num = num * 10 + schematic.at(&cur_pos).to_digit(10).unwrap() as u64;
 | 
			
		||||
                        valid = valid || schematic.adjacent_to_symbol(&cur_pos);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if valid {
 | 
			
		||||
                    results.push(num);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            cur_pos.0 += 1;
 | 
			
		||||
        }
 | 
			
		||||
        cur_pos.1 += 1;
 | 
			
		||||
        cur_pos.0 = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    results
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn problem1(input: InputIter) -> u64 {
 | 
			
		||||
    let schematic: Schematic = input.into();
 | 
			
		||||
    problem1_all_valid_part_numbers(&schematic).iter().sum()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PROBLEM 2 solution
 | 
			
		||||
 | 
			
		||||
fn problem2(input: InputIter) -> u64 {
 | 
			
		||||
    0
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user