diff --git a/2020/ruby/day_20.rb b/2020/ruby/day_20.rb new file mode 100644 index 0000000..7c89960 --- /dev/null +++ b/2020/ruby/day_20.rb @@ -0,0 +1,55 @@ +class Tile + SIZE = 10 + + attr_reader :raw + + def initialize(raw) + @raw = raw + end + + def edges + { + top: @raw.fetch(0), + bottom: @raw.fetch(SIZE-1), + left: @raw.transpose.fetch(0), + right: @raw.transpose.fetch(SIZE-1), + } + end + + def to_s + @raw.map(&:join).join("\n") + end +end + +input = ARGF.read + .scan(/Tile (\d+):\n((?:[.#]+\n)+)/m) + .to_h + .transform_keys(&:to_i) + .transform_values {|v| v.split("\n").map {|row| row.chars } } + .transform_values {|v| Tile.new(v) } + +edges = input.flat_map {|id,tile| + tile.edges.map {|edge,data| ["#{id}_#{edge}", data.join] } +}.to_h + +inverted_edges = edges.each.with_object(Hash.new {|h,k| h[k] = [] }) do |(id,data),hash| + hash[data] << id +end + +matches = edges.map {|id,data| + [ + id, + [ + inverted_edges[data], + inverted_edges[data.reverse], + ].flatten.compact.reject {|other| other == id }, + ] +}.to_h + +corners = input.keys.select {|id| + %w[ top bottom left right ].count {|edge| + matches.fetch("#{id}_#{edge}").empty? + } == 2 +} + +p corners.inject(&:*)