Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::env;
- use std::io::{self, prelude::*, BufReader};
- use std::fs::File;
- use std::collections::HashMap;
- extern crate regex;
- use regex::Regex;
- extern crate point2d;
- use point2d::point2d::Point2D;
- // Hex Grids: https://www.redblobgames.com/grids/hexagons/
- #[macro_use] extern crate lazy_static;
- lazy_static! {
- static ref RE_PT: Regex = {
- Regex::new(r"^\((\-*\d),(\-*\d)\)$").unwrap()
- };
- }
- fn coordinates(input: &str) -> Point2D {
- //let re = Regex::new(r"^\((\-*\d),(\-*\d)\)$").unwrap();
- let caps = RE_PT.captures(&input).unwrap();
- Point2D { x: caps[1].parse().unwrap(), y: caps[2].parse().unwrap() }
- }
- fn neighbors(pt: &Point2D) -> Vec<Point2D> {
- vec![Point2D{ x: pt.x , y: pt.y-1 }, // nw
- Point2D{ x: pt.x+1, y: pt.y-1 }, // ne
- Point2D{ x: pt.x+1, y: pt.y }, // e
- Point2D{ x: pt.x , y: pt.y+1 }, // se
- Point2D{ x: pt.x-1, y: pt.y+1 }, // sw
- Point2D{ x: pt.x-1, y: pt.y }] // w
- }
- fn adjacent_black(pt: &Point2D, map: &HashMap<Point2D,bool>) -> usize {
- neighbors(&pt).iter().map(|n| map.get(&n).unwrap_or(&false)).filter(|n| *n == &true).count()
- }
- fn map_extents(map: &HashMap<Point2D,bool>) -> (i64,i64,i64,i64) {
- let xmin = &map.keys().map(|&pt| pt.x).min().unwrap();
- let ymin = &map.keys().map(|&pt| pt.y).min().unwrap();
- let xmax = &map.keys().map(|&pt| pt.x).max().unwrap();
- let ymax = &map.keys().map(|&pt| pt.y).max().unwrap();
- (*xmin,*ymin,*xmax,*ymax)
- }
- fn expand_map(map: &mut HashMap<Point2D,bool>) {
- let temp = map.clone();
- for (pt,_) in temp.iter() {
- for neighbor in neighbors(pt) {
- match map.get(&neighbor) {
- Some(_) => {},
- None => { map.insert(neighbor, false); }
- }
- }
- }
- }
- fn day24(input: &str) -> io::Result<()> {
- let file = File::open(input).expect("Input file not found.");
- let reader = BufReader::new(file);
- let input: Vec<String> = match reader.lines().collect() {
- Err(err) => panic!("Unknown error reading input: {}", err),
- Ok(result) => result,
- };
- // Build map
- let mut map: HashMap<Point2D,bool> = HashMap::new();
- for line in input {
- let line = line
- .replace("se","(0,1)+")
- .replace("sw","(-1,1)+")
- .replace("nw","(0,-1)+")
- .replace("ne","(1,-1)+")
- .replace("e","(1,0)+")
- .replace("w","(-1,0)+");
- let line = format!("{}(0,0)",line);
- let pt = line.split("+").map(|coord| coordinates(coord)).sum::<Point2D>();
- let x = map.entry(pt).or_insert(false);
- *x = !*x;
- }
- // Part 1
- let part1 = map.iter().filter(|(_,t)| *t == &true).count();
- println!("Part 1: {}", part1); // 500
- // Part 2
- for _ in 0..100 {
- expand_map(&mut map);
- let current = map.clone();
- let (xmin,ymin,xmax,ymax) = map_extents(¤t);
- for y in ymin..=ymax {
- for x in xmin..=xmax {
- let pt = Point2D { x: x, y: y};
- let adjacent_black = adjacent_black(&pt,¤t);
- match ¤t.get(&Point2D { x: x, y: y}) {
- Some(true) => {
- // Black tile
- if adjacent_black == 0 || adjacent_black > 2 { map.insert(pt,false); }
- },
- _ => {
- // White tile
- if adjacent_black == 2 { map.insert(pt,true); }
- },
- }
- }
- }
- }
- // Part 2
- let part2 = map.iter().filter(|(_,t)| *t == &true).count();
- println!("Part 2: {}", part2); // 4280
- Ok(())
- }
- fn main() {
- let args: Vec<String> = env::args().collect();
- let filename = &args[1];
- day24(&filename).unwrap();
- }
- //#[macro_use]
- //extern crate text_io;
- pub mod point2d {
- use std::ops::{Add,AddAssign};
- use std::iter::Sum;
- extern crate num_complex;
- use num_complex::Complex;
- #[derive(Debug, Copy, Clone, Hash)]
- pub struct Point2D {
- pub x: i64,
- pub y: i64,
- }
- impl Point2D {
- pub fn new(x: i64, y: i64) -> Self {
- Self {
- x: x, y: y,
- }
- }
- pub fn zeros() -> Self {
- Self {
- x: 0, y: 0,
- }
- }
- pub fn from_complex(cmplx: Complex<i64>) -> Self {
- Self {
- x: cmplx.re, y: cmplx.im,
- }
- }
- pub fn as_complex(self) -> Complex<i64> {
- Complex::new(self.x, self.y)
- }
- pub fn as_tuple(self) -> (i64,i64) {
- (self.x, self.y)
- }
- }
- impl Add for Point2D {
- type Output = Self;
- fn add(self, other: Self) -> Self {
- Self {
- x: self.x + other.x,
- y: self.y + other.y,
- }
- }
- }
- impl AddAssign for Point2D {
- fn add_assign(&mut self, other: Self) {
- *self = Self {
- x: self.x + other.x,
- y: self.y + other.y,
- };
- }
- }
- impl PartialEq for Point2D {
- fn eq(&self, other: &Self) -> bool {
- self.x == other.x && self.y == other.y
- }
- }
- impl Eq for Point2D {}
- impl Sum for Point2D {
- fn sum<I>(iter: I) -> Self
- where
- I: Iterator<Item = Self>,
- {
- iter.fold(Self { x: 0, y: 0 }, |a, b| Self {
- x: a.x + b.x,
- y: a.y + b.y,
- })
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement