Project euler Ploblem 4 (プロジェクトオイラー4)
備忘のために残しておく。
2023/12/31 コードを修正しました。(コメントありがとうございます)
問題
問題文
回文の数はどちらから読んでも同じである。2つの2桁の数字の積から作られる、最大の回文の数は 9909 = 91 * 99 である。
2つの3桁の数字の積から作られる最大の回文の数を求めよ。
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9909 = 91 * 99.
Find the largest palindrome made from the product of two 3-digit numbers.
答え
906609
解答の方針
3桁どうしを掛けた値は最大で6桁(1000 × 1000 = 1,000,000の7桁)であるから、最大値は6桁とあたりをつける。
300×300=90000なので5桁<6桁、掛け合わせる数を999~300の範囲に限定する。
(きちんとsqrt(99999)を取った方が良いのかもしれないが)
あとは、3桁の数値を999×999,999×998,...,998×999,998×998,...,300×300と掛けていく。
積の前半3桁は1000で割ったときの商で求まり、後半3桁は1000で割ったときの余りで求まる。
後半3桁をリバースして前半3桁と比べ、回文になっているか確認する。
確認後、3桁どうしを掛けた値がより大きければ記録する。これを繰り返して最後に記録されたものが、最大の値。
Pythonのコード
def seek_ans() -> int:
ans = 0
for i in range(999,300,-1):
for j in range(999,300,-1):
if i >= j:
front_num = i * j // 1000
back_num = i * j % 1000
back_num = str(back_num)
r_back_num = back_num[::-1]
r_back_num = int(r_back_num)
if front_num == r_back_num:
if ans < i * j:
ans = i * j
return ans
print(seek_ans())
Juliaのコード
function seek_ans()::Int64
ans::Int64 = 0
for i::Int64 in 999:-1:300
for j::Int64 in 999:-1:300
if i >= j
front_num = i * j ÷ 1000
back_num = i * j % 1000
back_num = string(back_num)
r_back_num = parse(Int, reverse(back_num))
if front_num == r_back_num
if ans < i * j
ans = i * j
end
end
end
end
end
return ans
end
println(seek_ans())
追記
if i <= j については、コメントいただいた通り、順番を工夫すれば不要となる。
前半3桁と後半3桁を分ける必要もなく、全体をひっくり返して、一致すれば回文となる(むしろそちらのほうが、回文の定義に近い)
コードはコメントの通り
def seek_ans() -> int:
ans = 0
for i in range(300,1000):
for j in range(i+1,1000):
num = i * j
if ans < num and num == int(str(num)[::-1]):
ans = num
for k in range(300,1000):
num = k * k
if ans < num and num == int(str(num)[::-1]):
ans = num
return ans
print(seek_ans())