From d3690d856e6788f64dd382e3a7cf47c285e7ae95 Mon Sep 17 00:00:00 2001 From: Andrew Coleman Date: Sun, 20 Jan 2019 12:31:03 -0500 Subject: [PATCH] day 18 solution --- 2018/day18/Cargo.lock | 4 + 2018/day18/Cargo.toml | 7 ++ 2018/day18/input | 50 +++++++++++ 2018/day18/src/main.rs | 182 +++++++++++++++++++++++++++++++++++++++++ 2018/day18/test-input | 10 +++ 5 files changed, 253 insertions(+) create mode 100644 2018/day18/Cargo.lock create mode 100644 2018/day18/Cargo.toml create mode 100644 2018/day18/input create mode 100644 2018/day18/src/main.rs create mode 100644 2018/day18/test-input diff --git a/2018/day18/Cargo.lock b/2018/day18/Cargo.lock new file mode 100644 index 0000000..a4065a9 --- /dev/null +++ b/2018/day18/Cargo.lock @@ -0,0 +1,4 @@ +[[package]] +name = "day18" +version = "0.1.0" + diff --git a/2018/day18/Cargo.toml b/2018/day18/Cargo.toml new file mode 100644 index 0000000..74fcfb0 --- /dev/null +++ b/2018/day18/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day18" +version = "0.1.0" +authors = ["Andrew Coleman "] +edition = "2018" + +[dependencies] diff --git a/2018/day18/input b/2018/day18/input new file mode 100644 index 0000000..0e17eac --- /dev/null +++ b/2018/day18/input @@ -0,0 +1,50 @@ +....#......|.#........###|...||.#|||.||.|...|.#.|. +|#|#....|#...||.|#.#|.|.|..#...||.#|#.|.#||#||.|#. +.....##...#..###..##.|.|....|..#.|...#.#.....|.|.. +|....#|||#..||##....||#||.|..|...|..#....#|#....|# +|......|......|.#...|.....|..|.#...#.#..#|.....#|. +|#...#....#...#.|..#..|...|#..|.#.......#..#....|# +....|#.|#...........##...||......##...||#...#..|.| +.#.....|..|...|#..##||..#.#...#...#|.#...#.|....#. +.##|.....|||.....||.#...#...#...#......##...||#... +.||#.|#..|.....#.|.|..........|.#..|##...||...|#.. +|......|..#...#.##||..||..#.|..|.|....##|..|..|.|. +|#...####.#.|.....|#..#....|#.#..|.#.#|####.#..|.. +.#|.....#.|....|###..#||...#|...||.|.#|#.....|##.. +#.|..#|..#...||#.#|...#.##|..|..#...|#.....|..#|.. +#.|.....##..||##....|..|.|.|..##.#..|||.....|..... +......##|..|#.|#||...#.|..#..|.#....|..#....#..|## +|........|#.#.|.##...#|..|##.....|##.|.#....#.#... +#.#..#..|.........#|.##.......|...|.#..#.#|####.#. +.....#||#..|......#|.....#..|||..##.......#.#..#.# +#...........#|..#..|.||.|||.|....#||....|#..##.#.. +.|...#..##|#...#.||.|##.|..#.||.#.#.#.###...#...#| +|#|...|.......#..#..#....|.###..|.||...|.#...|.... +..#.#......|..|.||#.||.......|..#|.#.|..|.#..#.#.# +#..#...|...|..|..#....|..|...|#|...#......#...#... +|...|.|.||#...|...|....|...#.|.#.|.|.|#..|..###.#. +..|.|.....|##...##....|..|.....||...#..||##......| +.#.#....|.##|....|.|..|.|##..#...|##|.#.#.##|....# +..#|.|.....|.#....|...||....|.#..|#.#.|#|.||.||... +.|##.|.#|#|...|...##.||.....|.#|....|.....|#..||.. +|.#|...||....#|..#...|.....|.....#|...|#.#|..|.... +.|...|....###.|....||##||..|#||.#|##|..|.#.......| +...#.||###|#|.#.|...#...|.##.|.||#..#.......||.#.# +.#|....|#.|.###.##|...|#...#.||..##...#.#|##...#.# +..|#|#..#..#..#|#.....|.#.|...|..#.#......###..|.| +#.|.|..#.#.#.#.....|........|#.||..#......#|.....# +...#.#|#|.|.###|#...#.|......#|.......##||......#. +.#|#.|#..#|...|.|...##|.#....|#........|..|.#.#.#. +..|.##.|#..|...#|.#...#........|.|#|.#.|.|..|#|.#. +...#.#.#||.|||...|#||..##.....###......#..#|||#..# +...#.....#||##.|..#.#|......||..#..#..#..|..|..|.. +####.|....|.......|.|.#...|...#.#.......|.|.#...|| +..|.|#|.#..##..##...#.....|...|...#|.|...#|..#..## +|...##.#|.........#..||#..||.#....||#..|..||....#| +.#..........#|#.#|#.|...|#....|..|...|...##....|#. +|.|#..|..|......#..|...|..##|||#...|..##|...#.|#.. +||#.||.#|.|...#.........#...|.|##.#.|#||.|.#|..#.. +|..|..|..#....#...|.......#|.........|#....#|....| +##..###......#|.........|.......|...||.......#|..# +|..............#.......#...#|.|||..#..|..#........ +...|||.#.|.#.|..#.....##|....###.#.|....|.......|. diff --git a/2018/day18/src/main.rs b/2018/day18/src/main.rs new file mode 100644 index 0000000..5378994 --- /dev/null +++ b/2018/day18/src/main.rs @@ -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 = 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 { + let mut neighbors: Vec = 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 = Vec::with_capacity(max_iter); + let mut maps: HashSet = 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); + } +} diff --git a/2018/day18/test-input b/2018/day18/test-input new file mode 100644 index 0000000..13d299d --- /dev/null +++ b/2018/day18/test-input @@ -0,0 +1,10 @@ +.#.#...|#. +.....#|##| +.|..|...#. +..|#.....# +#.#|||#|#| +...#.||... +.|....|... +||...#|.#| +|.||||..|. +...#.|..|.