1
0
Fork 0

day 18 solution

main
Andrew Coleman 2019-01-20 12:31:03 -05:00
parent 960a2b1e28
commit d3690d856e
5 changed files with 253 additions and 0 deletions

4
2018/day18/Cargo.lock generated Normal file
View File

@ -0,0 +1,4 @@
[[package]]
name = "day18"
version = "0.1.0"

7
2018/day18/Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "day18"
version = "0.1.0"
authors = ["Andrew Coleman <penguincoder@gmail.com>"]
edition = "2018"
[dependencies]

50
2018/day18/input Normal file
View File

@ -0,0 +1,50 @@
....#......|.#........###|...||.#|||.||.|...|.#.|.
|#|#....|#...||.|#.#|.|.|..#...||.#|#.|.#||#||.|#.
.....##...#..###..##.|.|....|..#.|...#.#.....|.|..
|....#|||#..||##....||#||.|..|...|..#....#|#....|#
|......|......|.#...|.....|..|.#...#.#..#|.....#|.
|#...#....#...#.|..#..|...|#..|.#.......#..#....|#
....|#.|#...........##...||......##...||#...#..|.|
.#.....|..|...|#..##||..#.#...#...#|.#...#.|....#.
.##|.....|||.....||.#...#...#...#......##...||#...
.||#.|#..|.....#.|.|..........|.#..|##...||...|#..
|......|..#...#.##||..||..#.|..|.|....##|..|..|.|.
|#...####.#.|.....|#..#....|#.#..|.#.#|####.#..|..
.#|.....#.|....|###..#||...#|...||.|.#|#.....|##..
#.|..#|..#...||#.#|...#.##|..|..#...|#.....|..#|..
#.|.....##..||##....|..|.|.|..##.#..|||.....|.....
......##|..|#.|#||...#.|..#..|.#....|..#....#..|##
|........|#.#.|.##...#|..|##.....|##.|.#....#.#...
#.#..#..|.........#|.##.......|...|.#..#.#|####.#.
.....#||#..|......#|.....#..|||..##.......#.#..#.#
#...........#|..#..|.||.|||.|....#||....|#..##.#..
.|...#..##|#...#.||.|##.|..#.||.#.#.#.###...#...#|
|#|...|.......#..#..#....|.###..|.||...|.#...|....
..#.#......|..|.||#.||.......|..#|.#.|..|.#..#.#.#
#..#...|...|..|..#....|..|...|#|...#......#...#...
|...|.|.||#...|...|....|...#.|.#.|.|.|#..|..###.#.
..|.|.....|##...##....|..|.....||...#..||##......|
.#.#....|.##|....|.|..|.|##..#...|##|.#.#.##|....#
..#|.|.....|.#....|...||....|.#..|#.#.|#|.||.||...
.|##.|.#|#|...|...##.||.....|.#|....|.....|#..||..
|.#|...||....#|..#...|.....|.....#|...|#.#|..|....
.|...|....###.|....||##||..|#||.#|##|..|.#.......|
...#.||###|#|.#.|...#...|.##.|.||#..#.......||.#.#
.#|....|#.|.###.##|...|#...#.||..##...#.#|##...#.#
..|#|#..#..#..#|#.....|.#.|...|..#.#......###..|.|
#.|.|..#.#.#.#.....|........|#.||..#......#|.....#
...#.#|#|.|.###|#...#.|......#|.......##||......#.
.#|#.|#..#|...|.|...##|.#....|#........|..|.#.#.#.
..|.##.|#..|...#|.#...#........|.|#|.#.|.|..|#|.#.
...#.#.#||.|||...|#||..##.....###......#..#|||#..#
...#.....#||##.|..#.#|......||..#..#..#..|..|..|..
####.|....|.......|.|.#...|...#.#.......|.|.#...||
..|.|#|.#..##..##...#.....|...|...#|.|...#|..#..##
|...##.#|.........#..||#..||.#....||#..|..||....#|
.#..........#|#.#|#.|...|#....|..|...|...##....|#.
|.|#..|..|......#..|...|..##|||#...|..##|...#.|#..
||#.||.#|.|...#.........#...|.|##.#.|#||.|.#|..#..
|..|..|..#....#...|.......#|.........|#....#|....|
##..###......#|.........|.......|...||.......#|..#
|..............#.......#...#|.|||..#..|..#........
...|||.#.|.#.|..#.....##|....###.#.|....|.......|.

182
2018/day18/src/main.rs Normal file
View File

@ -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);
}
}

10
2018/day18/test-input Normal file
View File

@ -0,0 +1,10 @@
.#.#...|#.
.....#|##|
.|..|...#.
..|#.....#
#.#|||#|#|
...#.||...
.|....|...
||...#|.#|
|.||||..|.
...#.|..|.