AREA_DIGIT_SIZE = 10 ** Math.log(AREA_SIZE).to_i # 10^(エリア1辺の長さの桁数)
-def get_opposite_angle friends, enemies, i, y, x
- friends[i..-1].each{|s, d|
- # x, y座標が一致しても自分の駒とエリアを構成する対角の駒との間に敵の駒があってもスキップ
- if e == d && !enemies.index{|u, f| r <= u && u <= t && c <= f && f <= e }
+def calc_area friends, friends_xc, friends_yc, enemies, enemies_xc, enemies_yc
+ friends_yc.each{|self_y, self_xs|
+ self_xs.each.with_index(1){|self_x, i|
+ self_xs[i..-1].each{|opp_x|
+ next unless opp_ys = friends_xc[opp_x]
+ next unless opp_ys = opp_ys[opp_ys.index(self_y)+1..-1]
+ #p [self_y, self_x, opp_ys, opp_x]
+ next unless friends_xc[self_x].include?(opp_y)
+ next if enemies.find{|u, f| self_y <= u && u <= opp_y && self_x <= f && f <= opp_x }
+ # self_y: top-y, self_x: top-x, opp_point[0]: bottom-y, opp_point[1]: bottom-x
+ (AREA_DIGIT_SIZE*self_y).step(AREA_DIGIT_SIZE*(opp_y-1), AREA_DIGIT_SIZE) {|i|
+ (self_x...opp_x).each {|j|
-def calc_area_c friends, friends_xc, friends_yc, enemies, enemies_xc, enemies_yc
- friends.each_with_object(Set.new).with_index(1){|((row, column), area_unit), index|
- next unless y = friends_xc[column]
- y = y[y.bsearch_index{|e|row<=>e}+1..-1]
- next unless x = friends_yc[row]
- x = x[x.bsearch_index{|e|column<=>e}+1..-1]
- # 自陣営の中から上で集めたx,y座標と一致する駒を抜き出す
- z = get_opposite_angle friends, enemies, index, y, x
- # row: top-left, column: top-right, z[0]: bottom-left, z[1]: bottom-right
- (AREA_DIGIT_SIZE*row).step(AREA_DIGIT_SIZE*(z[0]-1), AREA_DIGIT_SIZE) {|i|
- (column...z[1]).each {|j|
-def calc_area friends, enemies
- friends.each_with_object(Set.new).with_index(1){|((row, column), area_unit), index|
- # 自陣営の全ての駒の対角となりうる駒を集める
- # 自分のy座標より大きいy座標の値を持ち、かつ同じx座標を持つ自陣営の駒を集める
- next unless y = friends[index..-1].select{|_,d|d == column}.map{|s,_|s}
- # 自分のx座標より大きいx座標の値を持ち、かつ同じy座標を持つ自陣営の駒を集める
- next unless x = friends[index..-1].select{|s,_|s == row}.map{|_,d|d}
- # 自陣営の中から上で集めたx,y座標と一致する駒を抜き出す
- z = get_opposite_angle friends, enemies, index, y, x
- # row: top-left, column: top-right, z[0]: bottom-left, z[1]: bottom-right
- (AREA_DIGIT_SIZE*row).step(AREA_DIGIT_SIZE*(z[0]-1), AREA_DIGIT_SIZE) {|i|
- (column...z[1]).each {|j|
- sorted_input = input.split(?,).map{|e|
- e.scan(/\d+/).map(&:to_i).zip(e.scan(/[a-z]/).map(&:ord))
+ w, w_xc, w_yc, b, b_xc, b_yc = input.split(?,).map{|e|
+ sorted_input = e.scan(/\d+/).map(&:to_i).zip(e.scan(/[a-z]/).map(&:ord))
.sort_by.with_index{|(_,c),i|[c,i]}
- if sorted_input.map(&:size).inject(:+) > 40
- w, w_xc, w_yx, b, b_xc, b_yc = sorted_input.map{|e|
- [e, e.chunk{|_,x|x}.map{|k,v|[k,v.map(&:first)]}.to_h, e.sort_by.with_index{|(r,_),i|[r,i]}.chunk{|y,_|y}.map{|k,v|[k,v.map(&:last)]}.to_h]
- [calc_area_c(w, w_xc, w_yx, b, b_xc, b_yc), calc_area_c(b, b_xc, b_yc, w, w_xc, w_yx)] * ?,
- [calc_area(w, b), calc_area(b, w)] * ?,
+ sorted_input.chunk{|_,x|x}.map{|k,v|[k,v.map(&:first)]}.to_h,
+ sorted_input.sort_by.with_index{|(r,_),i|[r,i]}.chunk{|y,_|y}.map{|k,v|[k,v.map(&:last)]}.to_h
+ [calc_area(w, w_xc, w_yc, b, b_xc, b_yc), calc_area(b, b_xc, b_yc, w, w_xc, w_yc)] * ?,
-class TestSaces < Test::Unit::TestCase
+class TestCaces < Test::Unit::TestCase
"1" => ["5,3", "d3d4e3e4d9h7h9j3j4j7j9,f4f6g4g5g6h5h6"],
"2" => ["0,0", "a1,s19"],
"47" => ["25,0", "a1a6b3b4c2c5d2d5e3e4f1f6,l9"],
- expected, actual = data
- assert_equal expected, solve(actual)
+ assert_equal expected, solve(input)