Files
adventofcode2023/day3/rust/src/main.rs

161 lines
4.6 KiB
Rust
Raw Normal View History

2023-12-03 18:44:27 +01:00
struct Number {
value: usize,
}
enum Symbol {
Asterisk,
Other,
}
enum Tile<'a> {
Number(&'a Number),
Symbol(Symbol),
Period,
}
fn main() {
let stdin = std::io::stdin();
let mut map: Vec<Vec<Tile>> = Vec::new();
for line in stdin.lines() {
let line = line.unwrap();
let mut num = Vec::new();
let mut v = Vec::new();
for char in line.chars() {
if !char.is_digit(10) && num.len() > 0 {
let s: String = num.iter().collect();
let number = Box::leak(Box::new(Number {
value: s.parse().unwrap(),
}));
for _ in 0..s.len() {
v.push(Tile::Number(number));
}
num.clear();
}
if char == '.' {
v.push(Tile::Period);
} else if char == '*' {
v.push(Tile::Symbol(Symbol::Asterisk));
} else if char.is_digit(10) {
num.push(char);
} else {
v.push(Tile::Symbol(Symbol::Other));
}
}
if num.len() > 0 {
let s: String = num.iter().collect();
let number = Box::leak(Box::new(Number {
value: s.parse().unwrap(),
}));
for _ in 0..s.len() {
v.push(Tile::Number(number));
}
}
map.push(v);
}
// Part 1
let mut part1 = 0;
for (x, row) in map.iter().enumerate() {
let mut already_added = false;
for (y, tile) in row.iter().enumerate() {
match tile {
Tile::Number(number) => {
if already_added {
continue;
};
for dx in -1i32..=1 {
for dy in -1i32..=1 {
let ix = x.wrapping_add(dx as usize);
let iy = y.wrapping_add(dy as usize);
if let Some(v) = map.get(ix) {
if let Some(Tile::Symbol(_)) = v.get(iy) {
already_added = true;
part1 += number.value;
}
}
if already_added {
break;
};
}
if already_added {
break;
};
}
}
_ => {
if already_added {
already_added = false;
}
}
}
}
}
println!("{}", part1);
// Part 2
let mut part2 = 0;
for (x, row) in map.iter().enumerate() {
for (y, tile) in row.iter().enumerate() {
if let Tile::Symbol(Symbol::Asterisk) = tile {
let mut gears = [None; 2];
let mut gear_num = 0;
let mut skip = false;
for dx in -1i32..=1 {
for dy in -1i32..=1 {
let ix = x.wrapping_add(dx as usize);
let iy = y.wrapping_add(dy as usize);
if let Some(v) = map.get(ix) {
if let Some(Tile::Number(number)) = v.get(iy) {
if let Some(gear) = gears[0] {
if std::ptr::eq(gear, *number) {
continue;
}
}
if let Some(gear) = gears[1] {
if std::ptr::eq(gear, *number) {
continue;
}
}
if gear_num == 2 {
skip = true;
break;
}
gears[gear_num] = Some(*number);
gear_num += 1;
}
}
}
if skip {
break;
}
}
if gear_num == 2 {
unsafe {
part2 += (*gears[0].unwrap()).value * (*gears[1].unwrap()).value;
}
}
}
}
}
println!("{}", part2);
}