day03: rust
This commit is contained in:
parent
abd2e35ea8
commit
0230ad7b9a
1
03/.gitignore
vendored
Normal file
1
03/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
day03
|
9
03/README.md
Normal file
9
03/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# [Day 3](https://adventofcode.com/2023/day/3)
|
||||
:gift::gift::gift:
|
||||
|
||||
Today's language: **Rust**
|
||||
|
||||
```shell
|
||||
rustc day03.rs
|
||||
./day03
|
||||
```
|
102
03/day03.rs
Normal file
102
03/day03.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use std::io::BufRead;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct Symbol(char, usize, usize);
|
||||
|
||||
|
||||
fn main() {
|
||||
let schematic = read_lines("input.txt");
|
||||
let mut part_sum = 0;
|
||||
let mut gear_ratio_sum: u32 = 0;
|
||||
let mut first_gears = HashMap::new(); // Symbol: first_gear
|
||||
for (n_line, line) in schematic.iter().enumerate() {
|
||||
// println!("{} {}", n_line, line);
|
||||
let mut num_begin: usize = usize::MAX;
|
||||
let mut num_end: usize = usize::MAX;
|
||||
for (n_char, c) in line.char_indices() {
|
||||
if num_begin == usize::MAX {
|
||||
if is_digit(c) { num_begin = n_char; }
|
||||
}
|
||||
else { // in number
|
||||
if !is_digit(c) {
|
||||
num_end = n_char - 1;
|
||||
}
|
||||
else if n_char == line.chars().count() - 1 { // last char
|
||||
num_end = n_char;
|
||||
}
|
||||
if num_end != usize::MAX {
|
||||
let symbol = find_symbol(&schematic, n_line, num_begin, n_char-1);
|
||||
if symbol != NO_SYMBOL {
|
||||
let num = line[num_begin..=num_end].parse::<u32>().expect("Could not parse number");
|
||||
part_sum += num;
|
||||
if symbol.0 == '*' {
|
||||
if first_gears.contains_key(&symbol) {
|
||||
gear_ratio_sum += first_gears[&symbol] * num;
|
||||
}
|
||||
else { first_gears.insert(symbol, num); }
|
||||
}
|
||||
}
|
||||
num_begin = usize::MAX;
|
||||
num_end = usize::MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("Total sum of part numbers: {}", part_sum);
|
||||
println!("Total sum of gear ratios: {}", gear_ratio_sum);
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn is_digit(c: char) -> bool {
|
||||
return '0' <= c && c <= '9'
|
||||
}
|
||||
fn is_symbol(c: char) -> bool {
|
||||
return c != '.' && (!is_digit(c));
|
||||
}
|
||||
|
||||
const NO_SYMBOL:Symbol = Symbol('\0', usize::MAX, usize::MAX);
|
||||
// return symbol and its position
|
||||
fn find_symbol(schematic: &Vec<String>, num_line: usize, num_begin: usize, num_end: usize) -> Symbol {
|
||||
// search char left and right
|
||||
if num_begin > 0 {
|
||||
let c = schematic[num_line].chars().nth(num_begin-1).unwrap();
|
||||
if is_symbol(c) { return Symbol(c, num_line, num_begin - 1); }
|
||||
}
|
||||
if num_end + 1 < schematic[num_line].chars().count() {
|
||||
let c = schematic[num_line].chars().nth(num_end+1).unwrap();
|
||||
if is_symbol(c) { return Symbol(c, num_line, num_end + 1); }
|
||||
}
|
||||
|
||||
let skip: usize = num_begin.saturating_sub(1);
|
||||
let take: usize;
|
||||
if num_begin == 0 {
|
||||
take = num_end.saturating_sub(num_begin) + 2;
|
||||
} else {
|
||||
take = num_end.saturating_sub(num_begin) + 3;
|
||||
}
|
||||
|
||||
// search top line
|
||||
if num_line > 0 {
|
||||
for (i, c) in schematic[num_line-1].char_indices().skip(skip).take(take) {
|
||||
if is_symbol(c) { return Symbol(c, num_line-1, i); }
|
||||
}
|
||||
}
|
||||
// search bottom line
|
||||
if num_line + 1 < schematic.len() {
|
||||
for (i, c) in schematic[num_line+1].char_indices().skip(skip).take(take) {
|
||||
if is_symbol(c) { return Symbol(c, num_line+1, i); }
|
||||
}
|
||||
}
|
||||
return NO_SYMBOL;
|
||||
}
|
||||
|
||||
|
||||
fn read_lines<P>(filename: P) -> Vec<String>
|
||||
where P: AsRef<std::path::Path>, {
|
||||
return match std::fs::File::open(filename) {
|
||||
Err(why) => panic!("Could not open file. {}", why),
|
||||
Ok(file) => std::io::BufReader::new(file).lines().map(|l| {l.expect("Could not parse line")}).collect(),
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user