ruskのメモブログ

python勉強記録

Project Euler

Project Euler 36〜40をpythonで解く

投稿日:

Problem 36

問題(英語)

The decimal number, 585 = 10010010012 (binary), is palindromic in both bases.

Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2.

(Please note that the palindromic number, in either base, may not include leading zeros.)

「 https://projecteuler.net/problem=36

問題(日本語)

585 = 10010010012 (2進) は10進でも2進でも回文数である.

100万未満で10進でも2進でも回文数になるような数の総和を求めよ.

(注: 先頭に0を含めて回文にすることは許されない.)

http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2036 」

コード

考え方

2進数はこれが初登場?

今回はformat関数で2進数に変換した。

回文数の判定

Problem4でも出てきた回文数。

この判定にはstrをスライスで反転させて一致するか確認するのが簡潔で良い。

step数を-1にすることで、後ろから1つずつ並べてくれるので反転させることができる。

sum関数 + リスト内包表記

短く簡潔に書ける。

最初は、次のように書いていた。

sum関数とリスト内包表記を使えばワンラインで書ける。

単純なfor,if,totはsum,[](リスト内包表記)で書くように心がけたい。

Problem 37

問題(英語)

The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.

Find the sum of the only eleven primes that are both truncatable from left to right and right to left.

NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.

「 https://projecteuler.net/problem=37

問題(日本語)

3797は面白い性質を持っている. まずそれ自身が素数であり, 左から右に桁を除いたときに全て素数になっている (3797, 797, 97, 7). 同様に右から左に桁を除いたときも全て素数である (3797, 379, 37, 3).

右から切り詰めても左から切り詰めても素数になるような素数は11個しかない. 総和を求めよ.

注: 2, 3, 5, 7を切り詰め可能な素数とは考えない.

「 http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2037

コード

考え方

自作関数isPrime

今回は上限が分からないのでエラトネスのふるいは不適切。

素直に毎回素数判定をする。(少し遅い)

切り詰め可能(truncatable)素数の判定

以下のコードで切り詰めをする。

l_nが左、r_nが右から切り詰めたもの。

iが切り詰める桁数。

やはり、str型+スライスの組み合わせは使いやすい。

切り詰めた数に対して素数判定を行い、一つでも素数でない数が出てきたらFalseとする。

最後まで生き残ったらTrue。

Problem 38

問題(英語)

Take the number 192 and multiply it by each of 1, 2, and 3:

192 × 1 = 192
192 × 2 = 384
192 × 3 = 576

By concatenating each product we get the 1 to 9 pandigital, 192384576. We will call 192384576 the concatenated product of 192 and (1,2,3)

The same can be achieved by starting with 9 and multiplying by 1, 2, 3, 4, and 5, giving the pandigital, 918273645, which is the concatenated product of 9 and (1,2,3,4,5).

What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product of an integer with (1,2, ... , n) where n > 1?

「 https://projecteuler.net/problem=38

問題(日本語)

192 に 1, 2, 3 を掛けてみよう.

192 × 1 = 192
192 × 2 = 384
192 × 3 = 576

積を連結することで1から9の パンデジタル数 192384576 が得られる. 192384576 を 192 と (1,2,3) の連結積と呼ぶ.

同じようにして, 9 を 1,2,3,4,5 と掛け連結することでパンデジタル数 918273645 が得られる. これは 9 と (1,2,3,4,5) との連結積である.

整数と (1,2,...,n) (n > 1) との連結積として得られる9桁のパンデジタル数の中で最大のものはいくつか?

「 http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2038

コード

考え方

num = 192, ls = [1,2,3]

と、それぞれをnum,lsとして説明する。

numの桁数

numの桁数(digit)はlsの長さ(n)で決まる。

結論から言うと、

で求まる。

