feat: complete day 19 part 2
This commit is contained in:
parent
2e495f674c
commit
2143563b80
518
src/day19.rs
518
src/day19.rs
@ -1,263 +1,337 @@
|
||||
// Solution for this problem by somone else: https://github.com/Jellycious/aoc-2021/blob/main/src/days/day19.rs
|
||||
|
||||
use std::{collections::{HashSet, HashMap}, ops::{Add, Sub}};
|
||||
|
||||
use std::{collections::{HashSet, HashMap}, ops::{Add, Sub, Neg}};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Point(i32, i32, i32);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct RotationMatrix(i32, i32, i32, i32, i32, i32, i32, i32, i32);
|
||||
|
||||
impl Point {
|
||||
fn apply_rotation(&self, t: &RotationMatrix) -> Point {
|
||||
return Point(
|
||||
self.0 * t.0 + self.1 * t.1 + self.2 * t.2,
|
||||
self.0 * t.3 + self.1 * t.4 + self.2 * t.5,
|
||||
self.0 * t.6 + self.1 * t.7 + self.2 * t.8
|
||||
);
|
||||
}
|
||||
|
||||
fn sqr_dist(&self, other: &Point) -> i32 {
|
||||
let dx = self.0 - other.0;
|
||||
let dy = self.1 - other.1;
|
||||
let dz = self.2 - other.2;
|
||||
return dx*dx + dy*dy + dz*dz;
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Point(
|
||||
self.0 + rhs.0,
|
||||
self.1 + rhs.1,
|
||||
self.2 + rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Point(
|
||||
self.0 - rhs.0,
|
||||
self.1 - rhs.1,
|
||||
self.2 - rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_point(line: &str) -> Point {
|
||||
let nums: Vec<&str> = line.splitn(3, ',').collect();
|
||||
let x = nums[0].parse().unwrap();
|
||||
let y = nums[1].parse().unwrap();
|
||||
let z = nums[2].parse().unwrap();
|
||||
return Point(x, y, z);
|
||||
let nums: Vec<&str> = line.splitn(3, ',').collect();
|
||||
let x = nums[0].parse().unwrap();
|
||||
let y = nums[1].parse().unwrap();
|
||||
let z = nums[2].parse().unwrap();
|
||||
Point(x, y, z)
|
||||
}
|
||||
|
||||
fn parse_scanner(input: &str) -> Vec<Point> {
|
||||
let mut beacons = Vec::new();
|
||||
for line in input.lines().skip(1) {
|
||||
beacons.push(parse_point(line));
|
||||
}
|
||||
return beacons;
|
||||
let mut beacons = Vec::new();
|
||||
for line in input.lines().skip(1) {
|
||||
beacons.push(parse_point(line));
|
||||
}
|
||||
beacons
|
||||
}
|
||||
|
||||
pub fn parse_input(input: &str) -> Vec<Vec<Point>> {
|
||||
let mut scanners = Vec::new();
|
||||
for scanner_section in input.split("\n\n") {
|
||||
scanners.push(parse_scanner(scanner_section));
|
||||
let mut scanners = Vec::new();
|
||||
for scanner_section in input.split("\n\n") {
|
||||
scanners.push(parse_scanner(scanner_section));
|
||||
}
|
||||
scanners
|
||||
}
|
||||
|
||||
impl Add for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Point(
|
||||
self.0 + rhs.0,
|
||||
self.1 + rhs.1,
|
||||
self.2 + rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Point(
|
||||
self.0 - rhs.0,
|
||||
self.1 - rhs.1,
|
||||
self.2 - rhs.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
Point(-self.0, -self.1, -self.2)
|
||||
}
|
||||
return scanners;
|
||||
}
|
||||
|
||||
fn generate_rotations() -> Vec<RotationMatrix> {
|
||||
let mut transforms = Vec::new();
|
||||
fn calc_diff(a: &Point, b: &Point) -> Point {
|
||||
let x = (a.0 - b.0).abs();
|
||||
let y = (a.1 - b.1).abs();
|
||||
let z = (a.2 - b.2).abs();
|
||||
|
||||
// +z axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
transforms.push(RotationMatrix( 0, 1, 0, -1, 0, 0, 0, 0, 1));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
transforms.push(RotationMatrix(0, -1, 0, 1, 0, 0, 0, 0, 1));
|
||||
let lowest = x.min(y).min(z);
|
||||
let highest = x.max(y).max(z);
|
||||
let middle = x + y + z - lowest - highest;
|
||||
|
||||
// -z axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, -1, 0, 0, 0, -1));
|
||||
transforms.push(RotationMatrix( 0, 1, 0, 1, 0, 0, 0, 0, -1));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, 1, 0, 0, 0, -1));
|
||||
transforms.push(RotationMatrix(0, -1, 0, -1, 0, 0, 0, 0, -1));
|
||||
|
||||
// +y axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, 0, -1, 0, 1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, 1, 0, 0, 0, 1, 0));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, 0, 1, 0, 1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, -1, 0, 0, 0, 1, 0));
|
||||
|
||||
// -y axis
|
||||
transforms.push(RotationMatrix( 1, 0, 0, 0, 0, 1, 0,-1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, -1, 0, 0, 0,-1, 0));
|
||||
transforms.push(RotationMatrix(-1, 0, 0, 0, 0, -1, 0,-1, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, 1, 0, 0, 0,-1, 0));
|
||||
|
||||
// +x axis
|
||||
transforms.push(RotationMatrix( 0,-1, 0, 0, 0, -1, 1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, 0, 1, 0, 1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 1, 0, 0, 0, 1, 1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, 0,-1, 0, 1, 0, 0));
|
||||
|
||||
// -x axis
|
||||
transforms.push(RotationMatrix( 0, 1, 0, 0, 0, -1, -1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0, 1, 0, 1, 0, -1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0,-1, 0, 0, 0, 1, -1, 0, 0));
|
||||
transforms.push(RotationMatrix( 0, 0,-1, 0,-1, 0, -1, 0, 0));
|
||||
|
||||
return transforms;
|
||||
Point(lowest, middle, highest)
|
||||
}
|
||||
|
||||
fn find_distances_pairs<'a>(points: &'a Vec<Point>) -> Vec<(i32, &'a Point, &'a Point)> {
|
||||
let mut distances = Vec::new();
|
||||
let n = points.len();
|
||||
for i in 0..n-1 {
|
||||
for j in i+1..n {
|
||||
let p1 = &points[i];
|
||||
let p2 = &points[j];
|
||||
let dist = p1.sqr_dist(&p2);
|
||||
distances.push((dist, p1, p2));
|
||||
}
|
||||
}
|
||||
return distances;
|
||||
fn get_point_pairs(points: &[Point]) -> Vec<(Point, Point)> {
|
||||
points.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, p1)| points.iter().skip(i + 1).map(move |p2| (*p1, *p2)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_common_points<'a, 'b>(scanner1: &'a Vec<Point>, scanner2: &'b Vec<Point>) -> (Vec<Point>, Vec<Point>) {
|
||||
let mut common_points1: Vec<Point> = Vec::new();
|
||||
let mut common_points2: Vec<Point> = Vec::new();
|
||||
|
||||
for pair1 in find_distances_pairs(scanner1) {
|
||||
for pair2 in find_distances_pairs(scanner2) {
|
||||
if pair1.0 == pair2.0 {
|
||||
if !common_points1.contains(pair1.1) {
|
||||
common_points1.push(*pair1.1);
|
||||
}
|
||||
if !common_points1.contains(pair1.2) {
|
||||
common_points1.push(*pair1.2);
|
||||
}
|
||||
if !common_points2.contains(pair2.1) {
|
||||
common_points2.push(*pair2.1);
|
||||
}
|
||||
if !common_points2.contains(pair2.2) {
|
||||
common_points2.push(*pair2.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (common_points1, common_points2);
|
||||
fn get_point_diffs(a: &[Point]) -> HashSet<Point> {
|
||||
get_point_pairs(a).iter()
|
||||
.map(|(p1, p2)| calc_diff(p1, p2))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn apply_offset_rotation(points: &Vec<Point>, offset: &Point, rotation: &RotationMatrix) -> Vec<Point> {
|
||||
points.iter()
|
||||
.map(|p| p.apply_rotation(&rotation) + *offset)
|
||||
.collect()
|
||||
fn do_scanners_possibly_overlap(a: &[Point], b: &[Point]) -> bool {
|
||||
let a_diffs = get_point_diffs(a);
|
||||
let b_diffs = get_point_diffs(b);
|
||||
|
||||
a_diffs.intersection(&b_diffs).count() >= 66
|
||||
}
|
||||
|
||||
fn find_offset_rotation(mut points1: Vec<Point>, points2: Vec<Point>) -> Option<(Point, RotationMatrix)> {
|
||||
points1.sort();
|
||||
fn find_possibly_overlapping_scanners(scanners: &[Vec<Point>]) -> Vec<(usize, usize)> {
|
||||
let mut pairs = vec![];
|
||||
|
||||
'outer: for rotation in generate_rotations() {
|
||||
let mut transformed_points: Vec<_> = points2.iter()
|
||||
.map(|p| p.apply_rotation(&rotation))
|
||||
.collect();
|
||||
transformed_points.sort();
|
||||
for (i, scanner1) in scanners.iter().enumerate() {
|
||||
for (j, scanner2) in scanners.iter().enumerate().skip(i + 1) {
|
||||
if do_scanners_possibly_overlap(scanner1, scanner2) {
|
||||
pairs.push((i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let offset = points1[0] - transformed_points[0];
|
||||
if rotation == RotationMatrix(-1, 0, 0, 0, -1, 0, 0, 0, 1) {
|
||||
println!("\n\nTransform: {:?}", rotation);
|
||||
println!("Offset: {:?}\n", offset);
|
||||
println!("{:?}\n", points1);
|
||||
// println!("{:?}", transformed_points);
|
||||
}
|
||||
|
||||
for i in 1..points1.len() {
|
||||
let diff = points1[i] - transformed_points[i];
|
||||
if offset != diff {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
return Some((offset, rotation));
|
||||
}
|
||||
|
||||
return None;
|
||||
pairs
|
||||
}
|
||||
|
||||
fn align_scanners(scanners: &mut Vec<Vec<Point>>) {
|
||||
let mut unaligned = HashSet::new();
|
||||
let mut unchecked = vec![0];
|
||||
|
||||
for i in 1..scanners.len() {
|
||||
unaligned.insert(i);
|
||||
}
|
||||
|
||||
while !unchecked.is_empty() {
|
||||
|
||||
let aligned_id = unchecked.pop().unwrap();
|
||||
for i in unaligned.clone() {
|
||||
let unaligned_scanner = &scanners[i];
|
||||
let (common_points1, common_points2) = find_common_points(&scanners[aligned_id], unaligned_scanner);
|
||||
if common_points1.len() >= 12 {
|
||||
let transform = find_offset_rotation(common_points1, common_points2);
|
||||
if let Some((offset, rotation)) = transform {
|
||||
scanners[i] = apply_offset_rotation(&scanners[i], &offset, &rotation);
|
||||
unchecked.push(i);
|
||||
unaligned.remove(&i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn calc_rotations(p: Point) -> Vec<Point> {
|
||||
// https://i.imgur.com/Ff1vGT9.png
|
||||
let Point(x, y, z) = p;
|
||||
vec![
|
||||
Point(x ,y ,z), Point(x ,z,-y), Point(x ,-y,-z), Point(x ,-z,y ),
|
||||
Point(-x,-y,z), Point(-x,z,y ), Point(-x,y ,-z), Point(-x,-z,-y ),
|
||||
Point(y ,z ,x), Point(y ,x,-z), Point(y ,-z,-x), Point(y ,-x,z ),
|
||||
Point(-y,-z,x), Point(-y,x,z ), Point(-y,z ,-x), Point(-y,-x,-z ),
|
||||
Point(z ,x ,y), Point(z ,y,-x), Point(z ,-x,-y), Point(z ,-y,x ),
|
||||
Point(-z,-x,y), Point(-z,y,x ), Point(-z,x ,-y), Point(-z,-y,-x)
|
||||
]
|
||||
}
|
||||
|
||||
fn find_unique_points(scanners: &Vec<Vec<Point>>) -> Vec<Point> {
|
||||
let mut cloned = scanners.clone();
|
||||
|
||||
align_scanners(&mut cloned);
|
||||
|
||||
let mut point_set = HashSet::new();
|
||||
for scanner in cloned {
|
||||
for point in scanner {
|
||||
point_set.insert(point);
|
||||
}
|
||||
}
|
||||
|
||||
return point_set.into_iter().collect();
|
||||
fn calc_rotation(p: Point, rotation: usize) -> Point {
|
||||
calc_rotations(p)[rotation]
|
||||
}
|
||||
|
||||
pub fn part1(scanners: &Vec<Vec<Point>>) -> u32 {
|
||||
find_unique_points(scanners).len() as u32
|
||||
fn combine_rotations(r1: usize, r2: usize) -> usize {
|
||||
let target_point = calc_rotation(calc_rotation(Point(1, 2, 3), r1), r2);
|
||||
for (i, rotated) in calc_rotations(Point(1, 2, 3)).iter().enumerate() {
|
||||
if *rotated == target_point {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
panic!()
|
||||
}
|
||||
|
||||
pub fn part2(scanners: &Vec<Vec<Point>>) -> u32 {
|
||||
0
|
||||
fn invert_rotation(r: usize) -> usize {
|
||||
let target_point = calc_rotation(Point(1, 2, 3), r);
|
||||
for (i, rotated) in calc_rotations(target_point).iter().enumerate() {
|
||||
if *rotated == Point(1, 2, 3) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn find_possible_rotations(dir1: Point, dir2: Point) -> Vec<usize> {
|
||||
let mut possible_rotations = vec![];
|
||||
|
||||
let rotated_dirs2 = calc_rotations(dir2);
|
||||
for (i, rotated_dir2) in rotated_dirs2.iter().enumerate() {
|
||||
if *rotated_dir2 == dir1 {
|
||||
possible_rotations.push(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i, rotated_dir2) in rotated_dirs2.iter().enumerate() {
|
||||
if *rotated_dir2 == -dir1 {
|
||||
possible_rotations.push(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
possible_rotations
|
||||
}
|
||||
|
||||
fn apply_transformation(points: &[Point], translation: Point, rotation: usize) -> Vec<Point> {
|
||||
points.iter()
|
||||
.map(|p| calc_rotation(*p, rotation) + translation)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_transformation(scanner1: &[Point], scanner2: &[Point]) -> Option<(Point, usize)> {
|
||||
let point_pairs1 = get_point_pairs(scanner1);
|
||||
let point_pairs2 = get_point_pairs(scanner2);
|
||||
|
||||
let scanner1_set: HashSet<_> = scanner1.iter().copied().collect();
|
||||
|
||||
for pair1 in &point_pairs1 {
|
||||
for pair2 in &point_pairs2 {
|
||||
if calc_diff(&pair1.0, &pair1.1) != calc_diff(&pair2.0, &pair2.1) {
|
||||
continue;
|
||||
}
|
||||
let dir1 = pair1.0 - pair1.1;
|
||||
let dir2 = pair2.0 - pair2.1;
|
||||
|
||||
for rotation in find_possible_rotations(dir1, dir2) {
|
||||
let translation = pair1.0 - calc_rotation(pair2.0, rotation);
|
||||
let transformed_scanner2: HashSet<_> = scanner2.iter()
|
||||
.map(|p| calc_rotation(*p, rotation) + translation)
|
||||
.collect();
|
||||
|
||||
if scanner1_set.intersection(&transformed_scanner2).count() >= 12 {
|
||||
return Some((translation, rotation));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn find_canonical_transformations(scanners: &[Vec<Point>]) -> Vec<(Point, usize)> {
|
||||
let mut canonical = vec![];
|
||||
for _ in 0..scanners.len() {
|
||||
canonical.push((Point(0, 0, 0), 0))
|
||||
}
|
||||
|
||||
let mut transforms = HashMap::new();
|
||||
for (scanner1, scanner2) in find_possibly_overlapping_scanners(scanners) {
|
||||
let (translation, rotation) = find_transformation(&scanners[scanner1], &scanners[scanner2]).unwrap();
|
||||
let inv_rotation = invert_rotation(rotation);
|
||||
|
||||
transforms.entry(scanner1)
|
||||
.or_insert_with(Vec::new)
|
||||
.push((scanner2, translation, rotation));
|
||||
|
||||
transforms.entry(scanner2)
|
||||
.or_insert_with(Vec::new)
|
||||
.push((scanner1, calc_rotation(-translation, inv_rotation), inv_rotation));
|
||||
}
|
||||
|
||||
let mut stack = vec![(0, Point(0, 0, 0), 0)];
|
||||
let mut visited = HashSet::new();
|
||||
while !stack.is_empty() {
|
||||
let (id, translation, rotation) = stack.pop().unwrap();
|
||||
|
||||
if visited.contains(&id) { continue; }
|
||||
visited.insert(id);
|
||||
|
||||
for nbr in transforms.get(&id).unwrap() {
|
||||
if visited.contains(&nbr.0) { continue; }
|
||||
|
||||
let new_translation = calc_rotation(nbr.1, rotation) + translation;
|
||||
let new_rotation = combine_rotations(nbr.2, rotation);
|
||||
stack.push((nbr.0, new_translation, new_rotation));
|
||||
canonical[nbr.0] = (new_translation, new_rotation);
|
||||
}
|
||||
}
|
||||
|
||||
// dbg!(&canonical);
|
||||
|
||||
canonical
|
||||
}
|
||||
|
||||
pub fn part1(scanners: &[Vec<Point>]) -> u32 {
|
||||
let transforms = find_canonical_transformations(scanners);
|
||||
let mut beacons = HashSet::new();
|
||||
|
||||
for (i, points) in scanners.iter().enumerate() {
|
||||
let (translation, rotation) = transforms[i];
|
||||
for point in apply_transformation(points, translation, rotation) {
|
||||
beacons.insert(point);
|
||||
}
|
||||
}
|
||||
|
||||
beacons.len() as u32
|
||||
}
|
||||
|
||||
pub fn part2(scanners: &[Vec<Point>]) -> i32 {
|
||||
let transforms = find_canonical_transformations(scanners);
|
||||
|
||||
let mut max_distance = 0;
|
||||
for (i, transform1) in transforms.iter().enumerate() {
|
||||
for transform2 in transforms.iter().skip(i+1) {
|
||||
let diff = transform1.0 - transform2.0;
|
||||
let distance = diff.0 + diff.1 + diff.2;
|
||||
max_distance = max_distance.max(distance);
|
||||
}
|
||||
}
|
||||
|
||||
max_distance
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
let scanners = vec![
|
||||
vec![Point(404,-588,-901), Point(528,-643,409), Point(-838,591,734), Point(390,-675,-793), Point(-537,-823,-458), Point(-485,-357,347), Point(-345,-311,381), Point(-661,-816,-575), Point(-876,649,763), Point(-618,-824,-621), Point(553,345,-567), Point(474,580,667), Point(-447,-329,318), Point(-584,868,-557), Point(544,-627,-890), Point(564,392,-477), Point(455,729,728), Point(-892,524,684), Point(-689,845,-530), Point(423,-701,434), Point(7,-33,-71), Point(630,319,-379), Point(443,580,662), Point(-789,900,-551), Point(459,-707,401)],
|
||||
vec![Point(686,422,578), Point(605,423,415), Point(515,917,-361), Point(-336,658,858), Point(95,138,22), Point(-476,619,847), Point(-340,-569,-846), Point(567,-361,727), Point(-460,603,-452), Point(669,-402,600), Point(729,430,532), Point(-500,-761,534), Point(-322,571,750), Point(-466,-666,-811), Point(-429,-592,574), Point(-355,545,-477), Point(703,-491,-529), Point(-328,-685,520), Point(413,935,-424), Point(-391,539,-444), Point(586,-435,557), Point(-364,-763,-893), Point(807,-499,-711), Point(755,-354,-619), Point(553,889,-390)],
|
||||
vec![Point(649,640,665), Point(682,-795,504), Point(-784,533,-524), Point(-644,584,-595), Point(-588,-843,648), Point(-30,6,44), Point(-674,560,763), Point(500,723,-460), Point(609,671,-379), Point(-555,-800,653), Point(-675,-892,-343), Point(697,-426,-610), Point(578,704,681), Point(493,664,-388), Point(-671,-858,530), Point(-667,343,800), Point(571,-461,-707), Point(-138,-166,112), Point(-889,563,-600), Point(646,-828,498), Point(640,759,510), Point(-630,509,768), Point(-681,-892,-333), Point(673,-379,-804), Point(-742,-814,-386), Point(577,-820,562)],
|
||||
vec![Point(-589,542,597), Point(605,-692,669), Point(-500,565,-823), Point(-660,373,557), Point(-458,-679,-417), Point(-488,449,543), Point(-626,468,-788), Point(338,-750,-386), Point(528,-832,-391), Point(562,-778,733), Point(-938,-730,414), Point(543,643,-506), Point(-524,371,-870), Point(407,773,750), Point(-104,29,83), Point(378,-903,-323), Point(-778,-728,485), Point(426,699,580), Point(-438,-605,-362), Point(-469,-447,-387), Point(509,732,623), Point(647,635,-688), Point(-868,-804,481), Point(614,-800,639), Point(595,780,-596)],
|
||||
vec![Point(727,592,562), Point(-293,-554,779), Point(441,611,-461), Point(-714,465,-776), Point(-743,427,-804), Point(-660,-479,-426), Point(832,-632,460), Point(927,-485,-438), Point(408,393,-506), Point(466,436,-512), Point(110,16,151), Point(-258,-428,682), Point(-393,719,612), Point(-211,-452,876), Point(808,-476,-593), Point(-575,615,604), Point(-485,667,467), Point(-680,325,-822), Point(-627,-443,-432), Point(872,-547,-609), Point(833,512,582), Point(807,604,487), Point(839,-516,451), Point(891,-625,532), Point(-652,-548,-490), Point(30,-46,-14)]
|
||||
];
|
||||
let result = part1(&scanners);
|
||||
assert_eq!(result, 79);
|
||||
}
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn part1_example() {
|
||||
let scanners = vec![
|
||||
vec![Point(404, -588, -901), Point(528, -643, 409), Point(-838, 591, 734), Point(390, -675, -793), Point(-537, -823, -458), Point(-485, -357, 347), Point(-345, -311, 381), Point(-661, -816, -575), Point(-876, 649, 763), Point(-618, -824, -621), Point(553, 345, -567), Point(474, 580, 667), Point(-447, -329, 318), Point(-584, 868, -557), Point(544, -627, -890), Point(564, 392, -477), Point(455, 729, 728), Point(-892, 524, 684), Point(-689, 845, -530), Point(423, -701, 434), Point(7, -33, -71), Point(630, 319, -379), Point(443, 580, 662), Point(-789, 900, -551), Point(459, -707, 401)],
|
||||
vec![Point(686, 422, 578), Point(605, 423, 415), Point(515, 917, -361), Point(-336, 658, 858), Point(95, 138, 22), Point(-476, 619, 847), Point(-340, -569, -846), Point(567, -361, 727), Point(-460, 603, -452), Point(669, -402, 600), Point(729, 430, 532), Point(-500, -761, 534), Point(-322, 571, 750), Point(-466, -666, -811), Point(-429, -592, 574), Point(-355, 545, -477), Point(703, -491, -529), Point(-328, -685, 520), Point(413, 935, -424), Point(-391, 539, -444), Point(586, -435, 557), Point(-364, -763, -893), Point(807, -499, -711), Point(755, -354, -619), Point(553, 889, -390)],
|
||||
vec![Point(649, 640, 665), Point(682, -795, 504), Point(-784, 533, -524), Point(-644, 584, -595), Point(-588, -843, 648), Point(-30, 6, 44), Point(-674, 560, 763), Point(500, 723, -460), Point(609, 671, -379), Point(-555, -800, 653), Point(-675, -892, -343), Point(697, -426, -610), Point(578, 704, 681), Point(493, 664, -388), Point(-671, -858, 530), Point(-667, 343, 800), Point(571, -461, -707), Point(-138, -166, 112), Point(-889, 563, -600), Point(646, -828, 498), Point(640, 759, 510), Point(-630, 509, 768), Point(-681, -892, -333), Point(673, -379, -804), Point(-742, -814, -386), Point(577, -820, 562)],
|
||||
vec![Point(-589, 542, 597), Point(605, -692, 669), Point(-500, 565, -823), Point(-660, 373, 557), Point(-458, -679, -417), Point(-488, 449, 543), Point(-626, 468, -788), Point(338, -750, -386), Point(528, -832, -391), Point(562, -778, 733), Point(-938, -730, 414), Point(543, 643, -506), Point(-524, 371, -870), Point(407, 773, 750), Point(-104, 29, 83), Point(378, -903, -323), Point(-778, -728, 485), Point(426, 699, 580), Point(-438, -605, -362), Point(-469, -447, -387), Point(509, 732, 623), Point(647, 635, -688), Point(-868, -804, 481), Point(614, -800, 639), Point(595, 780, -596)],
|
||||
vec![Point(727, 592, 562), Point(-293, -554, 779), Point(441, 611, -461), Point(-714, 465, -776), Point(-743, 427, -804), Point(-660, -479, -426), Point(832, -632, 460), Point(927, -485, -438), Point(408, 393, -506), Point(466, 436, -512), Point(110, 16, 151), Point(-258, -428, 682), Point(-393, 719, 612), Point(-211, -452, 876), Point(808, -476, -593), Point(-575, 615, 604), Point(-485, 667, 467), Point(-680, 325, -822), Point(-627, -443, -432), Point(872, -547, -609), Point(833, 512, 582), Point(807, 604, 487), Point(839, -516, 451), Point(891, -625, 532), Point(-652, -548, -490), Point(30, -46, -14)],
|
||||
];
|
||||
let result = part1(&scanners);
|
||||
assert_eq!(result, 79);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn part2_example() {
|
||||
let scanners = vec![
|
||||
vec![Point(404, -588, -901), Point(528, -643, 409), Point(-838, 591, 734), Point(390, -675, -793), Point(-537, -823, -458), Point(-485, -357, 347), Point(-345, -311, 381), Point(-661, -816, -575), Point(-876, 649, 763), Point(-618, -824, -621), Point(553, 345, -567), Point(474, 580, 667), Point(-447, -329, 318), Point(-584, 868, -557), Point(544, -627, -890), Point(564, 392, -477), Point(455, 729, 728), Point(-892, 524, 684), Point(-689, 845, -530), Point(423, -701, 434), Point(7, -33, -71), Point(630, 319, -379), Point(443, 580, 662), Point(-789, 900, -551), Point(459, -707, 401)],
|
||||
vec![Point(686, 422, 578), Point(605, 423, 415), Point(515, 917, -361), Point(-336, 658, 858), Point(95, 138, 22), Point(-476, 619, 847), Point(-340, -569, -846), Point(567, -361, 727), Point(-460, 603, -452), Point(669, -402, 600), Point(729, 430, 532), Point(-500, -761, 534), Point(-322, 571, 750), Point(-466, -666, -811), Point(-429, -592, 574), Point(-355, 545, -477), Point(703, -491, -529), Point(-328, -685, 520), Point(413, 935, -424), Point(-391, 539, -444), Point(586, -435, 557), Point(-364, -763, -893), Point(807, -499, -711), Point(755, -354, -619), Point(553, 889, -390)],
|
||||
vec![Point(649, 640, 665), Point(682, -795, 504), Point(-784, 533, -524), Point(-644, 584, -595), Point(-588, -843, 648), Point(-30, 6, 44), Point(-674, 560, 763), Point(500, 723, -460), Point(609, 671, -379), Point(-555, -800, 653), Point(-675, -892, -343), Point(697, -426, -610), Point(578, 704, 681), Point(493, 664, -388), Point(-671, -858, 530), Point(-667, 343, 800), Point(571, -461, -707), Point(-138, -166, 112), Point(-889, 563, -600), Point(646, -828, 498), Point(640, 759, 510), Point(-630, 509, 768), Point(-681, -892, -333), Point(673, -379, -804), Point(-742, -814, -386), Point(577, -820, 562)],
|
||||
vec![Point(-589, 542, 597), Point(605, -692, 669), Point(-500, 565, -823), Point(-660, 373, 557), Point(-458, -679, -417), Point(-488, 449, 543), Point(-626, 468, -788), Point(338, -750, -386), Point(528, -832, -391), Point(562, -778, 733), Point(-938, -730, 414), Point(543, 643, -506), Point(-524, 371, -870), Point(407, 773, 750), Point(-104, 29, 83), Point(378, -903, -323), Point(-778, -728, 485), Point(426, 699, 580), Point(-438, -605, -362), Point(-469, -447, -387), Point(509, 732, 623), Point(647, 635, -688), Point(-868, -804, 481), Point(614, -800, 639), Point(595, 780, -596)],
|
||||
vec![Point(727, 592, 562), Point(-293, -554, 779), Point(441, 611, -461), Point(-714, 465, -776), Point(-743, 427, -804), Point(-660, -479, -426), Point(832, -632, 460), Point(927, -485, -438), Point(408, 393, -506), Point(466, 436, -512), Point(110, 16, 151), Point(-258, -428, 682), Point(-393, 719, 612), Point(-211, -452, 876), Point(808, -476, -593), Point(-575, 615, 604), Point(-485, 667, 467), Point(-680, 325, -822), Point(-627, -443, -432), Point(872, -547, -609), Point(833, 512, 582), Point(807, 604, 487), Point(839, -516, 451), Point(891, -625, 532), Point(-652, -548, -490), Point(30, -46, -14)],
|
||||
];
|
||||
let result = part2(&scanners);
|
||||
assert_eq!(result, 3621);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn part1_overlap() {
|
||||
let scanner1 = vec![Point(404, -588, -901), Point(528, -643, 409), Point(-838, 591, 734), Point(390, -675, -793), Point(-537, -823, -458), Point(-485, -357, 347), Point(-345, -311, 381), Point(-661, -816, -575), Point(-876, 649, 763), Point(-618, -824, -621), Point(553, 345, -567), Point(474, 580, 667), Point(-447, -329, 318), Point(-584, 868, -557), Point(544, -627, -890), Point(564, 392, -477), Point(455, 729, 728), Point(-892, 524, 684), Point(-689, 845, -530), Point(423, -701, 434), Point(7, -33, -71), Point(630, 319, -379), Point(443, 580, 662), Point(-789, 900, -551), Point(459, -707, 401)];
|
||||
let scanner2 = vec![Point(686, 422, 578), Point(605, 423, 415), Point(515, 917, -361), Point(-336, 658, 858), Point(95, 138, 22), Point(-476, 619, 847), Point(-340, -569, -846), Point(567, -361, 727), Point(-460, 603, -452), Point(669, -402, 600), Point(729, 430, 532), Point(-500, -761, 534), Point(-322, 571, 750), Point(-466, -666, -811), Point(-429, -592, 574), Point(-355, 545, -477), Point(703, -491, -529), Point(-328, -685, 520), Point(413, 935, -424), Point(-391, 539, -444), Point(586, -435, 557), Point(-364, -763, -893), Point(807, -499, -711), Point(755, -354, -619), Point(553, 889, -390)];
|
||||
assert!(do_scanners_possibly_overlap(&scanner1, &scanner2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn part1_overlapping_scanners() {
|
||||
let scanners = vec![
|
||||
vec![Point(404, -588, -901), Point(528, -643, 409), Point(-838, 591, 734), Point(390, -675, -793), Point(-537, -823, -458), Point(-485, -357, 347), Point(-345, -311, 381), Point(-661, -816, -575), Point(-876, 649, 763), Point(-618, -824, -621), Point(553, 345, -567), Point(474, 580, 667), Point(-447, -329, 318), Point(-584, 868, -557), Point(544, -627, -890), Point(564, 392, -477), Point(455, 729, 728), Point(-892, 524, 684), Point(-689, 845, -530), Point(423, -701, 434), Point(7, -33, -71), Point(630, 319, -379), Point(443, 580, 662), Point(-789, 900, -551), Point(459, -707, 401)],
|
||||
vec![Point(686, 422, 578), Point(605, 423, 415), Point(515, 917, -361), Point(-336, 658, 858), Point(95, 138, 22), Point(-476, 619, 847), Point(-340, -569, -846), Point(567, -361, 727), Point(-460, 603, -452), Point(669, -402, 600), Point(729, 430, 532), Point(-500, -761, 534), Point(-322, 571, 750), Point(-466, -666, -811), Point(-429, -592, 574), Point(-355, 545, -477), Point(703, -491, -529), Point(-328, -685, 520), Point(413, 935, -424), Point(-391, 539, -444), Point(586, -435, 557), Point(-364, -763, -893), Point(807, -499, -711), Point(755, -354, -619), Point(553, 889, -390)],
|
||||
vec![Point(649, 640, 665), Point(682, -795, 504), Point(-784, 533, -524), Point(-644, 584, -595), Point(-588, -843, 648), Point(-30, 6, 44), Point(-674, 560, 763), Point(500, 723, -460), Point(609, 671, -379), Point(-555, -800, 653), Point(-675, -892, -343), Point(697, -426, -610), Point(578, 704, 681), Point(493, 664, -388), Point(-671, -858, 530), Point(-667, 343, 800), Point(571, -461, -707), Point(-138, -166, 112), Point(-889, 563, -600), Point(646, -828, 498), Point(640, 759, 510), Point(-630, 509, 768), Point(-681, -892, -333), Point(673, -379, -804), Point(-742, -814, -386), Point(577, -820, 562)],
|
||||
vec![Point(-589, 542, 597), Point(605, -692, 669), Point(-500, 565, -823), Point(-660, 373, 557), Point(-458, -679, -417), Point(-488, 449, 543), Point(-626, 468, -788), Point(338, -750, -386), Point(528, -832, -391), Point(562, -778, 733), Point(-938, -730, 414), Point(543, 643, -506), Point(-524, 371, -870), Point(407, 773, 750), Point(-104, 29, 83), Point(378, -903, -323), Point(-778, -728, 485), Point(426, 699, 580), Point(-438, -605, -362), Point(-469, -447, -387), Point(509, 732, 623), Point(647, 635, -688), Point(-868, -804, 481), Point(614, -800, 639), Point(595, 780, -596)],
|
||||
vec![Point(727, 592, 562), Point(-293, -554, 779), Point(441, 611, -461), Point(-714, 465, -776), Point(-743, 427, -804), Point(-660, -479, -426), Point(832, -632, 460), Point(927, -485, -438), Point(408, 393, -506), Point(466, 436, -512), Point(110, 16, 151), Point(-258, -428, 682), Point(-393, 719, 612), Point(-211, -452, 876), Point(808, -476, -593), Point(-575, 615, 604), Point(-485, 667, 467), Point(-680, 325, -822), Point(-627, -443, -432), Point(872, -547, -609), Point(833, 512, 582), Point(807, 604, 487), Point(839, -516, 451), Point(891, -625, 532), Point(-652, -548, -490), Point(30, -46, -14)],
|
||||
];
|
||||
let overlapping = find_possibly_overlapping_scanners(&scanners);
|
||||
assert_eq!(overlapping, [(0, 1), (1, 3), (1, 4), (2, 4)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[rustfmt::skip]
|
||||
fn part1_find_transformation() {
|
||||
let scanner1 = vec![Point(404, -588, -901), Point(528, -643, 409), Point(-838, 591, 734), Point(390, -675, -793), Point(-537, -823, -458), Point(-485, -357, 347), Point(-345, -311, 381), Point(-661, -816, -575), Point(-876, 649, 763), Point(-618, -824, -621), Point(553, 345, -567), Point(474, 580, 667), Point(-447, -329, 318), Point(-584, 868, -557), Point(544, -627, -890), Point(564, 392, -477), Point(455, 729, 728), Point(-892, 524, 684), Point(-689, 845, -530), Point(423, -701, 434), Point(7, -33, -71), Point(630, 319, -379), Point(443, 580, 662), Point(-789, 900, -551), Point(459, -707, 401)];
|
||||
let scanner2 = vec![Point(686, 422, 578), Point(605, 423, 415), Point(515, 917, -361), Point(-336, 658, 858), Point(95, 138, 22), Point(-476, 619, 847), Point(-340, -569, -846), Point(567, -361, 727), Point(-460, 603, -452), Point(669, -402, 600), Point(729, 430, 532), Point(-500, -761, 534), Point(-322, 571, 750), Point(-466, -666, -811), Point(-429, -592, 574), Point(-355, 545, -477), Point(703, -491, -529), Point(-328, -685, 520), Point(413, 935, -424), Point(-391, 539, -444), Point(586, -435, 557), Point(-364, -763, -893), Point(807, -499, -711), Point(755, -354, -619), Point(553, 889, -390)];
|
||||
let (translation, rotation) = find_transformation(&scanner1, &scanner2).unwrap();
|
||||
assert_eq!(translation, Point(68, -1246, -43));
|
||||
assert_eq!(rotation, 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
203
src/main.rs
203
src/main.rs
@ -1,12 +1,4 @@
|
||||
mod day1;
|
||||
mod day2;
|
||||
mod day3;
|
||||
mod day4;
|
||||
mod day5;
|
||||
mod day6;
|
||||
mod day7;
|
||||
mod day8;
|
||||
mod day9;
|
||||
mod day10;
|
||||
mod day11;
|
||||
mod day12;
|
||||
@ -17,94 +9,143 @@ mod day16;
|
||||
mod day17;
|
||||
mod day18;
|
||||
mod day19;
|
||||
mod day2;
|
||||
mod day20;
|
||||
mod day21;
|
||||
mod day22;
|
||||
mod day23;
|
||||
mod day3;
|
||||
mod day4;
|
||||
mod day5;
|
||||
mod day6;
|
||||
mod day7;
|
||||
mod day8;
|
||||
mod day9;
|
||||
|
||||
use std::{env, process};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::{env, process};
|
||||
|
||||
fn run(day: i32, part: i32, input_filename: &str) {
|
||||
let mut input_file = File::open(input_filename)
|
||||
.expect(format!("Input file '{}' not found", input_filename).as_str());
|
||||
let mut input_file = File::open(input_filename)
|
||||
.expect(format!("Input file '{}' not found", input_filename).as_str());
|
||||
|
||||
let mut contents = String::new();
|
||||
input_file.read_to_string(&mut contents)
|
||||
.expect("Failed to read input file");
|
||||
let mut contents = String::new();
|
||||
input_file
|
||||
.read_to_string(&mut contents)
|
||||
.expect("Failed to read input file");
|
||||
|
||||
// Janky solution so that I could specify what I want to run
|
||||
let parse_error_msg = "Failed to parse input";
|
||||
match format!("{}.{}", day, part).as_str() {
|
||||
"1.1" => println!("{}", day1::part1(&day1::parse_input(&contents).expect(parse_error_msg))),
|
||||
"1.2" => println!("{}", day1::part2(&day1::parse_input(&contents).expect(parse_error_msg))),
|
||||
"2.1" => println!("{}", day2::part1(&day2::parse_input(&contents).expect(parse_error_msg))),
|
||||
"2.2" => println!("{}", day2::part2(&day2::parse_input(&contents).expect(parse_error_msg))),
|
||||
"3.1" => println!("{}", day3::part1(&day3::parse_input(&contents).expect(parse_error_msg))),
|
||||
"3.2" => println!("{}", day3::part2(&day3::parse_input(&contents).expect(parse_error_msg))),
|
||||
"4.1" => println!("{}", day4::part1(&day4::parse_input(&contents).expect(parse_error_msg))),
|
||||
"4.2" => println!("{}", day4::part2(&day4::parse_input(&contents).expect(parse_error_msg))),
|
||||
"5.1" => println!("{}", day5::part1(&day5::parse_input(&contents).expect(parse_error_msg))),
|
||||
"5.2" => println!("{}", day5::part2(&day5::parse_input(&contents).expect(parse_error_msg))),
|
||||
"6.1" => println!("{}", day6::part1(&day6::parse_input(&contents).expect(parse_error_msg))),
|
||||
"6.2" => println!("{}", day6::part2(&day6::parse_input(&contents).expect(parse_error_msg))),
|
||||
"7.1" => println!("{}", day7::part1(&day7::parse_input(&contents).expect(parse_error_msg))),
|
||||
"7.2" => println!("{}", day7::part2(&day7::parse_input(&contents).expect(parse_error_msg))),
|
||||
"8.1" => println!("{}", day8::part1(&day8::parse_input(&contents))),
|
||||
"8.2" => println!("{}", day8::part2(&day8::parse_input(&contents))),
|
||||
"9.1" => println!("{}", day9::part1(day9::parse_input(&contents))),
|
||||
"9.2" => println!("{}", day9::part2(day9::parse_input(&contents))),
|
||||
"10.1" => println!("{}", day10::part1(&day10::parse_input(&contents))),
|
||||
"10.2" => println!("{}", day10::part2(&day10::parse_input(&contents))),
|
||||
"11.1" => println!("{}", day11::part1(&day11::parse_input(&contents))),
|
||||
"11.2" => println!("{}", day11::part2(&day11::parse_input(&contents))),
|
||||
"12.1" => println!("{}", day12::part1(&day12::parse_input(&contents))),
|
||||
"12.2" => println!("{}", day12::part2(&day12::parse_input(&contents))),
|
||||
"13.1" => println!("{}", day13::part1(&day13::parse_input(&contents))),
|
||||
"13.2" => day13::part2(&day13::parse_input(&contents)),
|
||||
"14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
||||
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
||||
"15.1" => println!("{}", day15::part1(&day15::parse_input(&contents))),
|
||||
"15.2" => println!("{}", day15::part2(&mut day15::parse_input(&contents))),
|
||||
"16.1" => println!("{}", day16::part1(&day16::parse_input(&contents))),
|
||||
"16.2" => println!("{}", day16::part2(&day16::parse_input(&contents))),
|
||||
"17.1" => println!("{}", day17::part1(&day17::parse_input(&contents))),
|
||||
"17.2" => println!("{}", day17::part2(&day17::parse_input(&contents))),
|
||||
"18.1" => println!("{}", day18::part1(&day18::parse_input(&contents))),
|
||||
"18.2" => println!("{}", day18::part2(&day18::parse_input(&contents))),
|
||||
"19.1" => println!("{}", day19::part1(&day19::parse_input(&contents))),
|
||||
"19.2" => println!("{}", day19::part2(&day19::parse_input(&contents))),
|
||||
"20.1" => println!("{}", day20::part1(&day20::parse_input(&contents))),
|
||||
"20.2" => println!("{}", day20::part2(&day20::parse_input(&contents))),
|
||||
"21.1" => println!("{}", day21::part1(&day21::parse_input(&contents))),
|
||||
"21.2" => println!("{}", day21::part2(&day21::parse_input(&contents))),
|
||||
"22.1" => println!("{}", day22::part1(&day22::parse_input(&contents))),
|
||||
"22.2" => println!("{}", day22::part2(day22::parse_input(&contents))),
|
||||
"23.1" => println!("{}", day23::part1(&day23::parse_input(&contents))),
|
||||
"23.2" => println!("{}", day23::part2(&day23::parse_input(&contents))),
|
||||
_ => println!("Day {} part {} not found", day, part)
|
||||
}
|
||||
// Janky solution so that I could specify what I want to run
|
||||
let parse_error_msg = "Failed to parse input";
|
||||
match format!("{}.{}", day, part).as_str() {
|
||||
"1.1" => println!(
|
||||
"{}",
|
||||
day1::part1(&day1::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"1.2" => println!(
|
||||
"{}",
|
||||
day1::part2(&day1::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"2.1" => println!(
|
||||
"{}",
|
||||
day2::part1(&day2::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"2.2" => println!(
|
||||
"{}",
|
||||
day2::part2(&day2::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"3.1" => println!(
|
||||
"{}",
|
||||
day3::part1(&day3::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"3.2" => println!(
|
||||
"{}",
|
||||
day3::part2(&day3::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"4.1" => println!(
|
||||
"{}",
|
||||
day4::part1(&day4::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"4.2" => println!(
|
||||
"{}",
|
||||
day4::part2(&day4::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"5.1" => println!(
|
||||
"{}",
|
||||
day5::part1(&day5::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"5.2" => println!(
|
||||
"{}",
|
||||
day5::part2(&day5::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"6.1" => println!(
|
||||
"{}",
|
||||
day6::part1(&day6::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"6.2" => println!(
|
||||
"{}",
|
||||
day6::part2(&day6::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"7.1" => println!(
|
||||
"{}",
|
||||
day7::part1(&day7::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"7.2" => println!(
|
||||
"{}",
|
||||
day7::part2(&day7::parse_input(&contents).expect(parse_error_msg))
|
||||
),
|
||||
"8.1" => println!("{}", day8::part1(&day8::parse_input(&contents))),
|
||||
"8.2" => println!("{}", day8::part2(&day8::parse_input(&contents))),
|
||||
"9.1" => println!("{}", day9::part1(day9::parse_input(&contents))),
|
||||
"9.2" => println!("{}", day9::part2(day9::parse_input(&contents))),
|
||||
"10.1" => println!("{}", day10::part1(&day10::parse_input(&contents))),
|
||||
"10.2" => println!("{}", day10::part2(&day10::parse_input(&contents))),
|
||||
"11.1" => println!("{}", day11::part1(&day11::parse_input(&contents))),
|
||||
"11.2" => println!("{}", day11::part2(&day11::parse_input(&contents))),
|
||||
"12.1" => println!("{}", day12::part1(&day12::parse_input(&contents))),
|
||||
"12.2" => println!("{}", day12::part2(&day12::parse_input(&contents))),
|
||||
"13.1" => println!("{}", day13::part1(&day13::parse_input(&contents))),
|
||||
"13.2" => day13::part2(&day13::parse_input(&contents)),
|
||||
"14.1" => println!("{}", day14::part1(&day14::parse_input(&contents))),
|
||||
"14.2" => println!("{}", day14::part2(&day14::parse_input(&contents))),
|
||||
"15.1" => println!("{}", day15::part1(&day15::parse_input(&contents))),
|
||||
"15.2" => println!("{}", day15::part2(&mut day15::parse_input(&contents))),
|
||||
"16.1" => println!("{}", day16::part1(&day16::parse_input(&contents))),
|
||||
"16.2" => println!("{}", day16::part2(&day16::parse_input(&contents))),
|
||||
"17.1" => println!("{}", day17::part1(&day17::parse_input(&contents))),
|
||||
"17.2" => println!("{}", day17::part2(&day17::parse_input(&contents))),
|
||||
"18.1" => println!("{}", day18::part1(&day18::parse_input(&contents))),
|
||||
"18.2" => println!("{}", day18::part2(&day18::parse_input(&contents))),
|
||||
"19.1" => println!("{}", day19::part1(&day19::parse_input(&contents))),
|
||||
"19.2" => println!("{}", day19::part2(&day19::parse_input(&contents))),
|
||||
"20.1" => println!("{}", day20::part1(&day20::parse_input(&contents))),
|
||||
"20.2" => println!("{}", day20::part2(&day20::parse_input(&contents))),
|
||||
"21.1" => println!("{}", day21::part1(&day21::parse_input(&contents))),
|
||||
"21.2" => println!("{}", day21::part2(&day21::parse_input(&contents))),
|
||||
"22.1" => println!("{}", day22::part1(&day22::parse_input(&contents))),
|
||||
"22.2" => println!("{}", day22::part2(day22::parse_input(&contents))),
|
||||
"23.1" => println!("{}", day23::part1(&day23::parse_input(&contents))),
|
||||
"23.2" => println!("{}", day23::part2(&day23::parse_input(&contents))),
|
||||
_ => println!("Day {} part {} not found", day, part),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() < 3 {
|
||||
println!("Usage: {} <day> <part> [input-file]", args[0]);
|
||||
process::exit(0);
|
||||
}
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() < 3 {
|
||||
println!("Usage: {} <day> <part> [input-file]", args[0]);
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
let day = args[1].parse::<i32>()
|
||||
.expect("Failed to parse day");
|
||||
let day = args[1].parse::<i32>().expect("Failed to parse day");
|
||||
|
||||
let part = args[2].parse::<i32>()
|
||||
.expect("Failed to parse part");
|
||||
let part = args[2].parse::<i32>().expect("Failed to parse part");
|
||||
|
||||
let input_filename;
|
||||
if args.len() > 3 {
|
||||
input_filename = args[3].clone();
|
||||
} else {
|
||||
input_filename = format!("input/{}.txt", day);
|
||||
}
|
||||
run(day, part, &input_filename);
|
||||
let input_filename;
|
||||
if args.len() > 3 {
|
||||
input_filename = args[3].clone();
|
||||
} else {
|
||||
input_filename = format!("input/{}.txt", day);
|
||||
}
|
||||
run(day, part, &input_filename);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user