http://nabetani.sakura.ne.jp/hena/ord2/
The problem is to erase a line of Tetris represented by bits.
Ruby
module BitTetris
module_function
def solve(input)
field = input.split("-").map { _1.to_i(16) }
to_be_erased = to_a(field.inject(:&))
field.map { "%02x" % erase(_1, to_be_erased) }.join("-")
end
def erase(i, to_be_erased)
to_a(i).zip(to_be_erased).map { |s, t| t == "1" ? "" : s }.join.to_i(2)
end
def to_a(i)
sprintf("%08b", i).chars
end
end
if __FILE__ == $0
require 'minitest/autorun'
describe 'BitTetris' do
[
["ff-2f-23-f3-77-7f-3b", "1f-03-00-1c-0d-0f-06"],
["01", "00"],
["00", "00"],
["7a-4e", "0c-02"],
["56-b6", "08-14"],
["12-12-12", "00-00-00"],
["de-ff-7b", "0a-0f-05"],
["95-be-d0", "05-1e-20"],
["7c-b0-bb", "1c-20-2b"],
["7a-b6-31-6a", "3a-56-11-2a"],
["32-0e-23-82", "18-06-11-40"],
["ff-7f-bf-df-ef", "0f-07-0b-0d-0e"],
["75-df-dc-6e-42", "35-5f-5c-2e-02"],
["62-51-ef-c7-f8", "22-11-6f-47-78"],
["0c-47-8e-dd-5d-17", "04-23-46-6d-2d-0b"],
["aa-58-5b-6d-9f-1f", "52-28-2b-35-4f-0f"],
["ff-55-d5-75-5d-57", "0f-00-08-04-02-01"],
["fe-fd-fb-f7-ef-df-bf", "7e-7d-7b-77-6f-5f-3f"],
["fd-fb-f7-ef-df-bf-7f", "7e-7d-7b-77-6f-5f-3f"],
["d9-15-b5-d7-1b-9f-de", "69-05-55-67-0b-4f-6e"],
["38-15-fd-50-10-96-ba", "18-05-7d-20-00-46-5a"],
["fe-fd-fb-f7-ef-df-bf-7f", "fe-fd-fb-f7-ef-df-bf-7f"]
].each do |input, expect|
it input do
assert_equal BitTetris.solve(input), expect
end
end
end
end
First, find the row to be erased by bit operation (field.inject (: &)
), and then erase the bits to be erased in each column with the erase
method. I was wondering what to do to erase the bit. After all, after expressing it in binary, I converted it to Array (to_a
method) and erased it with map
. I think it's a matter of how to use the binary and hexadecimal representations of String and Integer properly.
In addition, it should be notederase
I'm doing one liner with the methodary1.zip(ary2).map {|a, b| ...}
I often write something like thiszip
Recreating the Array in is not efficient, but it can be succinct. If you do it honestly (?), Is it like this?
def erase(i, to_be_erased)
a = to_a(i)
result = ""
a.length.times do |j|
result << a[j] if to_be_erased[j] != "1"
end
result.to_i(2)
end
This should be faster and more efficient.
Recommended Posts