数学パズル
Python勉強中のK君数学パズル
を持ってきて、これやってみる。と言い出した。
どんな問題かというと10進数、2進数、8進数のいずれでも回文数(12321のような数)で10以上で最小の値を求めるというもの。
皆さんも突っ込みどころ見つけて見てください。
D = list()
E = list()
F = list()
def checker(num):
a = str(num)
b = list(reversed(a))
c = len(b)
for j in range(c//2):
if b[j] != b[-j-1]:
return None
return num
for i in range(10,1000):
d = checker(i)
if d != None:
D.append(d)
for i in D:
e = checker(str(oct(i))[2:])
if e != None:
E.append(int(e,8))
for i in E:
f = checker(str(bin(i))[2:])
if f != None:
F.append(int(f,2))
print(F)
正解も求まっているのでGood Jobです。
1パスではなくて、まず1000までの10進数の回文数を調べて、見つかった回文数に対して、8進数、2進数でどうかチェックしていく方式。
いろいろ思考錯誤して、付けたししながら作ったんだろうなぁ。
K君のリファクタリングバージョン
でも1パスでできる事に気づいたK君直してきました。
number = 10
result_list = []
def checker(num):
a = list(reversed(str(num)))
for j in range(len(a)//2):
if a[j] != a[-j-1]:
return None
return num
while True:
if checker(number) != None and checker(str(oct(number))[2:]) != None and checker(str(bin(number))[2:]) != None:
result_list.append(number)
print(number)
break
else:
number += 1
これはかなり素直な流れ
料理開始
2進数、8進数の文字列に直す方法はいろいろあり、K君の方法でも問題ないと思いますが、"{:o}".format(number)
こんな方法に変えてみました。
ここは、どちらの方法がよいというレベルではないと思います。
一番、不思議なのは、checker関数の戻り値。単純に回文数かどうかを調べるという関数だとしたら、True/Falseを返せばいいと思うんだけどねぇ。
回文かしらべるのに、逆順にした文字を求めようとた名残のreversed(str(num))
結果的には、これいらないんじゃない?
その当たりをザックリ直してみました。
def checker(num_str):
for j in range(len(num_str)//2):
if num_str[j] != num_str[-j-1]:
return False
return True
number = 10
while True:
if (checker(str(number)) and
checker( "{:o}".format(number)) and
checker( "{:b}".format(number))) :
print(number)
break
number += 1
コメントいただいたプログラムがもっとシンプルでわかりやすかったので、追加します
from itertools import count
def is_palindrome(text):
return text == text[::-1]
for number in count(10):
if (is_palindrome(f"{number}")
and is_palindrome(f"{number:o}")
and is_palindrome(f"{number:b}")):
print(number)
break