day 18 solution
parent
960a2b1e28
commit
d3690d856e
|
@ -0,0 +1,4 @@
|
|||
[[package]]
|
||||
name = "day18"
|
||||
version = "0.1.0"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "day18"
|
||||
version = "0.1.0"
|
||||
authors = ["Andrew Coleman <penguincoder@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
|
@ -0,0 +1,50 @@
|
|||
....#......|.#........###|...||.#|||.||.|...|.#.|.
|
||||
|#|#....|#...||.|#.#|.|.|..#...||.#|#.|.#||#||.|#.
|
||||
.....##...#..###..##.|.|....|..#.|...#.#.....|.|..
|
||||
|....#|||#..||##....||#||.|..|...|..#....#|#....|#
|
||||
|......|......|.#...|.....|..|.#...#.#..#|.....#|.
|
||||
|#...#....#...#.|..#..|...|#..|.#.......#..#....|#
|
||||
....|#.|#...........##...||......##...||#...#..|.|
|
||||
.#.....|..|...|#..##||..#.#...#...#|.#...#.|....#.
|
||||
.##|.....|||.....||.#...#...#...#......##...||#...
|
||||
.||#.|#..|.....#.|.|..........|.#..|##...||...|#..
|
||||
|......|..#...#.##||..||..#.|..|.|....##|..|..|.|.
|
||||
|#...####.#.|.....|#..#....|#.#..|.#.#|####.#..|..
|
||||
.#|.....#.|....|###..#||...#|...||.|.#|#.....|##..
|
||||
#.|..#|..#...||#.#|...#.##|..|..#...|#.....|..#|..
|
||||
#.|.....##..||##....|..|.|.|..##.#..|||.....|.....
|
||||
......##|..|#.|#||...#.|..#..|.#....|..#....#..|##
|
||||
|........|#.#.|.##...#|..|##.....|##.|.#....#.#...
|
||||
#.#..#..|.........#|.##.......|...|.#..#.#|####.#.
|
||||
.....#||#..|......#|.....#..|||..##.......#.#..#.#
|
||||
#...........#|..#..|.||.|||.|....#||....|#..##.#..
|
||||
.|...#..##|#...#.||.|##.|..#.||.#.#.#.###...#...#|
|
||||
|#|...|.......#..#..#....|.###..|.||...|.#...|....
|
||||
..#.#......|..|.||#.||.......|..#|.#.|..|.#..#.#.#
|
||||
#..#...|...|..|..#....|..|...|#|...#......#...#...
|
||||
|...|.|.||#...|...|....|...#.|.#.|.|.|#..|..###.#.
|
||||
..|.|.....|##...##....|..|.....||...#..||##......|
|
||||
.#.#....|.##|....|.|..|.|##..#...|##|.#.#.##|....#
|
||||
..#|.|.....|.#....|...||....|.#..|#.#.|#|.||.||...
|
||||
.|##.|.#|#|...|...##.||.....|.#|....|.....|#..||..
|
||||
|.#|...||....#|..#...|.....|.....#|...|#.#|..|....
|
||||
.|...|....###.|....||##||..|#||.#|##|..|.#.......|
|
||||
...#.||###|#|.#.|...#...|.##.|.||#..#.......||.#.#
|
||||
.#|....|#.|.###.##|...|#...#.||..##...#.#|##...#.#
|
||||
..|#|#..#..#..#|#.....|.#.|...|..#.#......###..|.|
|
||||
#.|.|..#.#.#.#.....|........|#.||..#......#|.....#
|
||||
...#.#|#|.|.###|#...#.|......#|.......##||......#.
|
||||
.#|#.|#..#|...|.|...##|.#....|#........|..|.#.#.#.
|
||||
..|.##.|#..|...#|.#...#........|.|#|.#.|.|..|#|.#.
|
||||
...#.#.#||.|||...|#||..##.....###......#..#|||#..#
|
||||
...#.....#||##.|..#.#|......||..#..#..#..|..|..|..
|
||||
####.|....|.......|.|.#...|...#.#.......|.|.#...||
|
||||
..|.|#|.#..##..##...#.....|...|...#|.|...#|..#..##
|
||||
|...##.#|.........#..||#..||.#....||#..|..||....#|
|
||||
.#..........#|#.#|#.|...|#....|..|...|...##....|#.
|
||||
|.|#..|..|......#..|...|..##|||#...|..##|...#.|#..
|
||||
||#.||.#|.|...#.........#...|.|##.#.|#||.|.#|..#..
|
||||
|..|..|..#....#...|.......#|.........|#....#|....|
|
||||
##..###......#|.........|.......|...||.......#|..#
|
||||
|..............#.......#...#|.|||..#..|..#........
|
||||
...|||.#.|.#.|..#.....##|....###.#.|....|.......|.
|
|
@ -0,0 +1,182 @@
|
|||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::collections::HashSet;
|
||||
|
||||
const OPEN: char = '.';
|
||||
const WOODED: char = '|';
|
||||
const LUMBERYARD: char = '#';
|
||||
const MAP_SIZE: usize = 50;
|
||||
type Map = [[char; MAP_SIZE]; MAP_SIZE];
|
||||
|
||||
fn get_map_from_file(filename: &str) -> Map {
|
||||
let lines: Vec<String> = BufReader::new(File::open(filename).unwrap())
|
||||
.lines()
|
||||
.map(|line| line.unwrap())
|
||||
.collect();
|
||||
let mut m = [[OPEN; MAP_SIZE]; MAP_SIZE];
|
||||
let mut y: usize = 0;
|
||||
for line in lines.iter() {
|
||||
for (i, c) in line.char_indices() {
|
||||
m[i][y] = c;
|
||||
}
|
||||
y += 1;
|
||||
}
|
||||
m
|
||||
}
|
||||
|
||||
fn get_neighbors(map: &Map, width: usize, height: usize, x: usize, y: usize) -> Vec<char> {
|
||||
let mut neighbors: Vec<char> = Vec::with_capacity(8);
|
||||
if x > 0 && y > 0 {
|
||||
neighbors.push(map[x - 1][y - 1]);
|
||||
}
|
||||
if y > 0 {
|
||||
neighbors.push(map[x][y - 1]);
|
||||
}
|
||||
if x + 1 < width && y > 0 {
|
||||
neighbors.push(map[x + 1][y - 1]);
|
||||
}
|
||||
if x > 0 {
|
||||
neighbors.push(map[x - 1][y]);
|
||||
}
|
||||
if x + 1 < width {
|
||||
neighbors.push(map[x + 1][y]);
|
||||
}
|
||||
if x > 0 && y + 1 < height {
|
||||
neighbors.push(map[x - 1][y + 1]);
|
||||
}
|
||||
if y + 1 < height {
|
||||
neighbors.push(map[x][y + 1]);
|
||||
}
|
||||
if x + 1 < width && y + 1 < height {
|
||||
neighbors.push(map[x + 1][y + 1]);
|
||||
}
|
||||
neighbors
|
||||
}
|
||||
|
||||
fn print_map(map: &Map, width: usize, height: usize) {
|
||||
if cfg!(debug_assertions) {
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
print!("{}", map[x][y]);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(map: &mut Map, width: usize, height: usize, ticks: u64) -> u64 {
|
||||
for _ in 0..ticks {
|
||||
let mut new_map: Map = [[OPEN; MAP_SIZE]; MAP_SIZE];
|
||||
for x in 0..width {
|
||||
for y in 0..height {
|
||||
let mut wooded_squares = 0;
|
||||
let mut lumberyard_squares = 0;
|
||||
for c in get_neighbors(map, width, height, x, y).iter() {
|
||||
match *c {
|
||||
WOODED => wooded_squares += 1,
|
||||
LUMBERYARD => lumberyard_squares += 1,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
if map[x][y] == OPEN && wooded_squares >= 3 {
|
||||
new_map[x][y] = WOODED;
|
||||
} else if map[x][y] == WOODED && lumberyard_squares >= 3 {
|
||||
new_map[x][y] = LUMBERYARD;
|
||||
} else if map[x][y] == LUMBERYARD {
|
||||
if lumberyard_squares >= 1 && wooded_squares >= 1 {
|
||||
new_map[x][y] = LUMBERYARD;
|
||||
} else {
|
||||
new_map[x][y] = OPEN;
|
||||
}
|
||||
} else {
|
||||
new_map[x][y] = map[x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
for x in 0..width {
|
||||
for y in 0..height {
|
||||
map[x][y] = new_map[x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
part_one_score(map, width, height)
|
||||
}
|
||||
|
||||
fn map_to_string(map: &Map, width: usize, height: usize) -> String {
|
||||
let mut s = String::new();
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
s.push(map[x][y]);
|
||||
}
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
fn part_two_score(map: &mut Map, width: usize, height: usize, target_ticks: u64) -> u64 {
|
||||
let max_iter = 500;
|
||||
let mut scores: Vec<u64> = Vec::with_capacity(max_iter);
|
||||
let mut maps: HashSet<String> = HashSet::new();
|
||||
for i in 1..max_iter {
|
||||
let mut m = map.clone();
|
||||
let s = tick(&mut m, width, height, i as u64);
|
||||
scores.push(s);
|
||||
if !maps.insert(map_to_string(&m, width, height)) {
|
||||
let mut index: u64 = 0;
|
||||
for (i, k) in scores.iter().enumerate() {
|
||||
if s == *k {
|
||||
index = i as u64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let remaining_steps: u64 = target_ticks - index;
|
||||
let cycle_len: u64 = scores.len() as u64 - index - 1;
|
||||
let remainder: u64 = remaining_steps % cycle_len;
|
||||
let final_tick: u64 = remainder + index;
|
||||
println!("repeated value: {}", s);
|
||||
println!("first occurrence at {}", index);
|
||||
println!("remaining steps {}", remaining_steps);
|
||||
println!("cycle len {}", cycle_len);
|
||||
println!("remainder of {} with final tick at {}", remainder, final_tick);
|
||||
return tick(&mut map.clone(), width, height, final_tick);
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn part_one_score(map: &Map, width: usize, height: usize) -> u64 {
|
||||
let mut woods: u64 = 0;
|
||||
let mut lumberyards: u64 = 0;
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
match map[x][y] {
|
||||
WOODED => woods += 1,
|
||||
LUMBERYARD => lumberyards += 1,
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
woods * lumberyards
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let m: Map = get_map_from_file("input");
|
||||
print_map(&m, 50, 50);
|
||||
let part_one_score = tick(&mut m.clone(), 50, 50, 10);
|
||||
println!("part one score {}", part_one_score);
|
||||
//part_two_score(&mut m.clone(), 50, 50, 1000000000);
|
||||
let part_two_score = part_two_score(&mut m.clone(), 50, 50, 1000000000);
|
||||
println!("part two score {}", part_two_score);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_part_one() {
|
||||
let mut m: Map = get_map_from_file("test-input");
|
||||
print_map(&m, 10, 10);
|
||||
let part_one_score = tick(&mut m, 10, 10, 10);
|
||||
assert_eq!(part_one_score, 1147);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
.#.#...|#.
|
||||
.....#|##|
|
||||
.|..|...#.
|
||||
..|#.....#
|
||||
#.#|||#|#|
|
||||
...#.||...
|
||||
.|....|...
|
||||
||...#|.#|
|
||||
|.||||..|.
|
||||
...#.|..|.
|
Loading…
Reference in New Issue