diff --git a/README.md b/README.md index 60a23f9..aad9aee 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Consistency is hard without proper goals to set a good (let's dare say "atomic") I'm also adding notes that may be useful if you're learning Ruby. Notes for solving: -* [2015, up to day 17](year_2015.md) +* [2015, up to day 18](year_2015.md) * [2023, up to day 03](year_2023.md) # How to use diff --git a/spec/year_2015/day_18_input b/spec/year_2015/day_18_input new file mode 100644 index 0000000..6a14c51 --- /dev/null +++ b/spec/year_2015/day_18_input @@ -0,0 +1,100 @@ +###.##..##.#..#.##...#..#.####..#.##.##.##..###...#....#...###..#..###..###.#.#.#..#.##..#...##.#..# +.#...##.#####..##.......#..####.###.##.#..###.###.....#.#.####.##.###..##...###....#.##.....#.#.#.## +.....#.#.....#..###..####..#.....##.#..###.####.#.######..##......#####.#.##.#########.###..#.##.#.# +...###......#.#..###..#.#.....#.##..#.##..###...#.##.#..#..#.##.#..##......##.##.##.######...#....## +.###.....#...#.#...####.#.###..#..####.#..#.##..####...##.#...#..###...###...####..##....####.##..#. +..#....#...#.......#..###.###....#.##..#.....###.#.##.#....#.#....##.##..#.##.#..###.###.##.##..##.# +##..#####.#.#....#.#...#.#.####..#....#..#....#.#..#.#####...#..##.#.....#.##..##.####......#.#.##.. +.#..##..#.#.###..##..##...#....##...#..#.#..##.##..###.####.....#.####.#.....##.#.##...#..####..#... +#.#####.......#####...#...####.#.#.#....#.###.#.##.#####..#.###.#..##.##.#.##....#.##..#....####.#.# +#.##...#####....##.#.#.....##......##.##...#.##.##...##...###.###.##.#.####.####.##..#.##.#.#.####.. +#.##.##....###.###.#..#..##.##.#..#.#..##..#.#...#.##........###..#...##.#.#.##.......##.....#...### +###..#.#..##.##.#.#.#...#..#...##.##.#.########.......#.#...#....########..#.#.###..#.#..#.##..##### +####.#.#...#.##.##..#.#...#....#..###..#.#.#.####.#.##.##.#..##..##..#..#####.####.##..########..##. +.#.#...#..##.#..#..###.#..####.......##.#.#.#.##.#####..#..##...#.##...#..#....#..#..###..####.#.... +..#.#...#....##...#####..#..#...###.###.....#.###.#....#.#..##...#.##.##.####.#.#.#..#.##.#....#.#.. +#....###.####.##..#.#.###..###.##.##..#.#...###..#.##.#####.##.#######..#.#...##.#..........####.### +#.#####.#......#.#......#.....##...##.#.#########.#......##..##..##.#..##.##..#....##...###...#.#... +#..#..##..###.#.#.#.#.....###.#.####.##.##....#.#..##....#.#..#.####..###.##...#######.#####.##.#.#. +..###.#........##.#...###..#.##..#.#....##.#......#..#.##..#.#..#.#..#.####.#####..###.##..#.##.#... +##.###....#..##...#..#.#......##..#...#..#.####..#.##...##.####.#...#..###...#.#.#....###.##..#.#... +..##.##.#.##..##.#..#.###...##..##..#....##..##...####.#..####.###...#.....#..#.##..##..###..#.#...# +#.#....#.....#...##.#...####..#..##..##.####..##..##...####...#....##.#.#######..##.#......######.#. +#.#...###.######.######..##..##....#.#......#......#.#.##.#.##.#.#.#...#...#....#.#.#.#..#.##..#...# +####.###.#.#.##..#.##.#...#.##...#.##.##...#.....#.#..#.####.##..######.#..#.#..##....#.#.#..#.#.#.# +..##......#.#...#.##.##..##..##..#..##..#########.#..###..###.##...#..##.#..#.#.#.######..#....#.#.. +..##.##.#...###.#...##..######.##.#..####..#..#.#.##.####.##.##.#...##....#...###.##.####..#....#.#. +####...###..#.#.##.#.#....###..##.#.#..########..#...#.#...#.##....##.##...#.....#.#.....#.....#.... +.#.###############....#.##..###..#.####.#.##.##..#..#.#...###...##..##.##.#.....##...###.###.....#.. +.###..#..##.##..####.#.###.##.##..#..##....#.#......#......##.#...#.#...#..##.#.#...#...#.##..#.##.. +###.#.#.########.#.#..####.#..##.#.##.##.###.##..######...#..##.##.#..#.#...#.##..#####.....#.#.#..# +.##.##..#.#...#####.#.#.###...##...####...#......#...#..####..#.##..........#..#.#..###....######.## +..#####...#.#.#.#..#.##..#...#.#..#.##...##..##.##.#.##.#..#.#...#.......##.#...###.....#...#.#.#.## +##.##.#..######.##...#.....#.###.#..##.#.#.#..####.#....##.#....####...##....#.#.##.#..###.##.##..## +.###.##.#..#.###.####..#.##..####.#.#.##..###.#######.###.###...####........##....###.#...#.#.####.# +........#..#.#..##..########..........#.##.#..##.#...#.....####....##..#..#.#####.###...#...#.##.### +.....#..##.####...##.#####..######.##.#.###.####.##.##.#..##.##.######.##......#..#.####..##....#.## +##...####....#.##.##.###....#.#...#.####..##.#.##.#.#...####.#.#.#.#...##.###...##...###...######.## +.#....#.#.####...#.##.....##...###.#.#.##...##.#####....#.######.#.#....##..##...##....##.#.##.#.#.# +.###..###.#.......#.#######..#.#.#.######....#.#####.#.....#.#########...#....##...##.####.#..#..... +##.#..##..##.....#..##...#..##.##.#..#.#####.##.##.#.##.##...##.######.####..#.##..#####.##...##..#. +#.###...##.#.#.#.##....#.#.##.##..#....#...#.#.........#..#..####..####.####..#.##.##.#....####..##. +.#..######..#####.####.##.#.....#.#.#####..##..###.#.#.#..#.#...#.#######..##....##.##...#######..#. +#...#....#.#.##..#####..#########..#.....#...##.#.#.###...#####..##...##...####.......#######.#..### +.#......#...##.###..#....#...#.#.....#.#...##.#.#..#..###.##.###.#.##..##...#.##......#.###..#.#..## +.#....####...###..#.....##..#...#.#.###.#.#.##...#.##.##.#.#.#..####..###.#.#.#.##.#.#...#..#...#### +......##.##.#...#####.##..#.###..#.#####..##.#..##.###......#...#...#..#......###.######...#.#.##..# +###..#...#.##..###.#....##...#..#####.#.#..#.###...#####.#....##..####.#.##...#.#...##..#.#.#.#..#.# +...##.#.##.##..#.#.#.###.#.#...#.....###.###.##...#.###.##...##..#..###.#..##.##..###.#....###..##.. +.##.#..###..###.##.##...#..#####...#.....#####.##..####...#.##.#.#..##.#.#.#....###.....#....##..... +######.#..#.#..#....#.###...####.####.#.........#..##.#..##..##.....#..#.##.##...#...#####.#.##..#.# +.##.###...####....#.####...#####..#..#...#..#.....###.#..#.###..#.###.#.......##.####..#.##.#...##.. +........#.#.##.#.....#####.###......##..#.##.#..#...####.#...#..###.#.#...##..#.#...#.####...#.#.### +.#..#.##..##...######.###.##.#.#...#.#.#.#.##..##..##.#.##..#....#.##...#.##.##...##....##.###.##.#. +##...#...#...###.#.#...#...#..###......##.#.#....##..##.#..##.#.######...#..##.#.##.#.#....#.##.##.. +...#..###.#....#...#.##..##.#.##.#..###.##..#.##..####.#########....#.....##.#.##.##..##.##.######.# +#.##.#..##.......###...#.###....###.#..####..##.#####.##.###....##....#.###...####..#.#.#.##.....### +.......#...#...##.#...##.#.#..#.##..##.#....###...##.#####...#.........#.......###.##.#.#.###....##. +###.#.##.##.....#.#..#.#..####.####..#..###..........####.#.##...#######.###..#####..#.....#..###..# +#...##.##..####.##.###.#.#######..###.#..#######..#.##.####...#..#.##.####..####.#.#.......####.#... +...#.##..#..#..##........#.#..#..#.#....#.###.#.###..#.......###..#.....#....#..##.#...#.###...##.#. +###.##..#.##.#.#####..#.##.####....#####..###.#.#..#...#...###.#.##..#.#.#.....#.####.#.#.#.#.#.#... +..##..##..#..##.##.#...#..#....####....#...#..####..#.....######.###.####.#....##....##.#.#.###....# +.#.#.#.##..####..#.....#.####.#....#.....#....#.##..#.#..#.#...#.#.#.#..#..#..##.#....####.......#.. +..##.##..###......#...#..##...#.###.####.#...#.####..#.#.#.....#.#...####...#.########.##.#.#.#..### +#....#.##.....##.###.##.###..#.####.....####.##...#..##.###...###..###.#....####.#..#..#..#.#..##.#. +.#.#.##....#.##......#.#..###.#....###....#......#.#.##.##.#########..##..#...#.####..#...####..#..# +.#.#.......##.#.##.#...#...#.##.#..#.#.#.##....#..###.###.##.#.#...##.#..#..##....#..###.#...#.#.##. +#.##.#....####...#..##..#.#.#.#.##.#...#####.#...#..#..#.####.####.#.#....#......##..##..###...#..## +..##.###..##.####..#..#..##...###.#.#.#######.####...####......##.##..#...#.##...##....#..#..#.....# +....#..#..#.#.####.#...##..#....####.#..####...#.#...###...#..#..##...#....##...#.....#.#..#.#.#...# +...#.#.#.##..##.###..#.######....####.###...##...###.#...##.####..#.#..#.#..#.##.....#.#.#..##...... +.#.##.##.....##.#..###.###.##....#...###.#......#...##.###.#.##.##...###...###...#.######..#......#. +###..#...#......#..##...#....##.#..###.##.####..##..##....####.#...#.#....##..#.#######..#.#.#####.. +##...#####..####..##....#.#.###.##.#..#.#..#.....###...###.#####.....#..##.#......#...#.###.##.##... +...#.#.#..#.###..#.#.#....##.#.#..####.##.#.####.#.#.#...#....##....#.##.####..###.#.#...##.#..#..## +#.#.#..#.##..##.##.#...##.#....#...###..##..#.#######.#.###..##......##.#..###.########.#.##..#.#.## +######.###....##..#..#...####....#.#.#..#...#..######.#.#.##..##....##....##.##.##...#..#.####.#.#.. +#####.###..#..###......##...##.####.#.#.#.###.......##..##.####..##.####.#..#..####..#.####.#####... +##.#.#.###..##.#.##.#.#.#.##.#...##........###.#.##..####....###.#.####.####.#.......##.##.##...##.. +#.#..###...#..##.....##.#..#.#..##..######.#####...###.#.......###...#..##..#..#..##.#.#....#..#..#. +#.#..####.###..#...#...#...#.###..#.#.#.#.#.#.#..#....#.##.##.##..###..####.#..##..##.###.###....##. +#..#.##.#####........#..#.##.#..##.#...#....#..#.##..###..##..##.##..#..##.#.#...#.#.##.#.##....#.#. +.......##..#.....#..#.#.....#.##...####.###..####..#.#.#.#..#.....#....##...#..#.##..###.#.#....#... +#...###########.##.....##...###.#.##.##..####.##...#.####.#####.#####.####...###.##...##..#.#.###..# +....#.#.###.####.###...#...#.#..###.#.#.##...#..#.#.#..#.####..#..###.######.#.####.###...###.#.##.# +.....#..#..########...#.#.#.#.#.#.#.#..###.##..####...##.#.#.#...##..#####.##.#...#.####.#######.##. +.......#...#.#..#..#...#..#..##.....#.##....##.##...##..##.##...##...#.#..#.##.#.###.#.####.#.#..##. +.####...#...#.#.#....##..........##.##.###.##.#.#..#.#.#......########.#...#.####.##.###..##...####. +#.#.#...##.###..##..#..#.....####.#.....##.##.#..#.#.###.#..#######...##..#.#..#.#..############.### +.##..####.#..#.....###..#..#.#.....#.#.#...##.##.#....#..#..###.#...#....#.#...####..#.....###.####. +..#...#.###.###....##.#..#.##..####.##.#.##.##.##...###.####..#.#.#.##.#.#.#..###..##.##.##.##.#..## +#...............##.....######.#.#####.##.#....#.#..#.##...#.##....#........##.##...#.##.##.#..#.##.# +#..##..#.#.#.##.#..#.#.##.##...#...#..#.#.##..#.#...###...##...###..#####.#.#..#..#.#..#.#.##...##.# +.#######.#.....##...#.#.####.######.#..#......#....##.#.#..#..###.#...###...#....#.#..#.##.#...#.#.. +#.###......##.#.##..#.###.###..####..##....#..###......##..##..#####.####....#...###.....###.#..#... +###...#....###.#..#.###.##...###.##.......##.##.#.#.#....####....###..##.###...#..##....#.#.##..##.. +.##.......##.######.#.#..#..##....#####.###.#.##.....####....#......####....#.##.#.##..#.##...##.#.# +.#.###...#.#.#.##.###..###...##..#.##.##..##..#.....###.#..#.##.##.####........##.#####.#.#....#...# +##...##..#.##.#######.###.#.##.#####....##.....##.#.....#.#.##.#....#.##.#....##.#..#.###..#..#.#... +.#..#.#.#.#...#.##...###.##.#.#...###.##...#.#..###....###.#.###...##..###..#..##.##....###...###.## \ No newline at end of file diff --git a/spec/year_2015/day_18_sample_one b/spec/year_2015/day_18_sample_one new file mode 100644 index 0000000..6ddce72 --- /dev/null +++ b/spec/year_2015/day_18_sample_one @@ -0,0 +1,6 @@ +.#.#.# +...##. +#....# +..#... +#.#..# +####.. diff --git a/spec/year_2015/day_18_sample_two b/spec/year_2015/day_18_sample_two new file mode 100644 index 0000000..f9d88a2 --- /dev/null +++ b/spec/year_2015/day_18_sample_two @@ -0,0 +1,6 @@ +##.#.# +...##. +#....# +..#... +#.#..# +####.# diff --git a/spec/year_2015/day_18_spec.rb b/spec/year_2015/day_18_spec.rb new file mode 100644 index 0000000..502afc5 --- /dev/null +++ b/spec/year_2015/day_18_spec.rb @@ -0,0 +1,88 @@ +require 'year_2015/day_18' + +describe Year2015::Day18 do + context 'when Part 1' do + subject(:sample_one) do + described_class.new(File.read('spec/year_2015/day_18_sample_one'), true) + end + + it 'is correct after one step' do + sample_one.step + expect(sample_one.to_s).to eq("..##..\n..##.#\n...##.\n......\n#.....\n#.##..") + end + + it 'is correct after two steps' do + sample_one.step(2) + expect(sample_one.to_s).to eq("..###.\n......\n..###.\n......\n.#....\n.#....") + end + + it 'is correct after three steps' do + sample_one.step(3) + expect(sample_one.to_s).to eq("...#..\n......\n...#..\n..##..\n......\n......") + end + + it 'is correct after four steps' do + sample_one.step(4) + expect(sample_one.to_s).to eq("......\n......\n..##..\n..##..\n......\n......") + end + + it 'gives a final result' do + sample_one.step(4) + expect(sample_one.to_i).to eq(4) + end + end + + context 'when Part 2' do + subject(:sample_two) do + described_class.new(File.read('spec/year_2015/day_18_sample_two')) + end + + it 'is correct after one step' do + sample_two.step + expect(sample_two.to_s).to eq("#.##.#\n####.#\n...##.\n......\n#...#.\n#.####") + end + + it 'is correct after two steps' do + sample_two.step(2) + expect(sample_two.to_s).to eq("#..#.#\n#....#\n.#.##.\n...##.\n.#..##\n##.###") + end + + it 'is correct after three steps' do + sample_two.step(3) + expect(sample_two.to_s).to eq("#...##\n####.#\n..##.#\n......\n##....\n####.#") + end + + it 'is correct after four steps' do + sample_two.step(4) + expect(sample_two.to_s).to eq("#.####\n#....#\n...#..\n.##...\n#.....\n#.#..#") + end + + it 'is correct after five steps' do + sample_two.step(5) + expect(sample_two.to_s).to eq("##.###\n.##..#\n.##...\n.##...\n#.#...\n##...#") + end + + it 'gives a final result' do + sample_two.step(5) + expect(sample_two.to_i).to eq(17) + end + end + + context 'when Results' do + subject(:input_data) do + File.read('spec/year_2015/day_18_input') + end + + it 'correctly answers part 1' do + result_one = described_class.new(input_data, true) + result_one.step(100) + expect(result_one.to_i).to eq(821) + end + + it 'correctly answers part 2' do + result_two = described_class.new(input_data) + result_two.step(100) + expect(result_two.to_i).to eq(886) + end + end +end diff --git a/year_2015.md b/year_2015.md index 23f1095..66cec5c 100644 --- a/year_2015.md +++ b/year_2015.md @@ -286,3 +286,29 @@ Year2015::Day17 ``` Nothing really complicated here, or that we haven't seen yet. + +## Day 18 + +``` +Year2015::Day18 + when Part 1 + is correct after one step + is correct after two steps + is correct after three steps + is correct after four steps + gives a final result + when Part 2 + is correct after one step + is correct after two steps + is correct after three steps + is correct after four steps + is correct after five steps + gives a final result + when Results + correctly answers part 1 + correctly answers part 2 +``` + +I already touched upon [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) earlier, and this exercise is a good example of it. + +I thought I was being smart by only keeping track of positions of only ON lights, which was a good implementation for a six-by-six data set, but proved UTTERLY SLOW on the final data set. Using an array of strings (as is the most naive implementation) is indeed the fastest way to do it. I still kept the old code commented. diff --git a/year_2015/day_18.rb b/year_2015/day_18.rb new file mode 100644 index 0000000..875e065 --- /dev/null +++ b/year_2015/day_18.rb @@ -0,0 +1,139 @@ +class Year2015 + class Day18 + def initialize(input_data, input_part_one = false) + input_data = input_data.chomp.split("\n") + @size = input_data[0].length + @version = input_part_one ? 1 : 2 + # @current_iteration_set = [] + # @current_text = input_data.each_with_index do |input_line, i| + # input_line.each_char.with_index do |input_char, j| + # @current_iteration_set.push([i, j]) if input_char == '#' + # end + # end + @current_text = input_data.map do |input_line| + input_line + end + add_corners if @version == 2 + end + + # def alive_now?(x_axis, y_axis) + # # return false if x_axis.negative? || x_axis >= @size + # # return false if y_axis.negative? || y_axis >= @size + + # @current_iteration_set.include?([x_axis, y_axis]) + # end + + # def alive_neighbors_for(x_axis, y_axis) + # [ + # [x_axis - 1, y_axis - 1], [x_axis, y_axis - 1], [x_axis + 1, y_axis - 1], + # [x_axis - 1, y_axis], [x_axis + 1, y_axis], + # [x_axis - 1, y_axis + 1], [x_axis, y_axis + 1], [x_axis + 1, y_axis + 1] + # ].count do |x, y| + # alive_now?(x, y) + # end + # end + # + # def alive_next?(x_axis, y_axis) + # case alive_neighbors_for(x_axis, y_axis) + # when 3 + # true + # when 2 + # alive_now?(x_axis, y_axis) + # else + # false + # end + # end + # + # def do_one_step + # @next_iteration_set = [] + # 0.upto(@size - 1) do |i| + # # puts "CHECK ITERATION #{i}" + # 0.upto(@size - 1) do |j| + # @next_iteration_set.push([i, j]) if alive_next?(i, j) + # end + # end + # @current_iteration_set = @next_iteration_set + # end + # + # def to_s + # 0.upto(@size - 1).map do |i| + # 0.upto(@size - 1).map do |j| + # alive_now?(i, j) ? '#' : '.' + # end.join + # end.join("\n") + # end + # + # def to_i + # @current_iteration_set.length + # end + + def cell_is_currently_alive?(x_axis, y_axis) + return false if x_axis.negative? + return false if y_axis.negative? + return false unless @current_text[x_axis] + return false unless @current_text[x_axis][y_axis] + + @current_text[x_axis][y_axis] == '#' + end + + def alive_neighbors_for(x_axis, y_axis) + [ + [x_axis - 1, y_axis - 1], [x_axis, y_axis - 1], [x_axis + 1, y_axis - 1], + [x_axis - 1, y_axis], [x_axis + 1, y_axis], + [x_axis - 1, y_axis + 1], [x_axis, y_axis + 1], [x_axis + 1, y_axis + 1] + ].count do |x, y| + cell_is_currently_alive?(x, y) + end + end + + def corner?(x_axis, y_axis) + (x_axis.zero? || x_axis == (@size - 1)) && (y_axis.zero? || y_axis == (@size - 1)) + end + + def alive_next?(current_status, x_axis, y_axis) + # return true if @version == 2 && corner?(x_axis, y_axis) + + case alive_neighbors_for(x_axis, y_axis) + when 3 + true + when 2 + current_status == '#' + else + false + end + end + + def add_corners + @current_text[0][0] = '#' + @current_text[0][@size - 1] = '#' + @current_text[@size - 1][0] = '#' + @current_text[@size - 1][@size - 1] = '#' + end + + def do_one_step + @next_step_text = @current_text.each_with_index.map do |line, x_axis| + line.each_char.with_index.map do |char, y_axis| + alive_next?(char, x_axis, y_axis) ? '#' : '.' + end.join + end + @current_text = @next_step_text + add_corners if @version == 2 + end + + def step(steps = 1) + return if steps < 1 + + 1.upto(steps) do |_step_idx| + do_one_step + end + end + + def to_i + to_s.each_char.count{|char| char == '#' } + end + + def to_s + @current_text.join("\n") + end + end +end