changeset 20:fac484765bc9

Implement Day 13 mirror line finding Walking in a loop didn't work, but consecutive pairs give a great starting point. And there might even be a more Ruby-ish version of the WHILE loop using zip, reverse and array ranges.
author IBBoard <dev@ibboard.co.uk>
date Wed, 13 Dec 2023 20:32:13 +0000
parents 1e16a25a9553
children 46fb65f2cb94
files day13.rb day13.txt day13b.rb
diffstat 3 files changed, 170 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/day13.rb	Wed Dec 13 20:32:13 2023 +0000
@@ -0,0 +1,30 @@
+#! /usr/bin/env ruby
+
+if ARGV.length != 1
+        abort("Incorrect arguments - needs input file")
+elsif not File.exist? (ARGV[0])
+	abort("File #{ARGV[0]} did not exist")
+end
+
+file = ARGV[0]
+
+maps = File.open(file, "r").each_line().map(&:chomp).chunk_while {|before, after| before.length == after.length}.filter {|chunk| chunk != [""]}.map {|chunk| chunk.map{|row| row.each_char.to_a}}
+
+def find_reflection(data)
+	candidate_start = data.each_cons(2).with_index.flat_map {|vals,idx| a,b = vals; a == b ? [idx] : []}
+	valid_starts = candidate_start.flat_map do |start|
+		pos = start
+		reflected = start + 1
+		match = true
+		while pos > 0 and reflected < data.length - 1
+			pos -= 1
+			reflected += 1
+			match = data[pos] == data[reflected]
+			break unless match
+		end
+		match ? [start + 1] : []
+	end
+	valid_starts[0]
+end
+
+puts maps.flat_map {|data| [find_reflection(data).to_i * 100, find_reflection(data.transpose()).to_i]}.sum
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/day13.txt	Wed Dec 13 20:32:13 2023 +0000
@@ -0,0 +1,105 @@
+--- Day 13: Point of Indicence ---
+
+There is an area with mirrored layouts. For example:
+
+#.##..##.
+..#.##.#.
+##......#
+##......#
+..#.##.#.
+..##..##.
+#.#.##.#.
+
+#...##..#
+#....#..#
+..##..###
+#####.##.
+#####.##.
+..##..###
+#....#..#
+
+To find the reflection in each pattern, you need to find a perfect reflection across either a horizontal line between two rows or across a vertical line between two columns.
+
+In the first pattern, the reflection is across a vertical line between two columns; arrows on each of the two columns point at the line between the columns:
+
+123456789
+    ><   
+#.##..##.
+..#.##.#.
+##......#
+##......#
+..#.##.#.
+..##..##.
+#.#.##.#.
+    ><   
+123456789
+
+In this pattern, the line of reflection is the vertical line between columns 5 and 6. Because the vertical line is not perfectly in the middle of the pattern, part of the pattern (column 1) has nowhere to reflect onto and can be ignored; every other column has a reflected column within the pattern and must match exactly: column 2 matches column 9, column 3 matches 8, 4 matches 7, and 5 matches 6.
+
+The second pattern reflects across a horizontal line instead:
+
+1 #...##..# 1
+2 #....#..# 2
+3 ..##..### 3
+4v#####.##.v4
+5^#####.##.^5
+6 ..##..### 6
+7 #....#..# 7
+
+This pattern reflects across the horizontal line between rows 4 and 5. Row 1 would reflect with a hypothetical row 8, but since that's not in the pattern, row 1 doesn't need to match anything. The remaining rows match: row 2 matches row 7, row 3 matches row 6, and row 4 matches row 5.
+
+To summarize your pattern notes, add up the number of columns to the left of each vertical line of reflection; to that, also add 100 multiplied by the number of rows above each horizontal line of reflection. In the above example, the first pattern's vertical line has 5 columns to its left and the second pattern's horizontal line has 4 rows above it, a total of 405.
+
+Find the line of reflection in each of the patterns in your notes. What number do you get after summarizing all of your notes?
+
+--- Part 2 ---
+
+Every mirror line has exactly one smudge: exactly one . or # should be the opposite type.
+
+In each pattern, you'll need to locate and fix the smudge that causes a different reflection line to be valid. (The old reflection line won't necessarily continue being valid after the smudge is fixed.)
+
+Here's the above example again:
+
+#.##..##.
+..#.##.#.
+##......#
+##......#
+..#.##.#.
+..##..##.
+#.#.##.#.
+
+#...##..#
+#....#..#
+..##..###
+#####.##.
+#####.##.
+..##..###
+#....#..#
+
+The first pattern's smudge is in the top-left corner. If the top-left # were instead ., it would have a different, horizontal line of reflection:
+
+1 ..##..##. 1
+2 ..#.##.#. 2
+3v##......#v3
+4^##......#^4
+5 ..#.##.#. 5
+6 ..##..##. 6
+7 #.#.##.#. 7
+
+With the smudge in the top-left corner repaired, a new horizontal line of reflection between rows 3 and 4 now exists. Row 7 has no corresponding reflected row and can be ignored, but every other row matches exactly: row 1 matches row 6, row 2 matches row 5, and row 3 matches row 4.
+
+In the second pattern, the smudge can be fixed by changing the fifth symbol on row 2 from . to #:
+
+1v#...##..#v1
+2^#...##..#^2
+3 ..##..### 3
+4 #####.##. 4
+5 #####.##. 5
+6 ..##..### 6
+7 #....#..# 7
+
+Now, the pattern has a different horizontal line of reflection between rows 1 and 2.
+
+Summarize your notes as before, but instead use the new different reflection lines. In this example, the first pattern's new horizontal line has 3 rows above it and the second pattern's new horizontal line has 1 row above it, summarizing to the value 400.
+
+In each pattern, fix the smudge and find the different line of reflection. What number do you get after summarizing the new reflection line in each pattern in your notes?
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/day13b.rb	Wed Dec 13 20:32:13 2023 +0000
@@ -0,0 +1,35 @@
+#! /usr/bin/env ruby
+
+if ARGV.length != 1
+        abort("Incorrect arguments - needs input file")
+elsif not File.exist? (ARGV[0])
+	abort("File #{ARGV[0]} did not exist")
+end
+
+file = ARGV[0]
+
+maps = File.open(file, "r").each_line().map(&:chomp).chunk_while {|before, after| before.length == after.length}.filter {|chunk| chunk != [""]}.map {|chunk| chunk.map{|row| row.each_char.to_a}}
+
+def count_num_changes(row_a, row_b)
+	row_a.zip(row_b).map {|a,b| (a != b) ? 1 : 0}.sum
+end
+
+def find_imperfect_reflection(data)
+	candidate_start = data.each_cons(2).with_index.flat_map {|vals,idx| count_num_changes(*vals) <= 1 ? [idx] : []}
+	valid_starts = candidate_start.flat_map do |start|
+		pos = start
+		reflected = start + 1
+		num_changes = count_num_changes(data[pos], data[reflected])
+		while pos > 0 and reflected < data.length - 1
+			pos -= 1
+			reflected += 1
+			num_changes_in_row = count_num_changes(data[pos], data[reflected])
+			num_changes += num_changes_in_row
+			break unless num_changes <= 1
+		end
+		num_changes == 1 ? [start + 1] : []
+	end
+	valid_starts[0]
+end
+
+puts maps.flat_map {|data| [find_imperfect_reflection(data).to_i * 100, find_imperfect_reflection(data.transpose()).to_i]}.sum
\ No newline at end of file