(//は余りありの割り算の商を求めるもの。9//2 -> 4)

これは確認していけば分かる。

(1,2)の時は、4桁→5桁で合計9桁しかありえない。

(1,2,3)の時は、9//3 = 3 で、3桁→3桁→3桁で合計9桁しかありえない。

以降も同様である。

m桁の数字を生成

digit =m 桁の数字は以下で生成できる。

pandigital_9の判定

これはProblem32で作ったものをほぼそのまま採用。

Project Euler31〜35をpythonで解く

上で判定する。

joinメソッド

listの要素をstr型として一つに結合する時はjoinメソッドが便利。

実行結果:

グローバル変数

自作関数pandigital_9内の変数conc_pro(concatenated_product(連結積))はmain関数でも再び使いたいので、グローバル変数とする。

関数内の変数は本来その関数の中でのみ呼び出し可能だが、グローバル変数はある関数で使ったのち、別の関数でも呼びだすことが出来る。

以下のように書くことでグローバル変数とすることができる。

興味本位で

最大の時の、numとlsを調べてみた。

答えには関係ないが興味本位で知りたい情報を求めるためのコードには、「##」でコメントアウトしている。

Problem 39

問題(英語)

If p is the perimeter of a right angle triangle with integral length sides, {a,b,c}, there are exactly three solutions for p = 120.

{20,48,52}, {24,45,51}, {30,40,50}

For which value of p ≤ 1000, is the number of solutions maximised?

「 https://projecteuler.net/problem=39

問題(日本語)

辺の長さが {a,b,c} と整数の3つ組である直角三角形を考え, その周囲の長さを p とする. p = 120のときには3つの解が存在する:

{20,48,52}, {24,45,51}, {30,40,50}

p ≤ 1000 のとき解の数が最大になる p はいくつか?

「 http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2039

コード

考え方

実行時間が1分ぐらいかかってしまった。

main

和がpになるa,b,c(a<=b<=c)の組み合わせを全て生成して、それらがピタゴラス数か地道に判定していく方法を取った。

他の方のコードでいいと思ったのがこちら。

Project Euler 39「整数の直角三角形」

この方のコードはまずピタゴラス数の組a,b,cを生成してから求めるもので、こちらのアプローチの方が無駄がなくて早い。

itertools

iteartoolsは何かと便利なライブラリ。

色々できるが、直積(デカルト積)、順列、組み合わせなどが特に便利。

今回は「重複組み合わせ」というものを使った。

実行結果:

a=bも考慮する組み合わせを生成する。

itertoolsはその名の通り、イテレータを生成する。

詳しくはこのページなどをご参考なさってください。

Pythonで階乗、順列・組み合わせを計算、生成

Problem 40

問題(英語)

An irrational decimal fraction is created by concatenating the positive integers:

0.123456789101112131415161718192021...

It can be seen that the 12th digit of the fractional part is 1.

If dn represents the nth digit of the fractional part, find the value of the following expression.

d1 × d10 × d100 × d1000 × d10000 × d100000 × d1000000

「 https://projecteuler.net/problem=40

問題(日本語)

正の整数を順に連結して得られる以下の10進の無理数を考える:

0.123456789101112131415161718192021...

小数第12位は1である.

dnで小数第n位の数を表す. d1 × d10 × d100 × d1000 × d10000 × d100000 × d1000000 を求めよ.

「 http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2040

コード

考え方

久々に比較的優しい問題。

logを初めて使った。

上限

小数第100万位までしか必要ないので、整数を100万まで繋げる必要はない。

しかし、そこまで時間のかかる作業でもないし、減らしたとしてもオーダーが1つ下がる程度でモチベを感じなかったので、100万まで整数を繋げることにした。

対数(log)

最後の

を求める時のコードが簡潔にならずに戸惑った。

まず、100万(=TOP)は10^6だから10^0,10^1,...,10^6番目を調べるので、

と書きたいが、この6が何を表すのか分かりにくくなってしまう。

プログラミングのコードで僕が心がけていることの一つが「いきなり意味が分からない定数を出さない」である。

なので、本来の意味の次のコードに書き換えた。

以上!

以上!

 

-Project Euler

Copyright© python勉強記録 , 2026 All Rights Reserved Powered by AFFINGER4.