Advertisement
Guest User

Untitled

a guest
Dec 24th, 2020
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.65 KB | None | 0 0
  1. use std::env;
  2. use std::io::{self, prelude::*, BufReader};
  3. use std::fs::File;
  4. use std::collections::HashMap;
  5.  
  6. extern crate regex;
  7. use regex::Regex;
  8.  
  9. extern crate point2d;
  10. use point2d::point2d::Point2D;
  11.  
  12. // Hex Grids: https://www.redblobgames.com/grids/hexagons/
  13.  
  14. #[macro_use] extern crate lazy_static;
  15. lazy_static! {
  16.     static ref RE_PT: Regex = {
  17.         Regex::new(r"^\((\-*\d),(\-*\d)\)$").unwrap()
  18.     };
  19. }
  20.  
  21. fn coordinates(input: &str) -> Point2D {
  22.     //let re = Regex::new(r"^\((\-*\d),(\-*\d)\)$").unwrap();
  23.     let caps = RE_PT.captures(&input).unwrap();
  24.     Point2D { x: caps[1].parse().unwrap(), y: caps[2].parse().unwrap() }
  25. }
  26.  
  27. fn neighbors(pt: &Point2D) -> Vec<Point2D> {
  28.     vec![Point2D{ x: pt.x  , y: pt.y-1 },  // nw
  29.          Point2D{ x: pt.x+1, y: pt.y-1 },  // ne
  30.          Point2D{ x: pt.x+1, y: pt.y   },  // e
  31.          Point2D{ x: pt.x  , y: pt.y+1 },  // se
  32.          Point2D{ x: pt.x-1, y: pt.y+1 },  // sw
  33.          Point2D{ x: pt.x-1, y: pt.y   }]  // w
  34. }
  35.  
  36. fn adjacent_black(pt: &Point2D, map: &HashMap<Point2D,bool>) -> usize {
  37.     neighbors(&pt).iter().map(|n| map.get(&n).unwrap_or(&false)).filter(|n| *n == &true).count()
  38. }
  39.  
  40. fn map_extents(map: &HashMap<Point2D,bool>) -> (i64,i64,i64,i64) {
  41.     let xmin = &map.keys().map(|&pt| pt.x).min().unwrap();
  42.     let ymin = &map.keys().map(|&pt| pt.y).min().unwrap();
  43.     let xmax = &map.keys().map(|&pt| pt.x).max().unwrap();
  44.     let ymax = &map.keys().map(|&pt| pt.y).max().unwrap();
  45.     (*xmin,*ymin,*xmax,*ymax)
  46. }
  47.  
  48. fn expand_map(map: &mut HashMap<Point2D,bool>) {
  49.     let temp = map.clone();
  50.     for (pt,_) in temp.iter() {
  51.         for neighbor in neighbors(pt) {
  52.             match map.get(&neighbor) {
  53.                 Some(_) => {},
  54.                 None => { map.insert(neighbor, false); }
  55.             }
  56.         }
  57.     }
  58. }
  59.  
  60. fn day24(input: &str) -> io::Result<()> {
  61.     let file = File::open(input).expect("Input file not found.");
  62.     let reader = BufReader::new(file);
  63.  
  64.     let input: Vec<String> = match reader.lines().collect() {
  65.         Err(err) => panic!("Unknown error reading input: {}", err),
  66.         Ok(result) => result,
  67.     };
  68.  
  69.     // Build map
  70.     let mut map: HashMap<Point2D,bool> = HashMap::new();
  71.     for line in input {
  72.         let line = line
  73.             .replace("se","(0,1)+")
  74.             .replace("sw","(-1,1)+")
  75.             .replace("nw","(0,-1)+")
  76.             .replace("ne","(1,-1)+")
  77.             .replace("e","(1,0)+")
  78.             .replace("w","(-1,0)+");
  79.         let line = format!("{}(0,0)",line);
  80.  
  81.         let pt = line.split("+").map(|coord| coordinates(coord)).sum::<Point2D>();
  82.         let x = map.entry(pt).or_insert(false);
  83.         *x = !*x;
  84.     }
  85.  
  86.     // Part 1
  87.     let part1 = map.iter().filter(|(_,t)| *t == &true).count();
  88.     println!("Part 1: {}", part1); // 500
  89.  
  90.     // Part 2
  91.     for _ in 0..100 {
  92.         expand_map(&mut map);
  93.         let current = map.clone();
  94.         let (xmin,ymin,xmax,ymax) = map_extents(&current);
  95.         for y in ymin..=ymax {
  96.             for x in xmin..=xmax {
  97.                 let pt = Point2D { x: x, y: y};
  98.                 let adjacent_black = adjacent_black(&pt,&current);
  99.                 match &current.get(&Point2D { x: x, y: y}) {
  100.                     Some(true) => {
  101.                         // Black tile
  102.                         if adjacent_black == 0 || adjacent_black > 2 { map.insert(pt,false); }
  103.                     },
  104.                     _ => {
  105.                         // White tile
  106.                         if adjacent_black == 2 { map.insert(pt,true); }
  107.                     },
  108.                 }
  109.             }
  110.         }
  111.     }
  112.  
  113.     // Part 2
  114.     let part2 = map.iter().filter(|(_,t)| *t == &true).count();
  115.     println!("Part 2: {}", part2); // 4280
  116.  
  117.     Ok(())
  118. }
  119.  
  120. fn main() {
  121.     let args: Vec<String> = env::args().collect();
  122.     let filename = &args[1];
  123.     day24(&filename).unwrap();
  124. }
  125.  
  126. //#[macro_use]
  127. //extern crate text_io;
  128.  
  129. pub mod point2d {
  130.     use std::ops::{Add,AddAssign};
  131.     use std::iter::Sum;
  132.     extern crate num_complex;
  133.     use num_complex::Complex;
  134.  
  135.     #[derive(Debug, Copy, Clone, Hash)]
  136.     pub struct Point2D {
  137.         pub x: i64,
  138.         pub y: i64,
  139.     }
  140.  
  141.     impl Point2D {
  142.         pub fn new(x: i64, y: i64) -> Self {
  143.             Self {
  144.                 x: x, y: y,
  145.             }
  146.         }
  147.         pub fn zeros() -> Self {
  148.             Self {
  149.                 x: 0, y: 0,
  150.             }
  151.         }
  152.         pub fn from_complex(cmplx: Complex<i64>) -> Self {
  153.             Self {
  154.                 x: cmplx.re, y: cmplx.im,
  155.             }
  156.         }
  157.         pub fn as_complex(self) -> Complex<i64> {
  158.             Complex::new(self.x, self.y)
  159.         }
  160.         pub fn as_tuple(self) -> (i64,i64) {
  161.             (self.x, self.y)
  162.         }
  163.     }
  164.     impl Add for Point2D {
  165.         type Output = Self;
  166.         fn add(self, other: Self) -> Self {
  167.             Self {
  168.                 x: self.x + other.x,
  169.                 y: self.y + other.y,
  170.             }
  171.         }
  172.     }
  173.     impl AddAssign for Point2D {
  174.         fn add_assign(&mut self, other: Self) {
  175.             *self = Self {
  176.                 x: self.x + other.x,
  177.                 y: self.y + other.y,
  178.             };
  179.         }
  180.     }
  181.     impl PartialEq for Point2D {
  182.         fn eq(&self, other: &Self) -> bool {
  183.             self.x == other.x && self.y == other.y
  184.         }
  185.     }
  186.     impl Eq for Point2D {}
  187.  
  188.     impl Sum for Point2D {
  189.         fn sum<I>(iter: I) -> Self
  190.         where
  191.             I: Iterator<Item = Self>,
  192.         {
  193.             iter.fold(Self { x: 0, y: 0 }, |a, b| Self {
  194.                 x: a.x + b.x,
  195.                 y: a.y + b.y,
  196.             })
  197.         }
  198.     }
  199.  
  200. }
  201.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement