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