どう書く

オフラインリアルタイムどう書くE15の回答

ギャスケット上の位置に変換した後、上下左右の位置を数字に戻しています。
1時間ほどかかりました。

e15.rb
def get_bitarray(num, div)
  ret = num.divmod(div)
  while ret[0] >= div
    ret = ret[0].divmod(div) + ret[1..-1]
  end
  ret.reverse
end

def pos_to_num(pos)
  bitx = get_bitarray(pos[0], 2)
  bity = get_bitarray(pos[1], 2)
  length = [bitx.length, bity.length,].max
  sum = (0...length).inject(0) { |sum, i|
    return [ false, ] if bitx[i] == 1 and bity[i] == 1
    next sum + 3**i if bitx[i] == 1
    next sum + 3**i*2 if bity[i] == 1
    sum
  }
  [ true, sum, ]
end

def solve( input )
  bit = get_bitarray(input.to_i, 3)
  posx = 0
  posy = 0
  bit.each_with_index { |n, i|
    case n
    when 1; posx += 2**i
    when 2; posy += 2**i
    end
  }
  [
   [ posx-1, posy, ],
   [ posx+1, posy, ],
   [ posx, posy-1, ],
   [ posx, posy+1, ],
  ].each_with_object([]) { |check, obj|
    next if check[0] < 0 or check[1] < 0
    is_num, num = pos_to_num(check)
    obj << num if is_num
  }.sort.join(',')
end

def test( input, expected )
  actual = solve( input )
  if expected != actual
    puts 'NG: input = %s, expected = %s, actual = %s' % [ input, expected, actual, ]
    exit(1)
  else
    puts 'OK: input = %s, actual = %s' % [ input, actual, ]
  end
end

test( "21", "19,22,23" )
test( "0", "1,2" )
test( "1", "0,3" )
test( "2", "0,6" )
test( "3", "1,4,5" )
test( "4", "3,9" )
test( "9", "4,10,11" )
test( "15", "11,16,17" )
test( "27", "13,28,29" )
test( "32", "30" )
test( "47", "45,51" )
test( "65", "63,69" )
test( "80", "78,162" )
test( "199", "198,201" )
test( "204", "200,205,206" )
test( "243", "121,244,245" )
test( "493", "492" )
test( "508", "507" )
test( "728", "726,1458" )
test( "793", "792,795" )
test( "902", "900,906" )
test( "981", "976,982,983" )
test( "1093", "1092,2187" )
test( "1202", "1200" )
test( "1300", "1299,1305" )
test( "1962", "1952,1963,1964" )
test( "2188", "2187,2190" )
test( "2405", "2403,2409" )
test( "3326", "3324" )
test( "6561", "3280,6562,6563" )
test( "6612", "6608,6613,6614" )
test( "7058", "7056,7062" )
test( "8444", "8442,8448" )
test( "9841", "9840,19683" )
test( "15243", "15239,15244,15245" )
test( "19946", "19944,19950" )
test( "21148", "21147" )
test( "39365", "39363" )
test( "39366", "19682,39367,39368" )
test( "55694", "55692,55698" )
test( "57245", "57243" )
test( "66430", "66429,66432" )
test( "92740", "92739" )
test( "115250", "115248" )
test( "163031", "163029" )
test( "221143", "221142,221157" )
test( "410353", "410352" )
test( "412649", "412647,412659" )
test( "550391", "550389" )
test( "699921", "699880,699922,699923" )
test( "797161", "797160,1594323" )
test( "1000000", "999999,1000002" )