Skip to content

Commit

Permalink
Tweak parsing and add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
maneatingape committed Aug 27, 2023
1 parent c6b93d5 commit f7b1f78
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions src/year2021/day19.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
//! factor of 24.
//!
//! The set of Euclidean distance squared between all beacons is a good choice, as it's invariant
//! under rotation, quick to calculate and a good discriminant. To check for an overlap of 12
//! beacons, we look for an overlap of a least 12 * 11 / 2 = 66 distances. (12 pairs is 12 * 11
//! different distances but divided by 2 since the distance from a -> b is the same as b -> a).
//! under rotation and translation, quick to calculate and a good discriminant. To check for an
//! overlap of 12 beacons, we look for an overlap of a least 12 * 11 / 2 = 66 distances.
//! (12 beacons gives 12 * 11 = 132 pairs of distances but divided by 2 since the distance from
//! a -> b is the same as b -> a).
//!
//! An overlap indicates a potential match, but we need to confirm by checking the beacons against
//! each other in two steps. First confirming orientation by matching the deltas between
Expand All @@ -31,8 +32,7 @@ use std::ops::{Add, Sub};
struct Point3D(i32, i32, i32);

impl Point3D {
fn parse(line: &&str) -> Point3D {
let [x, y, z] = line.iter_signed().chunk::<3>().next().unwrap();
fn parse([x, y, z]: [i32; 3]) -> Point3D {
Point3D(x, y, z)
}

Expand Down Expand Up @@ -112,9 +112,14 @@ struct Scanner {
impl Scanner {
/// Calculate the signature as the set of Euclidean distance squared between every possible
/// pair of beacons.
fn parse(lines: &[&str]) -> Scanner {
let beacons: Vec<_> = lines.iter().skip(1).map(Point3D::parse).collect();
fn parse(block: &str) -> Scanner {
// Each beacon header results in 5 mangled numbers at the start that should be skipped.
let beacons: Vec<_> =
block.iter_signed().skip(5).chunk::<3>().map(Point3D::parse).collect();

// Include indices of the points so that we can match translation and rotation for
// points that have the same signature. Use indices so that we don't need to recalculate
// signature when rotating and translation a beacon from unknown to known.
let mut signature = FastMap::with_capacity(1_000);
for i in 0..(beacons.len() - 1) {
for j in (i + 1)..beacons.len() {
Expand Down Expand Up @@ -164,9 +169,7 @@ impl Located {
/// Convert the raw input into a vec of unknown scanners, then do all the heavy lifting of figuring
/// out the relative orientations and translations of each scanner.
pub fn parse(input: &str) -> Vec<Located> {
let lines: Vec<_> = input.lines().collect();
let mut scanners: Vec<_> = lines.split(|line| line.is_empty()).map(Scanner::parse).collect();
locate(&mut scanners)
locate(&mut input.split("\n\n").map(Scanner::parse).collect())
}

/// Calculate the total number of distinct beacons.
Expand Down

0 comments on commit f7b1f78

Please sign in to comment.