Advertisement
tech_hutch

Untitled

Dec 11th, 2018
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.54 KB | None | 0 0
  1. extern crate chrono;
  2. extern crate regex;
  3.  
  4. use std::collections::HashMap;
  5. use std::fs;
  6. use std::ops::Not;
  7. use regex::Regex;
  8. use chrono::DateTime;
  9. use chrono::offset::Utc;
  10.  
  11. struct Point {
  12.     position: (i64, i64),
  13.     velocity: (i16, i16),
  14. }
  15.  
  16. impl Point {
  17.     fn apply_velocity(&mut self) {
  18.         let Self { position, velocity } = self;
  19.         position.0 += velocity.0 as i64;
  20.         position.1 += velocity.1 as i64;
  21.     }
  22. }
  23.  
  24. fn fmt_secs(start: DateTime<Utc>) -> String {
  25.     format!("⏱ {}s", (Utc::now() - start).num_milliseconds() as f64 / 1000_f64)
  26. }
  27.  
  28. fn main() {
  29.     const INPUT: &str = include_str!("../../input");
  30. //     const INPUT: &str = "position=< 9,  1> velocity=< 0,  2>
  31. // position=< 7,  0> velocity=<-1,  0>
  32. // position=< 3, -2> velocity=<-1,  1>
  33. // position=< 6, 10> velocity=<-2, -1>
  34. // position=< 2, -4> velocity=< 2,  2>
  35. // position=<-6, 10> velocity=< 2, -2>
  36. // position=< 1,  8> velocity=< 1, -1>
  37. // position=< 1,  7> velocity=< 1,  0>
  38. // position=<-3, 11> velocity=< 1, -2>
  39. // position=< 7,  6> velocity=<-1, -1>
  40. // position=<-2,  3> velocity=< 1,  0>
  41. // position=<-4,  3> velocity=< 2,  0>
  42. // position=<10, -3> velocity=<-1,  1>
  43. // position=< 5, 11> velocity=< 1, -2>
  44. // position=< 4,  7> velocity=< 0, -1>
  45. // position=< 8, -2> velocity=< 0,  1>
  46. // position=<15,  0> velocity=<-2,  0>
  47. // position=< 1,  6> velocity=< 1,  0>
  48. // position=< 8,  9> velocity=< 0, -1>
  49. // position=< 3,  3> velocity=<-1,  1>
  50. // position=< 0,  5> velocity=< 0, -1>
  51. // position=<-2,  2> velocity=< 2,  0>
  52. // position=< 5, -2> velocity=< 1,  2>
  53. // position=< 1,  4> velocity=< 2,  1>
  54. // position=<-2,  7> velocity=< 2, -2>
  55. // position=< 3,  6> velocity=<-1, -1>
  56. // position=< 5,  0> velocity=< 1,  0>
  57. // position=<-6,  0> velocity=< 2,  0>
  58. // position=< 5,  9> velocity=< 1, -2>
  59. // position=<14,  7> velocity=<-2,  0>
  60. // position=<-3,  6> velocity=< 2, -1>";
  61.  
  62.     let time = Utc::now();
  63.     let re = Regex::new(r"-?\d+").unwrap();
  64.     let points: Vec<Point> = INPUT
  65.         .trim()
  66.         .lines()
  67.         .map(|line| {
  68.             if let &[x, y, dx, dy] = &re
  69.                 .find_iter(line)
  70.                 .map(|mat| mat.as_str().parse::<i64>().unwrap())
  71.                 .collect::<Vec<i64>>()[..] {
  72.                 Point {
  73.                     position: (x, y),
  74.                     velocity: (dx as i16, dy as i16),
  75.                 }
  76.             } else { panic!(); }
  77.         })
  78.         .collect();
  79.     println!("Prep: {}", fmt_secs(time));
  80.  
  81.     let time = Utc::now();
  82.     part1(points);
  83.     println!("Part 1 {}", fmt_secs(time));
  84. }
  85.  
  86. fn part1(mut points: Vec<Point>) {
  87.     let x_values: Vec<i64> = points
  88.         .iter()
  89.         .map(|&Point { position: (x, _), .. }| x)
  90.         .collect();
  91.     let y_values: Vec<i64> = points
  92.         .iter()
  93.         .map(|&Point { position: (_, y), .. }| y)
  94.         .collect();
  95.     let top_left = (
  96.         *x_values.iter().min().unwrap(),
  97.         *y_values.iter().min().unwrap(),
  98.     );
  99.     let bottom_right = (
  100.         *x_values.iter().max().unwrap(),
  101.         *y_values.iter().max().unwrap(),
  102.     );
  103.  
  104.     for sec in 0.. {
  105.         if is_message(&points) {
  106.             print_grid(sec, &points, top_left, bottom_right);
  107.             break;
  108.         }
  109.         for point in &mut points { point.apply_velocity(); }
  110.     }
  111. }
  112.  
  113. fn is_message(points: &Vec<Point>) -> bool {
  114.     const TOO_MANY_LONELY_POINTS: usize = 1000;
  115.     // Check how many points are not surrounded by points on any side
  116.     points
  117.         .iter()
  118.         .filter(|Point { position: pos, .. }|
  119.             [
  120.                         (pos.0, pos.1 - 1),
  121.                 (pos.0 - 1, pos.1), (pos.0 + 1, pos.1),
  122.                         (pos.0, pos.1 + 1),
  123.             ]
  124.             .into_iter()
  125.             .any(|p| points.iter().any(|Point { position, .. }| position == p))
  126.             .not())
  127.         .count() < TOO_MANY_LONELY_POINTS
  128. }
  129.  
  130. fn print_grid(sec: u32, points: &Vec<Point>, top_left: (i64, i64), bottom_right: (i64, i64)) {
  131.     let grid: HashMap<(i64, i64), char> = points
  132.         .into_iter()
  133.         .map(|&Point { position, .. }| (
  134.             position,
  135.             '#',
  136.         ))
  137.         .collect();
  138.     let dot = &'.';
  139.  
  140.     let mut out = "".to_string();
  141.     out += &format!("After {} second(s):\n", sec);
  142.     for y in top_left.1 ..= bottom_right.1 {
  143.         for x in top_left.0 ..= bottom_right.0 {
  144.             out += &format!("{}", grid.get(&(x, y)).unwrap_or(dot));
  145.         }
  146.         out += "\n";
  147.     }
  148.     out += "\n";
  149.  
  150.     fs::write("../out.txt", out).expect("unable to write file");
  151. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement