Pythonで解く数学パズル

「プログラマ脳を鍛える数学パズル」をPythonで解きます。

10進数で回文:「プログラマ脳を鍛える数学パズル」Q01の答え

問題

10進数、2進数、8進数のいずれで表現しても回文数となる数のうち、 10進数の10以上で最小の値を求めてください。
回文数は逆から数字を読んでも同じ数になる数のことです。

元ネタ:
第4回「今週のアルゴリズム:10進数で回文」正解者発表|CodeIQ MAGAZINE

わたしの考え方

  • 回文を判定する関数を作る
  • 数値を文字列に変換>逆転し、元の文字列と等しいか判定する
  • 2進数、8進数への変換は組み込み関数bin(x), oct(x)を利用
  • 2進数、8進数はそれぞれアタマに0b, 0がつくのでそれらは取り除いて回文を判定しなければならない
  • 10以上で最小の答えをみつけるのは、変数iを用意して、i =10から初めてi += 1で一つずつ増やして行けばいいかと最初は思ったけど、うまく書けなかったのでrange(10, 1000)として答えを得た。

わたしのオリジナル解答

def ispalindrome(x):
    Dec_x = str(x)
    Bin_x = str(bin(x))[2:]
    Oct_x = str(oct(x))[1:]
    return Dec_x == Dec_x[::-1] and Bin_x == Bin_x[::-1] and Oct_x == Oct_x[::-1]

for i in range(10, 1000):
    if ispalindrome(i):
        print i

Ruby模範解答のミソ

  • Rubyには.reverseという文字列を反転するメソッドがあるのでそれを利用している。
  • 2進数で考えた時回文になる整数は必ず奇数なので、11から始めて奇数のみを検索する。
  • While True構文を使い、正解が見つかったらbreakする。

修正されたわたしの解答

def ispalindrome(x):
    return str(x) == str(x)[::-1]

i =11
while True:
    if ispalindrome(i) and ispalindrome(format(i,'b')) and ispalindrome(format(i, 'o')):
        break
    i += 2
print(i)

気づき・反省点

  • 後から気付いたが、2進数・8進数への変換にformat文を使うと'0b'や'0'が頭につかないので処理が簡単になった。
  • Pythonでの反転処理は数値を一旦文字列に変換しなければならない。
  • 最初の解答は「最小の解答をみつける」のではなく、「10から1000の間で合致する答えをみつける」だったので、問題の本意に沿うものではなかった。
  • 奇数だけを検索することで処理が速くなるのだろう。
  • While True構文を使うことは気付かなかった。

参考にしたサイト

文字列を逆順にする - ひきメモ
文字列の操作 - ひきメモ
Pythonで2進数変換と文字列の扱い - 月からの使い