横浜へなちょこプログラミング勉強会にて過去に出題された境界線分を解いてみた。
回答にかかった時間は50分程度。
LineSegments#count
の中身は初めcline
とnline
をzip
し、1マスずつ比較してから結果を出していたのだが、よくよく考えれば隣り合う行のビットXORを取るだけでよいことに気付いたので書き直した。
class LineSegments
def initialize input
@field = input.chars.each_slice(2).map{|c| ("%06b" % c.join.to_i(8)).chars.map &:to_i}
end
def lines
count(@field).zip(count(@field.transpose)).map{|r1, r2| r1 + r2}
end
private
def count field
field.each_cons(2).each_with_object(Array.new(6){0}){|(cline, nline), sum|
("%06b" % (cline.join.to_i(2) ^ nline.join.to_i(2))).scan(/1+/){|m| sum[m.size - 1] += 1}
}
end
end
test = <<_TEST
/*0*/ test( "060276724276", "6,2,1,1,0,1" );
/*1*/ test( "770175454177", "2,3,0,3,1,0" );
/*2*/ test( "743733377170", "9,3,1,0,0,0" );
/*3*/ test( "724212121273", "5,2,1,1,1,1" );
/*4*/ test( "100000000000", "3,0,0,0,0,0" );
/*5*/ test( "000002000000", "4,0,0,0,0,0" );
/*6*/ test( "003622223600", "0,4,0,4,0,0" );
/*7*/ test( "520073737070", "8,3,1,1,0,0" );
/*8*/ test( "770077007700", "0,0,0,0,0,5" );
/*9*/ test( "555555555514", "2,0,0,0,2,2" );
/*10*/ test( "764252427600", "4,0,4,0,2,0" );
/*11*/ test( "774555554177", "3,3,1,3,0,0" );
/*12*/ test( "674574754557", "11,5,0,1,0,0" );
/*13*/ test( "000000000000", "0,0,0,0,0,0" );
/*14*/ test( "777777777777", "0,0,0,0,0,0" );
/*15*/ test( "774377777577", "6,0,2,0,0,0" );
/*16*/ test( "070777777777", "0,1,1,0,0,0" );
/*17*/ test( "373737373737", "0,0,0,0,0,1" );
/*18*/ test( "603260327725", "30,0,0,0,0,0" );
/*19*/ test( "466331144663", "30,0,0,0,0,0" );
/*20*/ test( "000000000242", "3,2,0,0,0,0" );
/*21*/ test( "567656043772", "18,2,1,0,0,0" );
/*22*/ test( "200763012420", "15,4,1,0,0,0" );
/*23*/ test( "400101140052", "14,3,0,0,0,0" );
/*24*/ test( "764767476476", "13,2,0,1,0,0" );
/*25*/ test( "001110140110", "12,2,1,0,0,0" );
/*26*/ test( "765405076527", "16,3,0,1,0,0" );
/*27*/ test( "377323370373", "8,4,2,0,0,0" );
/*28*/ test( "250541131216", "11,5,2,0,0,0" );
/*29*/ test( "744165741476", "12,3,2,0,0,0" );
/*30*/ test( "042101000300", "10,3,0,0,0,0" );
/*31*/ test( "002004554101", "11,3,1,0,0,0" );
/*32*/ test( "371707762706", "15,1,1,0,0,0" );
/*33*/ test( "130371310175", "7,3,1,2,0,0" );
/*34*/ test( "212537003613", "13,2,1,1,1,0" );
/*35*/ test( "157700063411", "15,3,0,0,0,1" );
/*36*/ test( "011500036007", "6,7,1,0,0,0" );
/*37*/ test( "743113313517", "17,2,1,0,0,0" );
/*38*/ test( "174105270405", "13,3,1,1,0,0" );
/*39*/ test( "427272200311", "13,3,2,0,0,0" );
/*40*/ test( "725370332237", "12,5,1,1,0,0" );
/*41*/ test( "005640420046", "12,1,3,0,0,0" );
/*42*/ test( "700350001101", "14,3,1,0,0,0" );
/*43*/ test( "577627744076", "16,1,1,1,0,0" );
/*44*/ test( "620332232007", "10,4,2,1,0,0" );
/*45*/ test( "260406401000", "15,1,1,0,0,0" );
/*46*/ test( "737272723276", "5,0,0,0,3,0" );
/*47*/ test( "000400040444", "7,0,2,0,0,0" );
/*48*/ test( "370222002177", "13,2,2,0,0,0" );
/*49*/ test( "372236024656", "9,3,2,0,1,0" );
/*50*/ test( "276131137003", "11,6,2,0,0,0" );
/*51*/ test( "742134007240", "13,4,2,0,0,0" );
/*52*/ test( "777721775571", "13,1,2,0,0,0" );
/*53*/ test( "700301232233", "11,2,3,0,0,0" );
_TEST
require 'minitest/autorun'
describe 'LineSegment' do
test.split("\n").each do |line|
t, n, input, expect = line.match(/^\/\*(\d+)\*\/\s*test\(\s*"([^"]+)",\s*"([^"]+)"\s*\);\s*$/).to_a
ls = LineSegments.new input
it input do
assert_equal expect, ls.lines.join(",")
end
end
end