mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement day 18.
Curiously, it reminds me of some other day involving plants.
This commit is contained in:
50
2018/inputs/18.txt
Normal file
50
2018/inputs/18.txt
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
..|#..#......#|.#..#|#.|##|.|.##.||..|.||....###|.
|
||||||
|
||.|....|#.#|.#...#.|...|#.#.#.#....#......#....#.
|
||||||
|
...#...|.....#.#..|#...||..#.|.|#....#|#|..##...|.
|
||||||
|
.....#....|#.|..|.....#|##...#.#.#||....||||....#.
|
||||||
|
..###...#.||.|||.##.#.|....|.##.#....|.#.|..|.....
|
||||||
|
....|..#.#.|...|..|.....#....#.#.......|.||...|...
|
||||||
|
#..|.....##|..#..#...#..|.##.....#......||##|.|#..
|
||||||
|
##........#...|#|.##.#|#..#|...#...#.##|||.#||..||
|
||||||
|
......#..|..|.#...|#||.#....#.#.|#.||......|.....|
|
||||||
|
.|...|.##....#.||...|..|..|.|........#.#..|||..|##
|
||||||
|
..|....|...#####..|#|..|...#...#.|...|..|.|..|.#|#
|
||||||
|
....|...#.#.#.......#......#.#|......#|.##..##.#|.
|
||||||
|
.....|.#..|#...||..#......|..#.|#.#|...#|.|..#||..
|
||||||
|
#....#.......|#.|..|...#...|..|.##|#.|#.#|.....|..
|
||||||
|
....#.||#.....#..#...|....##.#.......#.|.|||.|....
|
||||||
|
|.|..||##....|#..#..|..|.|.|..|||.##..#.|......##|
|
||||||
|
###..|.#|##|#.|||.#|.#..|#|..#..|.#|....#.#.#..||.
|
||||||
|
.|.....|#.#.|#||..#.....#.|.||.#.|.....|#..|...#..
|
||||||
|
...##.........|...#.#|....##..#.|.|.......#..|...|
|
||||||
|
..#.#.|.|.....||#..||...##||.#|..|.....#|...|...#|
|
||||||
|
....#...#||..|...|.|..|#.#.........|#...#.|||...#.
|
||||||
|
.#..|.##.|.|.#...#.....#.#.......|#.|.#||#.#.....#
|
||||||
|
|...#|..#....#...|.##.####....|#.##|#.#.|.....||..
|
||||||
|
....|.#.|#||..|#.|.|.#|...|.#....||.#...#|.#...|.#
|
||||||
|
.|..#.#..|#|..##..|.##..||...#...||....#||..#.|...
|
||||||
|
##......#.|...|.||.#.||....|.......#......##|#..|.
|
||||||
|
|#....#||....##...........#.|....|....|#|#.|..#...
|
||||||
|
..#...#|....|.|..|...#.......#.##.#.....#.||......
|
||||||
|
...|....#|#..#|...|...#|....#.#|.......|.......|#.
|
||||||
|
.#||..##||.|..|.|#..|.|....|.#|.|.|.....#.#.|..#.#
|
||||||
|
.....|..|...|...|......||...##.....##.......|.#..|
|
||||||
|
.....#..#|.#...#..#...||.|##..|#..##.|#.....##....
|
||||||
|
|...|.#||.........#..#..#||||....|...|..|..#...##.
|
||||||
|
#.#..|.|.......||..|#|..|....|.|#|#|.|..|.|...#.#.
|
||||||
|
#.|..||#.||||..###.|......|.#|||.##........||...||
|
||||||
|
.....#|..#.#.....|..|#.....|....|.#|||#.|.....#...
|
||||||
|
...||#..#...#...||#.||......|#..#..#.|#.|#|...|..#
|
||||||
|
.||.....||..|#.|#||...##..###|.#....|.|..|#...#|.|
|
||||||
|
...#.|#||..#.|||......#...||.#..|||..|#.|.##..#.|#
|
||||||
|
.#||..#.|||.......|.|#.....|.|#.#..##..|.|....|#..
|
||||||
|
..#.###..|.........|.....#..###|.|#..........#|.#|
|
||||||
|
#.||.|.#.|..||#|||#..##.|#....#.#.|.#.....|.|.#.|#
|
||||||
|
|..|..#.#..|.#.......#...#.|..|..|#..|..###|.||..|
|
||||||
|
|..|...||...|.#.#..##|.#..#...#|#..|.#..|.#..|.||.
|
||||||
|
..#.##..#.|..#.#..|..|#.|||.#..#..|#####.|..#.....
|
||||||
|
.|.|#.|#...||..##...#|#.........#...#|..##.#.#..#.
|
||||||
|
##|.|..#.#|....#..|..#....#......#||.|....||##..||
|
||||||
|
.##|#....#..#..#.....#|.#...#..#.|#||||.##.#....|.
|
||||||
|
..|.......#|....|#|..||..##..#.|#|..#.#|....|..#|#
|
||||||
|
....|||.|||#..||...|||.##..#.#|##....|..|..||..#|#
|
||||||
@@ -1,25 +1,189 @@
|
|||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
use common::GroupingCount;
|
||||||
use common::Solution;
|
use common::Solution;
|
||||||
|
use std::mem::swap;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
|
||||||
|
enum Tile {
|
||||||
|
Tree,
|
||||||
|
Lumber,
|
||||||
|
Open,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tile {
|
||||||
|
pub fn next(self, counts: &[usize; 3]) -> Self {
|
||||||
|
match self {
|
||||||
|
Tile::Open => {
|
||||||
|
if counts[Tile::Tree as usize] >= 3 {
|
||||||
|
Tile::Tree
|
||||||
|
} else {
|
||||||
|
Tile::Open
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tile::Tree => {
|
||||||
|
if counts[Tile::Lumber as usize] >= 3 {
|
||||||
|
Tile::Lumber
|
||||||
|
} else {
|
||||||
|
Tile::Tree
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tile::Lumber => {
|
||||||
|
if counts[Tile::Tree as usize] >= 1 && counts[Tile::Lumber as usize] >= 1 {
|
||||||
|
Tile::Lumber
|
||||||
|
} else {
|
||||||
|
Tile::Open
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<char> for Tile {
|
||||||
|
fn from(c: char) -> Self {
|
||||||
|
match c {
|
||||||
|
'|' => Tile::Tree,
|
||||||
|
'#' => Tile::Lumber,
|
||||||
|
'.' => Tile::Open,
|
||||||
|
_ => panic!("Invalid tile '{}'", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Tile> for char {
|
||||||
|
fn from(t: Tile) -> Self {
|
||||||
|
match t {
|
||||||
|
Tile::Tree => '|',
|
||||||
|
Tile::Lumber => '#',
|
||||||
|
Tile::Open => '.',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Day18 {}
|
pub struct Day18 {
|
||||||
|
grid: Vec<Vec<Tile>>,
|
||||||
|
buf: Vec<Vec<Tile>>,
|
||||||
|
width: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl Day18 {
|
impl Day18 {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_input(&mut self, input: &mut Read) {
|
||||||
|
let reader = BufReader::new(input);
|
||||||
|
self.grid.clear();
|
||||||
|
|
||||||
|
for line in reader.lines() {
|
||||||
|
let line = line.unwrap();
|
||||||
|
|
||||||
|
self.grid.push(line.chars().map(From::from).collect());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.width = self.grid.first().unwrap().len();
|
||||||
|
self.buf = vec![vec![Tile::Tree; self.width]; self.grid.len()];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simulate(&mut self) {
|
||||||
|
let height = self.grid.len();
|
||||||
|
let width = self.width;
|
||||||
|
|
||||||
|
for y in 0..height {
|
||||||
|
let ymin = if y > 0 { y - 1 } else { y };
|
||||||
|
let ymax = if y < height - 1 { y + 1 } else { y };
|
||||||
|
|
||||||
|
for x in 0..self.width {
|
||||||
|
let mut counts = [0; 3];
|
||||||
|
let xmin = if x > 0 { x - 1 } else { x };
|
||||||
|
let xmax = if x < width - 1 { x + 1 } else { x };
|
||||||
|
|
||||||
|
for ys in ymin..=ymax {
|
||||||
|
for xs in xmin..=xmax {
|
||||||
|
if ys != y || xs != x {
|
||||||
|
counts[self.grid[ys][xs] as usize] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.buf[y][x] = self.grid[y][x].next(&counts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(&mut self.buf, &mut self.grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print(&self) -> String {
|
||||||
|
let mut buf = String::with_capacity(self.width * self.grid.len());
|
||||||
|
for row in &self.grid {
|
||||||
|
buf.extend(row.iter().cloned().map(Into::<char>::into));
|
||||||
|
}
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn score(&self) -> String {
|
||||||
|
let result = self.grid.iter()
|
||||||
|
.flat_map(|x| x.iter())
|
||||||
|
.cloned().grouping_count();
|
||||||
|
|
||||||
|
format!("{}", result[&Tile::Tree] * result[&Tile::Lumber])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Solution for Day18 {
|
impl Solution for Day18 {
|
||||||
fn part1(&mut self, _input: &mut Read) -> String {
|
fn part1(&mut self, input: &mut Read) -> String {
|
||||||
unimplemented!()
|
self.read_input(input);
|
||||||
|
|
||||||
|
for _ in 0..10 {
|
||||||
|
self.simulate();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.score()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(&mut self, _input: &mut Read) -> String {
|
fn part2(&mut self, input: &mut Read) -> String {
|
||||||
unimplemented!()
|
self.read_input(input);
|
||||||
|
let limit = 1_000_000_000;
|
||||||
|
|
||||||
|
let mut seen = HashMap::new();
|
||||||
|
seen.insert(self.print(), 0);
|
||||||
|
|
||||||
|
for i in 1..=limit {
|
||||||
|
self.simulate();
|
||||||
|
let summary = self.print();
|
||||||
|
if let Some(first) = seen.get(&summary) {
|
||||||
|
let period = i - *first;
|
||||||
|
let remaining = (limit - *first) % period;
|
||||||
|
|
||||||
|
for _ in 0..remaining {
|
||||||
|
self.simulate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.score();
|
||||||
|
}
|
||||||
|
|
||||||
|
seen.insert(summary, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I encourage everyone to hit this line of code.
|
||||||
|
self.score()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {}
|
mod tests {
|
||||||
|
use common::Solution;
|
||||||
|
use day18::Day18;
|
||||||
|
|
||||||
|
const SAMPLE_INPUT: &[u8] = include_bytes!("samples/18.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
let mut instance = Day18::new();
|
||||||
|
assert_eq!("1147", instance.part1(&mut SAMPLE_INPUT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
10
2018/src/samples/18.txt
Normal file
10
2018/src/samples/18.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.#.#...|#.
|
||||||
|
.....#|##|
|
||||||
|
.|..|...#.
|
||||||
|
..|#.....#
|
||||||
|
#.#|||#|#|
|
||||||
|
...#.||...
|
||||||
|
.|....|...
|
||||||
|
||...#|.#|
|
||||||
|
|.||||..|.
|
||||||
|
...#.|..|.
|
||||||
Reference in New Issue
Block a user