day3: problem 2 solution. this is ugly.
This commit is contained in:
parent
1911614428
commit
b1e7d7ad35
85
3/Cargo.lock
generated
85
3/Cargo.lock
generated
@ -2,6 +2,91 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "day3"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
@ -6,3 +6,4 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
num = "0.4.1"
|
||||
|
155
3/src/main.rs
155
3/src/main.rs
@ -1,5 +1,7 @@
|
||||
use num::traits;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Lines};
|
||||
use std::ops::Range;
|
||||
|
||||
// --- Day 3: Gear Ratios ---
|
||||
|
||||
@ -52,6 +54,7 @@ fn main() {
|
||||
|
||||
// We will store the schematic as a 2D Vector of char
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Pos(usize, usize);
|
||||
|
||||
// Outer Vec holds rows, so addressing is column then row
|
||||
@ -85,6 +88,19 @@ const ADJACENCY_OFFSETS: &[(i64, i64)] = &[
|
||||
|
||||
// We assume the schematic is composed of equal length lines
|
||||
impl Schematic {
|
||||
fn in_bounds<T: PartialOrd + num::traits::Zero + TryFrom<usize>>(&self, x: T, y: T) -> bool {
|
||||
let x_bound: T = self.0[0]
|
||||
.0
|
||||
.len()
|
||||
.try_into()
|
||||
.unwrap_or_else(|_| panic!("bad bounds"));
|
||||
let y_bound: T = self
|
||||
.0
|
||||
.len()
|
||||
.try_into()
|
||||
.unwrap_or_else(|_| panic!("bad bounds"));
|
||||
x >= T::zero() && x < x_bound && y >= T::zero() && y < y_bound
|
||||
}
|
||||
fn at(&self, pos: &Pos) -> char {
|
||||
self.0[pos.1].0[pos.0]
|
||||
}
|
||||
@ -94,6 +110,26 @@ impl Schematic {
|
||||
let adj_x = (pos.0 as i64) + x_ofs;
|
||||
let adj_y = (pos.1 as i64) + y_ofs;
|
||||
|
||||
if !self.in_bounds(adj_x, adj_y) {
|
||||
false
|
||||
} else {
|
||||
let adj_c = self.at(&Pos(adj_x as usize, adj_y as usize));
|
||||
adj_c != '.' && adj_c.is_ascii_punctuation()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn is_gear(&self, pos: &Pos) -> bool {
|
||||
if self.at(pos) != '*' {
|
||||
return false;
|
||||
}
|
||||
|
||||
ADJACENCY_OFFSETS
|
||||
.iter()
|
||||
.filter(|(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
|
||||
@ -102,9 +138,74 @@ impl Schematic {
|
||||
false
|
||||
} else {
|
||||
let adj_c = self.at(&Pos(adj_x as usize, adj_y as usize));
|
||||
adj_c != '.' && adj_c.is_ascii_punctuation()
|
||||
adj_c.is_digit(10)
|
||||
}
|
||||
})
|
||||
.count()
|
||||
>= 2
|
||||
}
|
||||
|
||||
fn gear_ratio(&self, pos: &Pos) -> Option<u64> {
|
||||
if self.at(pos) != '*' {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut exclusions: Vec<(Range<usize>, i64)> = Vec::new();
|
||||
let mut nums = (0u64, 0u64);
|
||||
|
||||
for (x_ofs, y_ofs) in ADJACENCY_OFFSETS {
|
||||
let adj_x = (pos.0 as i64) + x_ofs;
|
||||
let adj_y = (pos.1 as i64) + y_ofs;
|
||||
if !self.in_bounds(adj_x, adj_y)
|
||||
|| exclusions
|
||||
.iter()
|
||||
.any(|(ex_x_range, ex_y)| *ex_y == adj_y && ex_x_range.contains(&(adj_x as usize)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let adj_c = self.at(&Pos(adj_x as usize, adj_y as usize));
|
||||
if adj_c.is_digit(10) {
|
||||
let mut num_start_x = adj_x as usize;
|
||||
loop {
|
||||
if num_start_x > 0
|
||||
&& self
|
||||
.at(&Pos((num_start_x - 1) as usize, adj_y as usize))
|
||||
.is_digit(10)
|
||||
{
|
||||
num_start_x -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let mut num_end_x = adj_x as usize;
|
||||
loop {
|
||||
if self.in_bounds(num_end_x + 1, adj_y as usize)
|
||||
&& self
|
||||
.at(&Pos((num_end_x + 1) as usize, adj_y as usize))
|
||||
.is_digit(10)
|
||||
{
|
||||
num_end_x += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// we have the bounds for the number, extract a slice
|
||||
let num_slice = &self.0[adj_y as usize].0[num_start_x..num_end_x + 1];
|
||||
let mut num = 0u64;
|
||||
for c in num_slice {
|
||||
num = num * 10 + c.to_digit(10).unwrap() as u64;
|
||||
}
|
||||
if nums.0 == 0 {
|
||||
nums.0 = num
|
||||
} else {
|
||||
nums.1 = num;
|
||||
return Some(nums.0 * nums.1);
|
||||
}
|
||||
exclusions.push((num_start_x..num_end_x + 1, adj_y));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +257,54 @@ fn problem1(input: InputIter) -> u64 {
|
||||
|
||||
// PROBLEM 2 solution
|
||||
|
||||
fn problem2(input: InputIter) -> u64 {
|
||||
0
|
||||
// --- Part Two ---
|
||||
|
||||
// The engineer finds the missing part and installs it in the engine! As the engine
|
||||
// springs to life, you jump in the closest gondola, finally ready to ascend to the
|
||||
// water source.
|
||||
|
||||
// You don't seem to be going very fast, though. Maybe something is still wrong?
|
||||
// Fortunately, the gondola has a phone labeled "help", so you pick it up and the
|
||||
// engineer answers.
|
||||
|
||||
// Before you can explain the situation, she suggests that you look out the window.
|
||||
// There stands the engineer, holding a phone in one hand and waving with the other.
|
||||
// You're going so slowly that you haven't even left the station. You exit the gondola.
|
||||
|
||||
// The missing part wasn't the only issue - one of the gears in the engine is wrong. A
|
||||
// gear is any * symbol that is adjacent to exactly two part numbers. Its gear ratio is
|
||||
// the result of multiplying those two numbers together.
|
||||
|
||||
// This time, you need to find the gear ratio of every gear and add them all up so that
|
||||
// the engineer can figure out which gear needs to be replaced.
|
||||
|
||||
// Consider the same engine schematic again:
|
||||
|
||||
// 467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592.....
|
||||
// ......755. ...$.*.... .664.598..
|
||||
|
||||
// In this schematic, there are two gears. The first is in the top left; it has part
|
||||
// numbers 467 and 35, so its gear ratio is 16345. The second gear is in the lower
|
||||
// right; its gear ratio is 451490. (The * adjacent to 617 is not a gear because it is
|
||||
// only adjacent to one part number.) Adding up all of the gear ratios produces 467835.
|
||||
|
||||
// What is the sum of all of the gear ratios in your engine schematic?
|
||||
|
||||
fn problem2_all_gear_ratios(schematic: &Schematic) -> Vec<u64> {
|
||||
let mut gears = Vec::new();
|
||||
for y in 0..schematic.0.len() {
|
||||
for x in 0..schematic.0[0].0.len() {
|
||||
match schematic.gear_ratio(&Pos(x, y)) {
|
||||
Some(ratio) => gears.push(ratio),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gears
|
||||
}
|
||||
|
||||
fn problem2(input: InputIter) -> u64 {
|
||||
let schematic: Schematic = input.into();
|
||||
problem2_all_gear_ratios(&schematic).iter().sum()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user