diff --git a/2015/README.md b/2015/README.md index 626d1d8..312b515 100644 --- a/2015/README.md +++ b/2015/README.md @@ -19,7 +19,7 @@ | ✓ | 15 | Permutations | Ruby | | ✓ | 16 | Searching | Ruby | | | 17 | Combinations | | -| | 18 | | | +| ✓ | 18 | Game of Life | Ruby | | | 19 | | | | | 20 | | | | | 21 | | | diff --git a/2015/day-18/.ruby-version b/2015/day-18/.ruby-version new file mode 100644 index 0000000..4a36342 --- /dev/null +++ b/2015/day-18/.ruby-version @@ -0,0 +1 @@ +3.0.0 diff --git a/2015/day-18/inputs/puzzle.txt b/2015/day-18/inputs/puzzle.txt new file mode 100644 index 0000000..b2a6ab1 --- /dev/null +++ b/2015/day-18/inputs/puzzle.txt @@ -0,0 +1,100 @@ +####.#.##.###.#.#.##.#..###.#..#.#.#..##....#.###...##..###.##.#.#.#.##...##..#..#....#.#.##..#...## +.##...##.##.######.#.#.##...#.#.#.#.#...#.##.#..#.#.####...#....#....###.#.#.#####....#.#.##.#.#.##. +###.##..#..#####.......#.########...#.####.###....###.###...#...####.######.#..#####.#.###....####.. +....#..#..#....###.##.#.....##...#.###.#.#.#..#.#..##...#....#.##.###.#...######......#..#.#..####.# +..###.####..#.#.#..##.#.#....#......#.##.##..##.#.....##.###.#..###...###.#.##..#.#..###....####.#.# +#.#...#......####.#..##.####.#.#.#...##..###.##.#...#..#..###....#.#....#..##..#....##.....##.#...#. +....##.#.#.#.##..##...##..##..#....#....###...####.###...##.#...#..#....##.....#..#.#####.###.###.## +#...##..#.#..#....#..########.##....##..##.###..#.#..#..#.##.##.#..##..######....####..#####.#.###.. +.####...######.#..#.##.#.#..####...####.##.#.#......#...##....##..#...###..#.####......###......#.## +.####.###..#..#####.##...###......#...###..#..##..#.#....##.##.#.##.###..#..#..###.#..#.#....####.## +#..#..##.##.##.###.#.##.##.#.#.#....#....#.####.#.##...#####...###.#####.#.#.#....####..###..###..## +#.##....#...########..##...#.#.##.......#.#..##...####...#.####.####..##...##.#....###.#.####...#.## +#.#...##..#.##.##..##....#.....##.##.....#...###...#..#...####.##.####..#...##..##.##.##.##..##...## +.#..###...#.#.....#######..##.###....##..#.##.#......###.##....#......###...#.##....#.....##......## +..##....#.###...###..####.##..#..##.##......##.#.....#...#..#..##...###..#.####...#...#..##.#..##..# +...#.#.#...#.#..#.##....##..#...#.##..#......#.#.....#####.##.#...#######.#.#..#.####..###.....###.# +.#....#.#.##..####.#####..#.#######..#.##.###...##.##....##..###..#.##.###.......#....#..######.#### +#..#.##.##..#..#..##.####.#.#.#.#..#.##...#..######....#.##.#..##.##.######.###.###.###...#.....#.#. +.#.......#...#.####.##...#####..##..#.#....##..#.#.#.####.#.##....#..##.##..#.###.....#.##.##.#.##.# +#..##..##...#....#.##.#...#.#....#......####...##..#...##.##.#..#########..#..#.##.##..#.#.#######.. +#.......#####..###..######.#..##.#.#####..##...###...#.####.##...###..#.#.#####....#...#.##...#.#..# +.##..#...#####.##.##......#...#.#.#.###.#.#.#...##.#..#....###.....#..#.#.###......#####.###.#..##.# +.....###.#.#.#..##...#...###..#...#.#.##..###.##.#####.##..#.#.#.#.#####....#.#.#####...##.#..#.#.#. +###...##.#..#.####..##.#..##.#.#.#...#.#..#..##..##..#.#.#.#.##...##..#..#.....#....#####.#.#.####.# +....##....#.#.....#...###.#...##..##.##..#..###..##.###..#####..#...#####.##.#..#.#.#.###...####.### +##.##.##.#...#..#...........##.##.###.#...###.####.#..#..#...#..#..####.#.###########..#.###.###.#.# +##.##..##.####..###...##...#....###.###.#..##..#..#.###.#..####.#..##.#.#...#..#.#.##.##...#...#.... +..##...#.#.##....##...#.#.#......##.##.#.#.####.####....####.#.###.##.#.#..####..#..######..#..#.#.. +####.#.##.......##.###....##.#..####.#.#######..#...###..##.##..#...#...####........#.#..##...#....# +#..#.#.....#..#.###..#.#...###..##...#.#..#.#.##..#...##.##.##.#.#.#..#.####.########....########..# +#...#..##.##..#.#.#.##.##.##.#..#..#.##....#....###.#.###.#.#..#....#...##..#.....####...##.#..#...# +.###...##...####....###.##.#..####...##.#.##.#..##..##....#....##.#...#..#..##..##..##.#...#...###.. +.#..##.#..##..####..#.#.##..###.#...#....##.###...#.###....#.#.#........#..#.#.#..##..#####..#..#.#. +.#.##.....#..#...#.##.....#.##..#..#....#..#..#....#.##..##...#.##.##..##..#.#.#.##..####.##..#.#..# +...###.#.....#...#.##.#.###.#...##..#.###..#..#..#.#..#...###.#.##.##.##.#.##.#####.#..#.#..#.#...## +#.#.#.#.##.#.....##..#.###......##.#.##..#...#.########.##.###..#..#..##..##.#..##..###.#.###...#.#. +..##...##...#...###.#..##..#..#..#.#.##..##......##..##.....##.....####..#.##......#..####...###..## +##.......#..##....###...###......#.##.##....######..###.##...##.#...#...#.....#.###.#.#..#.##..#..#. +#.#..#..#.#####.##.##.###..#...###.....#..##..####...#.#.###....#..#.#.###.####..#.#........##.#.... +..###.#...##.#.####.#.##.##.....##...#.##.#.###.#.#..##.#..##..#..##.##....#.#####.##..#######.....# +###.###..##.#..##...#####..##.####....#.##......##......#.#....##.####.#.#.#.###...#..####..#.###### +#..###...#.#.......#..####.####...#....###.###...#.##..##..#..##.##.......####.##...#.#.#.##.#.#..#. +..#...#..###.##..#.#.#.##..#..#.#.......###..###..#####.#.#.#.#.#..#.#.#.#..###....#.####..###...#.. +...######.###....#..####.####......#...#.###.#....#...####.##........##...##.#..##.###.#..#..##..### +.#..###.####.###.#.#..#..#..#.##.#.#.###.##..####.#####..##....##.#.##...###.####.#.#######.#..#..#. +.#..##.#..##..#...##...#..#..##.#.#....##.##...###.#.#...##..##..#.###.#.#.#.#...#....#.#..#.#.###.# +.###..#.#..####.#########...####....####.#.##...##.##..#.##.#........#.....###.###.######.##.....### +..##.##..##..#.####.#..#####.#....##.##.#####.....#.#......##...#####..####....###..#.#...#..####..# +.#..##..##.##.##.##.#.###.###.#..#..#...###.#.##..##...##...###...##.###..#.#.#####.#.#.##....#.##.. +...#.#....##.#.....###.##...#..##....#...###....#..#.###...##.#...###.#....#...##..###.#.....##....# +.#######..#...##.#.###.##.#.###...##......#.###.#...#.###.#.#.#..#..#####..#########...##..##...#..# +.#..#.##...#.#..#.##..#.#.#.##.....####.#..#.###..##.#.#.#...#....#.#..##.######...#.#..##.##...#..# +#.#######.#####..#####.##.##.#.#.##.###..#....####.#..##.##.######..###...#.#..#.####.##.##....####. +...##..#...##..#..#.....#.##...#.....##.#####.###.########.######..#...###..#.##.#.#.##..#.#.##..##. +#..#..#.#....###.#...##..####.#.##..#.####.###..##.#...#.###.#..#.##..#######.#...#..#.#..##.#....## +..#.##.#.####..##.###.###..#.##.#.####..##....##.###.#..##.#.###.###.##.##.#####..#.#...########.... +.#.#.###..###...#...#..##.##......#..#...#.#.#.######.#.#...##..##........#....###..##...#..##.##... +##..#....##.###...##.#.##.##.##..#....#.#.#..#..####.##..#...#...#..#..#####.###...#..###..#...#.#.. +##.#.#.##.###.....######.#.....#...#.##....###.#.##.#.#.##..##.######.#####....#.#####...##.#..###.# +######.#...####..###..##..#..##...#.#....##.#...##...#.....#...##....#.##..###..###...###..#..###### +.....##.........#####.#.##..#..#.#.#.#.##...#....#.....###.########...#..####..#...#...##..#.##.##.# +#..###...#.##.##.#.#..####.#.....##..###....##..#...#.#...##.##..###..####...#.####..##..#..##..#... +#.####.#..##.#..#.....#..#.#..###...######.#.........####....###..#.#.#.##.#..#...#..####.....##..#. +..##....#.###.......##.#...#.####..##....##.#..#....#######...####.##..#####.#.#.#.#.##..##..#.#.#.. +#.#.#.###..#..#.#..#.#.###....#...#####.###...........#.#....#####...#..####....#...###.#..#..####.. +.......#.####.##...#..#.##..###..#..#.#.#.#.###....#....#.#.#..#.#..##.#####.#.....#.##.#.###.###.## +..###...#..#...####.#..##..##.#.#..#...#.#..#....###.#..####..######...####.#.##..#.#..###...##.#### +..#.###..#.#...##...#.#....#..#...#.#..##.######.######.#.##.....#..##.#..###..#..#.##.###...#..#.## +####..##.####.....#...#.#.###..#...####.###.#.#.#.......##...#....#..#....#.#......###...#####.#.##. +#..##..#..#.####...#####.#.###.##.#.##.....#.#..#.##........######.#.#.###....##.##..##..########.## +#.#....###.##....#######.#...#.#.#.#..##.#.##...#.###...#.#.#..#.#..####.#.#..#..#.##.####....#..##. +####.##....#.......###..#..##.#.#.##..#...#...##.###....##..###.#.#...#..#.....##.###.##...###....## +..##.#..#....######..#.##.#.#...##..####.#####...##.#..###.##...#..####..###.##..##.##.#####.#..#.#. +.#.##..#..##.#.###.###....#.#..#....#...###.##.#.#.####.....#....#...#.....#....#.#.###.#..#.##..### +..###.#.#.##...##.##.##.#...#####.#..##.#....##..####...###..#....#.##...#........#####.#.###.#..#.. +....#..##..##....#.#....#.#..##...##.#...##.###.#.#..###..##.##.##..#.#.#..#.#.##.......#.##.###..#. +.#..##.##.####.##....##.##.....###..##.#.##...#..###....###.###....#.#....#....#.##.#.##.#.##.....## +#.#..#.##.###.#.######.....###.#..#...#.#.....##.###.#...#.#..###.#.....##.###.#.###.####..#####.#.. +#.#.##......#.##.#.#..##....#..###.#.###...##...###.#..#.##...#..#.##..##.#...######.##.....#####.## +#.#..#####....###.###...#.......#....###.##...#..#.##..#...#####..#..#.##......###...#...###..#.#..# +#.##..##.##.#..#.##.##..#.###.##.........###.#.#..#.#.....#.#...#.#.##.#.##.#...#...####.#.......##. +.#...####.##..#..##....####..######...#.#..##.##.....#####.#...#..#.####.#######...#.#####..#.###... +.#..######.#.##..##...##.....###.#..##..#...####..###...###.###..#..######.#....########..#####...#. +#..##.......#####...###..#.#.##.#..###.#...##.#..#.##.###...###...##.#..##..########..#.#..##..#.### +.#.#..#...#.#..#..##...#.#.##...###..#..#....###.#....#.##....###.###..##..#.#.####..####.#######.## +...##..##.##.###.##.###...##.#.#.....##.####..#..##.#..#.####...##..#..#.##...##...###.##.#.......## +.#.....#.##..#.#.....#.##.##..###..#....###...#.#....##########.##.###.#...#.####..####.#..#.#..###. +.##.#.#.##..#..###.###.##.#########.#.#.#.#.##.###..##..#.##.####......#####...#..####.#.##..#####.# +..#....###...##....#.###..##..#..####.##..####.#..####.###.#....####.....#.###..##...##..####...##.# +.###.....###.##.##..###.###.....##..#.######.#.#..##..#.##.#..#.#.#....#...#.#.#...#...##....#..##.# +..##....#..#####....#..####.#.#...##.#....##..##.###.###....###......#...#.#####.......#...#.....### +###.#..#.#.##..#..#...#.#....###.##.#.###.#...#.##.#..#.#.......#.#.#.###.####.###....#..##..#####.. +.#..#######.#..###.#.##.#####.#####...##..#.####.#.#.##..###...#..##.##..#.#.###..#....#..#...###.#. +..#####..#.##.....###..##.#...#.#.#..#######.#..#...#.##.##.#.#....####...###..##...#....####.#..#.# +.####..#.#.##.###.#.##.....#..##.#.....###.....#..##...#....###.###..#......###.#.#.#.##.#.##..#...# +##.#..##.#..##...#.#....##..######..#.....#..#...#####....##......####.##..#...##..#.##.#.#######..# +##..####.#...##...#.#####.#.#..#....#.#..##.####.#..######.#..#..#.......#####..#..#..###.##...##.## +#.####......#.###...#..####.#..##.##..#.#...##.###.#...#####..####.#..#.#.....#.##...###...#.#....## +###.#.#.##.######......#.#.#.#.#........#..#..###.#.#.#..#.........#..#....#.#..#..#..###.##......## +##.#########...#...###..#.###.....#.#.##.........###....#.####.#...###.#..##..#.###..#..##......#.## diff --git a/2015/day-18/inputs/test.txt b/2015/day-18/inputs/test.txt new file mode 100644 index 0000000..6ddce72 --- /dev/null +++ b/2015/day-18/inputs/test.txt @@ -0,0 +1,6 @@ +.#.#.# +...##. +#....# +..#... +#.#..# +####.. diff --git a/2015/day-18/main.rb b/2015/day-18/main.rb new file mode 100755 index 0000000..57288b7 --- /dev/null +++ b/2015/day-18/main.rb @@ -0,0 +1,131 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "pathname" +require "set" + +class Grid + NEIGHBOR = { + n: [0, -1], + s: [0, 1], + e: [1, 0], + w: [-1, 0], + ne: [1, -1], + se: [1, 1], + nw: [-1, -1], + sw: [-1, 1], + }.map(&:freeze).to_h.freeze + + def add_row(row) + @area ||= [] + row = row.map { |x| x == "#" ? 1 : 0 } + @width ||= row.size + @area.push(row[0..@height]) + end + + def to_s = @area.map(&:to_s).join("\n") + def row_count = @area.size + def col_count = @width + + def dup + grid = self.class.new + grid.instance_variable_set(:@area, @area.map(&:dup).dup) + grid.instance_variable_set(:@width, @width.dup) + grid.instance_variable_set(:@sticky, @sticky&.dup) + grid + end + + def []=(x, y, val) + return if @sticky&.include?([x, y]) + @area[y][x] = val + end + + def [](x, y) + @area[y][x] + end + + def make_sticky(x, y, val = 1) + @sticky ||= Set.new + self[x, y] = val + @sticky.add([x, y]) + end + + def count_on + @area.sum { |r| r.sum } + end + + def advance(steps) + steps.times do |step| + change_count = advance_step() + return step if change_count.zero? + end + end + + private + + def advance_step + changes = [] + + @area.each_with_index do |row, y| + row.each_with_index do |_, x| + nb_on_count = neighbors_that_are_on(x, y) + + if self[x, y] == 1 && (nb_on_count < 2 || nb_on_count > 3) + changes.push([x, y, 0]) + elsif self[x, y] == 0 && nb_on_count == 3 + changes.push([x, y, 1]) + end + end + end + + changes.each do |(x, y, val)| + self[x, y] = val + end + + changes.size + end + + def neighbors_that_are_on(x, y) + NEIGHBOR.keys.sum { |d| neighbor_on?(x, y, d) ? 1 : 0 } + end + + def neighbor_on?(x, y, direction) + nb_x, nb_y = NEIGHBOR[direction].then { |(nx, ny)| [x + nx, y + ny] } + return false if nb_x < 0 || nb_y < 0 + + neighbor = @area.dig(nb_y, nb_x) + return false unless neighbor + + neighbor == 1 + end +end + +def parse_file(file) + file.each_line.each_with_object(Grid.new) do |line, grid| + grid.add_row(line.chomp.chars) + end +end + +def main(file_paths) + file_paths.each do |file_path| + puts "File: #{file_path}" + + grid1 = parse_file(file_path) + grid2 = grid1.dup + + grid1.advance(100) + solution1 = grid1.count_on + puts " Solution 1: #{solution1}" + + grid2.make_sticky(0, 0) + grid2.make_sticky(0, grid2.col_count - 1) + grid2.make_sticky(grid2.row_count - 1, 0) + grid2.make_sticky(grid2.row_count - 1, grid2.col_count - 1) + grid2.advance(100) + + solution2 = grid2.count_on + puts " Solution 2: #{solution2}" + end +end + +main(ARGV.map { |x| Pathname(x) })