Advertisement
Guest User

AoC day19

a guest
Dec 20th, 2021
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 11.36 KB | None | 0 0
  1. use std::collections::{HashMap, HashSet};
  2. use itertools::Itertools;
  3. use pathfinding::num_traits::{abs, pow};
  4. use pathfinding::prelude::absdiff;
  5. use std::borrow::Borrow;
  6.  
  7.  
  8. fn euclid_dist(first: &(i64, i64, i64), second: &(i64, i64, i64)) -> i64 {
  9.     pow(first.0 - second.0, 2) + pow(first.1 - second.1, 2) + pow(first.2 - second.2, 2)
  10. }
  11.  
  12. fn rotation_matrix(a: &(i64, i64, i64)) -> Vec<((i64, i64, i64))> {
  13.     let &(x,y,z) = a;
  14.     vec![
  15.         (x, y, z),
  16.         (x, z, -y),
  17.         (x, -y, -z),
  18.         (x, -z, y),
  19.         (y, x, -z),
  20.         (y, z, x),
  21.         (y, -x, z),
  22.         (y, -z, -x),
  23.         (z, x, y),
  24.         (z, y, -x),
  25.         (z, -x, -y),
  26.         (z, -y, x),
  27.         (-x, y, -z),
  28.         (-x, z, y),
  29.         (-x, -y, z),
  30.         (-x, -z, -y),
  31.         (-y, x, z),
  32.         (-y, z, -x),
  33.         (-y, -x, -z),
  34.         (-y, -z, x),
  35.         (-z, x, -y),
  36.         (-z, y, x),
  37.         (-z, -x, y),
  38.         (-z, -y, -x),
  39.     ]
  40. }
  41.  
  42. fn rotate_and_translate_single(a: &(i64, i64, i64), rot: usize, b: &(i64, i64, i64)) -> (i64, i64, i64) {
  43.    let &(x,y, z) = a;
  44.    match rot {
  45.         0 => (x + b.0, y + b.1, z + b.2),
  46.         1 => (x + b.0, z + b.1, -y + b.2),
  47.         2 => (x + b.0, -y + b.1, -z + b.2),
  48.         3 => (x + b.0, -z + b.1, y + b.2),
  49.         4 => (y + b.0, x + b.1, -z + b.2),
  50.         5 => (y + b.0, z + b.1, x + b.2),
  51.         6 => (y + b.0, -x + b.1, z + b.2),
  52.         7 => (y + b.0, -z + b.1, -x + b.2),
  53.         8 => (z + b.0, x + b.1, y + b.2),
  54.         9 => (z + b.0, y + b.1, -x + b.2),
  55.         10 => (z + b.0, -x + b.1, -y + b.2),
  56.         11 => (z + b.0, -y + b.1, x + b.2),
  57.         12 => (-x + b.0, y + b.1, -z + b.2),
  58.         13 => (-x + b.0, z + b.1, y + b.2),
  59.         14 => (-x + b.0, -y + b.1, z + b.2),
  60.         15 => (-x + b.0, -z + b.1, -y + b.2),
  61.         16 => (-y + b.0, x + b.1, z + b.2),
  62.         17 => (-y + b.0, z + b.1, -x + b.2),
  63.         18 => (-y + b.0, -x + b.1, -z + b.2),
  64.         19 => (-y + b.0, -z + b.1, x + b.2),
  65.         20 => (-z + b.0, x + b.1, -y + b.2),
  66.         21 => (-z + b.0, y + b.1, x + b.2),
  67.         22 => (-z + b.0, -x + b.1, y + b.2),
  68.         23 => (-z + b.0, -y + b.1, -x + b.2),
  69.         _ => unreachable!(),
  70.     }
  71. }
  72.  
  73. pub fn day19_1UNSTABLE(){
  74.     let mut inputs: Vec<HashSet<(i64, i64, i64)>> = Vec::new();
  75.     include_str!("../temp19").split("\r\n\r\n").for_each(|x| {
  76.         let mut inner:HashSet<(i64,i64,i64)> = HashSet::new();
  77.         x.lines().skip(1).for_each(|x| {
  78.             inner.insert(x.split(',').map(|x| x.parse().unwrap()).collect_tuple().unwrap());
  79.         });
  80.         inputs.push(inner);
  81.     });
  82.     let mut all_distances = Vec::new();
  83.     let mut all_distances_dict = Vec::new();
  84.  
  85.     for input in &inputs {
  86.         let mut distances = HashSet::new();
  87.         let mut distances_dict = HashMap::new();
  88.         for (&first, &second) in input.iter().tuple_combinations() {
  89.             let euclid_dist : i64 = euclid_dist(&first, &second);
  90.             //let man_dist : i64 = absdiff(first.0, second.0) + absdiff(first.1, second.1) + absdiff(first.2, second.2); //euclid might be sufficient?
  91.             distances.insert(euclid_dist);
  92.             distances_dict.insert(euclid_dist, (first, second));
  93.         }
  94.         all_distances.push(distances);
  95.         all_distances_dict.push(distances_dict);
  96.     }
  97.     loop {
  98.         let mut to_stich = ((0), (Vec::new()));
  99.         let first = &all_distances[0];
  100.         for (i2, second) in all_distances.iter().enumerate().skip(1) {
  101.             let intersection = first.intersection(second).collect_vec();
  102.             if intersection.len() >= 66 { //66 not 12 since 12 * 11 / 2 = 66 and thats the amount of intersections that they would have
  103.                 //stitch the first matching thing to the first one
  104.                 to_stich = (i2, intersection);
  105.                 break;
  106.             }
  107.         }
  108.         let first1 = &all_distances_dict[0];
  109.         let mut translation = HashMap::new();
  110.         for dists in to_stich.1 {
  111.             //find out if these two lines (formed by two points) are translations of each other (this doesnt work right now cause I'm not accounting for rotations)
  112.             let (p1_1, p1_2) = first1.get(dists).unwrap();
  113.             let (p2_1, p2_2) = all_distances_dict[to_stich.0].get(dists).unwrap();
  114.             //do another loop for rotations
  115.             rotation_matrix(&p2_1).iter().zip(rotation_matrix(&p2_2)).enumerate().for_each(|(i, (rp2_1, rp2_2))|
  116.                 {
  117.                     let dist_11 = euclid_dist(&rp2_1, p1_1);
  118.                     let dist_22 = euclid_dist(&rp2_2, p1_2);
  119.                     let dist_12 = euclid_dist(p1_1, &rp2_2);
  120.                     let dist_21 = euclid_dist(p1_2, &rp2_1);
  121.                     if absdiff(dist_11, dist_22) == 0 {
  122.                         //p1_1 is the same point as p2_1
  123.                         let counter = translation.entry(((p1_1.0 - rp2_1.0, p1_1.1 - rp2_1.1, p1_1.2 - rp2_1.2), i)).or_insert(0);
  124.                         *counter += 1;
  125.                     } else if absdiff(dist_12, dist_21) == 0 {
  126.                         //other match
  127.                         let counter = translation.entry(((p1_1.0 - rp2_2.0, p1_1.1 - rp2_2.1, p1_1.2 - rp2_2.2), i)).or_insert(0);
  128.                         *counter += 1;
  129.                     }
  130.                 });
  131.         };
  132.         let x = translation.iter().filter(|(x, &y)| y >= 66).next().unwrap(); //this assumes something to stitch
  133.         let insert = inputs[to_stich.0].iter().map(|y| {
  134.             rotate_and_translate_single(y, x.0.1, &x.0.0)
  135.         }).collect_vec();
  136.  
  137.         inputs[0].extend(&mut insert.iter());
  138.         //if that was the only element left break out of the loop.
  139.         if inputs.len() == 2 {
  140.             break;
  141.         }
  142.         //remove from everywhere it needs to be
  143.         inputs.remove(to_stich.0);
  144.         all_distances_dict.remove(to_stich.0);
  145.         all_distances.remove(to_stich.0);
  146.         //recalculate the thing
  147.         let mut distances = HashSet::new();
  148.         let mut distances_dict = HashMap::new();
  149.         for (&first, &second) in inputs[0].iter().tuple_combinations() {
  150.             let euclid_dist: i64 = euclid_dist(&first, &second);
  151.             //let man_dist: i64 = absdiff(first.0, second.0) + absdiff(first.1, second.1) + absdiff(first.2, second.2); //euclid might be sufficient?
  152.             distances.insert(euclid_dist);
  153.             distances_dict.insert(euclid_dist, (first, second));
  154.         }
  155.         all_distances[0] = distances;
  156.         all_distances_dict[0] = distances_dict;
  157.     }
  158.     println!("ANSWER {}", inputs[0].len());
  159.     return;
  160. }
  161.  
  162.  
  163. pub fn day19_2stable() {
  164.     let mut inputs: Vec<HashSet<(i64, i64, i64)>> = Vec::new();
  165.     include_str!("../temp19").split("\r\n\r\n").for_each(|x| {
  166.         let mut inner:HashSet<(i64,i64,i64)> = HashSet::new();
  167.         x.lines().skip(1).for_each(|x| {
  168.             inner.insert(x.split(',').map(|x| x.parse().unwrap()).collect_tuple().unwrap());
  169.         });
  170.         inputs.push(inner);
  171.     });
  172.     let mut all_distances = Vec::new();
  173.     let mut all_distances_dict = Vec::new();
  174.  
  175.     for input in &inputs {
  176.         let mut distances = HashSet::new();
  177.         let mut distances_dict = HashMap::new();
  178.         for (&first, &second) in input.iter().tuple_combinations() {
  179.             let euclid_dist : i64 = euclid_dist(&first, &second);
  180.             let man_dist : i64 = absdiff(first.0, second.0) + absdiff(first.1, second.1) + absdiff(first.2, second.2); //euclid might be sufficient?
  181.             distances.insert((euclid_dist, man_dist));
  182.             distances_dict.insert((euclid_dist, man_dist), (first, second));
  183.         }
  184.         all_distances.push(distances);
  185.         all_distances_dict.push(distances_dict);
  186.     }
  187.     let mut rel_dists = vec![(0i64, 0i64, 0i64)];
  188.     loop {
  189.         let mut to_stich = ((0), (Vec::new()));
  190.         let first = &all_distances[0];
  191.         for (i2, second) in all_distances.iter().enumerate().skip(1) {
  192.             let intersection = first.intersection(second).collect_vec();
  193.             if intersection.len() >= 66 { //66 not 12 since 12 * 11 / 2 = 66 and thats the amount of intersections that they would have
  194.                 //stitch the first matching thing to the first one
  195.                 to_stich = (i2, intersection);
  196.                 break;
  197.             }
  198.         }
  199.         let mut translation = HashMap::new();
  200.         let thing = &all_distances_dict[0];
  201.         for dists in to_stich.1 {
  202.             //find out if these two lines (formed by two points) are translations of each other (this doesnt work right now cause I'm not accounting for rotations)
  203.             let (p1_1, p1_2) = thing.get(dists).unwrap();
  204.             let (p2_1, p2_2) = all_distances_dict[to_stich.0].get(dists).unwrap();
  205.             //do another loop for rotations
  206.             rotation_matrix(&p2_1).iter().zip(rotation_matrix(&p2_2)).enumerate().for_each(|(i, (rp2_1, rp2_2))|
  207.                 {
  208.                     let dist_11 = euclid_dist(&rp2_1, p1_1);
  209.                     let dist_22 = euclid_dist(&rp2_2, p1_2);
  210.                     let dist_12 = euclid_dist(p1_1, &rp2_2);
  211.                     let dist_21 = euclid_dist(p1_2, &rp2_1);
  212.                     if absdiff(dist_11, dist_22) == 0 {
  213.                         //p1_1 is the same point as p2_1
  214.                         let counter = translation.entry(((p1_1.0 - rp2_1.0, p1_1.1 - rp2_1.1, p1_1.2 - rp2_1.2), i)).or_insert(0);
  215.                         *counter += 1;
  216.                     } else if absdiff(dist_12, dist_21) == 0 {
  217.                         //other match
  218.                         let counter = translation.entry(((p1_1.0 - rp2_2.0, p1_1.1 - rp2_2.1, p1_1.2 - rp2_2.2), i)).or_insert(0);
  219.                         *counter += 1;
  220.                     }
  221.                 });
  222.         };
  223.  
  224.         let x = translation.iter().filter(|(x, &y)| y >= 66).next().unwrap(); //this assumes something to stitch
  225.         rel_dists.push(x.0.0);
  226.         //if that was the only element left break out of the loop. in part 2 we can leave earlier because we don't have to stitch.
  227.         //if inputs.len() == 2 {
  228.         //    break;
  229.         //}
  230.         let insert = inputs[to_stich.0].iter().map(|y| {
  231.             rotate_and_translate_single(y, x.0.1, &x.0.0)
  232.         }).collect_vec();
  233.  
  234.         inputs[0].extend(&mut insert.iter());
  235.  
  236.         if inputs.len() == 2 {
  237.             break;
  238.         }
  239.         //remove from everywhere it needs to be
  240.         inputs.remove(to_stich.0);
  241.         all_distances_dict.remove(to_stich.0);
  242.         all_distances.remove(to_stich.0);
  243.         //recalculate the thing
  244.         let mut distances = HashSet::new();
  245.         let mut distances_dict = HashMap::new();
  246.         for (&first, &second) in inputs[0].iter().tuple_combinations() {
  247.             let euclid_dist: i64 = euclid_dist(&first, &second);
  248.             let man_dist: i64 = absdiff(first.0, second.0) + absdiff(first.1, second.1) + absdiff(first.2, second.2); //euclid might be sufficient?
  249.             distances.insert((euclid_dist, man_dist));
  250.             distances_dict.insert((euclid_dist, man_dist), (first, second));
  251.         }
  252.         all_distances[0] = distances;
  253.         all_distances_dict[0] = distances_dict;
  254.     }
  255.     println!("ANSWER PART 1 {}", inputs[0].len());
  256.     println!("ANSWER PART 2 {}", rel_dists.iter().tuple_combinations().map(|((x1, y1, z1), (x2, y2, z2))| abs(x1 - x2) + abs(y1 - y2) + abs(z1 - z2)).max().unwrap());
  257.  
  258.     return;
  259. }
  260.  
  261.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement