From 37f9e696bcb54c8ce12042f00a27c38614b97ca4 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 22 Nov 2018 15:59:51 +0100 Subject: [PATCH] Implement day 24. --- 2016/Cargo.toml | 1 + 2016/inputs/24.txt | 37 ++++++++++++++ 2016/src/common.rs | 4 +- 2016/src/day24.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++ 2016/src/main.rs | 3 ++ 5 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 2016/inputs/24.txt create mode 100644 2016/src/day24.rs diff --git a/2016/Cargo.toml b/2016/Cargo.toml index 8bfd723..f78000e 100644 --- a/2016/Cargo.toml +++ b/2016/Cargo.toml @@ -7,3 +7,4 @@ authors = ["Bert Peters "] clap = "2.32" regex = "1.0" itertools = "0.7.8" +permutohedron = "0.2.4" diff --git a/2016/inputs/24.txt b/2016/inputs/24.txt new file mode 100644 index 0000000..2d33623 --- /dev/null +++ b/2016/inputs/24.txt @@ -0,0 +1,37 @@ +##################################################################################################################################################################################### +#.....#.........#.#...#.....#.............#.......#.....#.....#...........#...#.........#.#.#.....#.......#...............#..........3#.#.#.....#.......#...#.....#...#.#.#.....#...# +#.###.#.#.###.#.#.#.#.#.#.#.#.#.#####.#####.#.###.#.#.#######.###.#.#######.#.#.#.#.#.#.#.#.#.#####.#.#.###.#######.#.###.###.#.#.#.#.#.#.#.#.#.#.#.#.#####.#.###.#.#.#.#.###.#.###.# +#.......#.#...#...#.#...#...#.#...#...#.#...#.....#...#.#.....#.....#.....#.......#...#...#.................#.#.............#...#.....#.........#...#...#.#...#...#.....#.......#...# +#.#.#.###.#.#.###.#.#.#.#.###.#.###.###.#.#.#.#######.#.#####.#.#.#####.#.#.#.#####.#.###.#.#####.#####.#.###.###.###.#####.#.#.#.#.#.#.#.#.#.#.###.###.#.#.#.#.#####.#.#.#.#.#.##### +#..1#.......#...........#...#.........#.#.....#...#.#...#.........#...#...#...#.....#.#...#.#.#.....#...#.#.#...#.......#.........#.......#...#.#...#.....#.#.....#...#...#..2#.....# +#.#####.###.#.#.#.###.###.###.#####.#.#.#.#.###.#.#.#.#.#####.###.#.#.#####.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#####.###.#.#.#####.###.###.#.#.#.###.#.#####.#.#.#.###.#.#.#.#.# +#...#.............#.#...#.#...#...#.#.#...#...#.............#.#.....#.........#.........#.#...#.#.#.#...#.......#.#.......#...#...#.#.......#...#.#.....#.........#.#.#.#.........#.# +#.#.#.###.###.#.#.#.#.#.#.#.#.#.#.#.###.###.###.#.#####.#.#.#.###.#.#.#.#####.#.#.###.#.#.#.#.#.###.#.#.#.#####.#####.###.#.#.#.#.#.#.#######.#.#.#.#.#.#.#######.#.#.#.#.###.#.#.#.# +#.......#...#.....#.....#.......#...#.....#.#.#.........#.......#.#.....#...#.#...#...#.#.....#...#.#...........#.........#...#.#.#...#.#.....#.....#.....#...........#...#.......#.# +#####.###.#.###########.###.#.###.###.###.#.#.#.###.#.###.###.#.#.#.#####.#.#.#.#########.#####.#.#.###.#.#.#.#.#.###.#.#.#.###.#.#####.#.#.#.#.#.#.#.#####.###.#####.###.#.#.#.#.#.# +#...#...#.......#.....#.....#.....#.....#.......#.#.#.....#...........#.....#.#.#.#.......#.....#.......#...........#.#...#...#.#.......#...#.....#...#.#...#.#...#...#.....#.....#.# +#.#.###.#.###.#.#####.#.#.#.#.#.#.###.#.###.###.#.#.#.###.#.#.#.###.#.#.###.#.#.#.#.#.#.#.###.#.#.#######.###.#######.#.###.###.#.###.#.#.#.###.###.#.#.#.#.#.#.#.#.###.#.#.###.#.#.# +#.....#...#.........#...#...#.#.#.........#.#.#...#.#...#.#...#.#.........#.....#.#...#.#...#...#.......#.....#...#...#.#.....#.......#.#...#...#.........#.#...#.#.........#.#...#.# +#.###.###########.#.###.#.#.#.#####.#.#.#.###.#.#.#.#####.#.###.#.#.#######.#####.#.#.#.#.###.#.#.###.#.#.#####.###.#.#.#.#.#.#########.###.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#####.# +#.#.................#.............#...#...#.#.#.#...#...#...#.....#.......#.#.#...#...........#.........#.......#.........#...#...#...#.........#.#...#...#.........#.........#...#.# +#.#.#.#####.#######.###.###.###.#.#######.#.#.###.###.#.#.#.#####.#####.###.#.#.#.#.###.#.###.#.#.#####.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#.###.###.#######.###.#.#.#.#.#.#.###.#.#.#.#.# +#...#.#.#...................#0............#...........#.#.....#.#.....#.#.........#.....#.......#.......#.....#.......#.#...#.......#.#.#...#.............#...#.....#.#.......#...#6# +#.#.#.#.#.###.#.#.#.#.#####.###.#.#.#####.#####.###.#.###.###.#.#.#.#.#.#.#####.#.#.#.#.#.#####.#.###.#.#####.#.#####.#.#.#.#.#####.#.#.#.#.#.#.#.#########.#.###.###.#######.#.#.### +#.#...#.#.......#.#.#.#.....#...#...#.#...#...#.#...#.........#...#...#...#.....#.....#.....#...#.....#.......#.....#...#...#.#.....#.#...#.#.#.#.#.......#...#.......#...#...#...#.# +#.###.#.###.#.#.#.#.#.###.#.#.#.###.#.###.#.#.#.#.###.#.#.#.#.#.#.#####.#.#####.#.#####.#.#.#.###.#.#############.###.###.###.###########.#.###.#.#.#.###.#.###.###.#.#.#.#.#.#.###.# +#.....#.#...#...#...#...#.#.#.........#.....#...#...#.#.....#...#.#...........#.#.......#...#.#.......#.#...#.........#...#...#.#.#.....#...#.#.#.#.......#...........#...#.#.......# +#.#.#####.#.###########.#.#.#.#############.#.#.#.#.#######.#######.###.#.###.###.###.#######.#.###.#.#.#.#.#######.###.###.###.#.#.#.#.#.#.#.#.#.#.###.#.#######.###.###.#.#.#.##### +#...#.#.......#.................#.#.........#.....#.#.#.....#...#.....#.......#...#...#.......#.#...#.#.#...#...........#.#.#.....#.#.........#...#.#...........#...#.....#...#.#...# +###.#.#.#.###.#.#.#.#.#.#.###.#.#.#.#.#.#.###.#.#.#.#.#.#.#.###.#.###.#.###.###.#.#####.#####.###.#.#.#.#######.#.#.#.#.#.#.#.###.#.#.###.#.#.###.#.#.#####.#.#.#.###.#.#.###.#.#.#.# +#...#...#.....#.#.#...#...#...#...#.............#.....#...#.#.#...#.............#.#.............#...#.#.#...#.#.#...#.#...#.#.#.......#.#.......#...#.#.....#...#...#.#...#.#...#...# +#.#.#.#.#.#####.#.#.#.#.#.#.#######.###.#######.#.###.#.###.#.#.#.###.#.#.###.#.#.#.#.#.#.#.###.###.#.###.###.###.###.###.###.###.#####.#######.###.#.###.#.#.###.#.#.#.###.###.#.#.# +#...#.#.#.......#.#.#...#...........#.........#.#.#...#.#.#.#.#.#.............#...#...#...#.....#.......#...#.#...#...#...#...#.........#...#...#.....#.#.....#.#.#...#...#.#...#...# +###.#.#.#.###.###.###.#.#####.#.#.#.#.#.#####.###.#.###.#.#.#.#.###.#.###.###.###.#.#.#.###.###.###.###.###.###.#.#.###.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.###.# +#...#...#.#...#...#.#.#.......#...#...#.#.......#.......#.#.....#.........#...........#.....#...#...#.......#...........#...#...#.#.#...#.......#...#.....#.....#.#....5#.....#.....# +#.#.#.#####.#.#.#.#.###.#.#.#.###.#.#.###.#####.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.###############.#.###.#.#.#.###.###.#.#.#.#.###.#.#.###.#####.#.#.#####.###.###.#.#.#.###.#.#.#.#.# +#.........#.#...#.....#...#.#.#...#.....#...#.....#.....#...#.#.#...#.#.....#...#.............#...#.#.....#.#.....#...........#...#.............#...#...#.#...#...#.#.......#...#...# +#.#.#.#.#.#.###.#####.###.#.#.#.#.#.###.#.###.#.###.#.#.#.#.#.###.#.#.#.#####.#.#####.#####.###.#.#.#.#############.#####.#.###.#.###.#.#.#.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.####### +#4#.#.....#.#.....#...#...#...#...#...#.#.#...#...#...#.#.....#...#...#.........#...#.#.....#...#.#...#.#.....#.#.#...#...#.#...#.#.......#.#.......#...#.......#.#.#.#.#.........#.# +#####.#.###.###.###.#####.###.#.#.###.#.#.#.#.#.#.#.#.#####.#.#.#.#.###.#.#.#.#.#.#.#.#.#.###.#.#.###.#.#.#.#.#.#.###.#.#.###.#.#.###.#.#.#.###.###.#.#.#.#.#####.#.###.#.#####.###.# +#.......#...#...#...#.#.#.........#...#.#7#.#...#...#.......#.#.#.#.....#.#.....#.....#.....#...#.#.#.#...........#...#.....#.............#...............#.....#.........#...#.....# +##################################################################################################################################################################################### diff --git a/2016/src/common.rs b/2016/src/common.rs index 2c95103..8081092 100644 --- a/2016/src/common.rs +++ b/2016/src/common.rs @@ -59,7 +59,9 @@ pub trait Solution { fn part1(&mut self, input: &mut io::Read) -> String; /// Solve the second part of the day - fn part2(&mut self, input: &mut io::Read) -> String; + fn part2(&mut self, _input: &mut io::Read) -> String { + panic!("Not implemented yet."); + } } #[derive(Default)] diff --git a/2016/src/day24.rs b/2016/src/day24.rs new file mode 100644 index 0000000..3563367 --- /dev/null +++ b/2016/src/day24.rs @@ -0,0 +1,122 @@ +use std::cmp; +use std::collections::{HashSet,VecDeque}; +use std::io; +use std::io::prelude::*; +use permutohedron::Heap; +use common; + +#[derive(Default)] +pub struct Day24 { + map: Vec>, + positions: [(usize, usize);10], + max_index: usize, + adjacency: [[u32;10];10], +} + +impl Day24 { + pub fn new() -> Day24 { + Default::default() + } + + fn read_map(&mut self, input: &mut io::Read) { + let reader = io::BufReader::new(input); + self.map.clear(); + for (y, line) in reader.lines().enumerate() { + let mut contents = Vec::new(); + + for (x, c) in line.unwrap().chars().enumerate() { + if let Some(val) = c.to_digit(10) { + self.max_index = cmp::max(self.max_index, val as usize); + self.positions[val as usize] = (x, y); + } + contents.push(c); + } + self.map.push(contents); + } + self.compute_adjacency(); + } + + fn compute_adjacency(&mut self) { + for i in 0..(self.max_index + 1) { + let mut visited = HashSet::new(); + let mut todo = VecDeque::new(); + visited.insert(self.positions[i]); + todo.push_back((self.positions[i], 0)); + + while !todo.is_empty() { + let ((x, y), dist) = todo.pop_front().unwrap(); + if let Some(d) = self.map[y][x].to_digit(10) { + self.adjacency[i][d as usize] = dist; + } + + for dx in -1..2 { + for dy in -1..2 { + if dx * dy != 0 { + continue; + } + let nx = (x as i32 + dx) as usize; + let ny = (y as i32 + dy) as usize; + let npos = (nx, ny); + if self.map[y][x] != '#' && !visited.contains(&npos) { + visited.insert(npos); + todo.push_back((npos, dist + 1)); + } + } + } + } + } + } + + fn tour_length(&self, tour: &[usize]) -> u32 { + let mut prev = 0; + let mut dist = 0; + for cur in tour { + dist += self.adjacency[prev][*cur]; + prev = *cur; + } + dist + } + + fn tour_length2(&self, tour: &[usize]) -> u32 { + let dist = self.tour_length(tour); + dist + self.adjacency[*tour.last().unwrap()][0] + } +} + +impl common::Solution for Day24 { + + fn part1(&mut self, input: &mut io::Read) -> String { + self.read_map(input); + let mut order: Vec = (1..(self.max_index + 1)).collect(); + let result = Heap::new(&mut order).map(|x| self.tour_length(&x)).min(); + format!("{}", result.unwrap()) + } + + fn part2(&mut self, input: &mut io::Read) -> String { + self.read_map(input); + let mut order: Vec = (1..(self.max_index + 1)).collect(); + let result = Heap::new(&mut order).map(|x| self.tour_length2(&x)).min(); + format!("{}", result.unwrap()) + } + +} + +#[cfg(test)] +mod tests { + use super::*; + use common::Solution; + + const SAMPLE_INPUT: &str = " +########### +#0.1.....2# +#.#######.# +#4.......3# +###########"; + + #[test] + fn sample_part1() { + let mut instance = Day24::new(); + assert_eq!("14", instance.part1(&mut SAMPLE_INPUT.as_bytes())) + } + +} diff --git a/2016/src/main.rs b/2016/src/main.rs index 92c98c0..f46982a 100644 --- a/2016/src/main.rs +++ b/2016/src/main.rs @@ -1,6 +1,7 @@ extern crate clap; extern crate regex; extern crate itertools; +extern crate permutohedron; use clap::{Arg, App}; use std::fs; use std::io; @@ -11,6 +12,7 @@ pub mod day12; pub mod day15; pub mod day16; pub mod day23; +pub mod day24; fn get_impl(day: i32) -> Box { match day { @@ -19,6 +21,7 @@ fn get_impl(day: i32) -> Box { 15 => { Box::new(day15::Day15::new()) } 16 => { Box::new(day16::Day16::new()) } 23 => { Box::new(day23::Day23::new()) } + 24 => { Box::new(day24::Day24::new()) } _ => { panic!("Unimplemented day {}", day) }