ruskのメモブログ

python勉強記録

Project Euler

Project Euler26〜30をpythonで解く

更新日:

Problem 26

問題(英語)

A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:

1/2 = 0.5
1/3 = 0.(3)
1/4 = 0.25
1/5 = 0.2
1/6 = 0.1(6)
1/7 = 0.(142857)
1/8 = 0.125
1/9 = 0.(1)
1/10 = 0.1

Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.

Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

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

問題(日本語)

単位分数とは分子が1の分数である. 分母が2から10の単位分数を10進数で表記すると次のようになる.

1/2 = 0.5
1/3 = 0.(3)
1/4 = 0.25
1/5 = 0.2
1/6 = 0.1(6)
1/7 = 0.(142857)
1/8 = 0.125
1/9 = 0.(1)
1/10 = 0.1

0.1(6)は 0.166666... という数字であり, 1桁の循環節を持つ. 1/7 の循環節は6桁ある.

d < 1000 なる 1/d の中で小数部の循環節が最も長くなるような d を求めよ.

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

コード1

コード2

考え方

意外と数学力が必要な問題。

循環の判定

まず、何を持って「循環した」と判断出来るか。

一見、桁に同じ数字が出てきた時に「循環した」と言えそうだが、そうではない。

例えば1/17なんかがその例。

1/17 = 0.(0588235294117647)

1/17は上のように16桁周期になり、同じ数字が出てきても循環しない。

つまり、小数の桁の見た目では判断できない。

余りで判定

ならどうするかというと余り(mod)で判定すれば良い。

d=7の例で考える。

1/7 = 0.(142857)

これは、次のように書ける。

割られる数 = 余り,商(割る数はd=7)

1 = 1,0

10 = 3,1

30 = 2,4

20 = 6,2

60 = 4,8

40 = 5,5

50 = 1,7

10 = 3,1

これは筆算で小数を求めることと同じことをやっている。

注目すべきは右側の商ではなく、左側の余りである。

赤字にしている「3」で初めて余りが一致したので、そこで循環すると分かる。

循環の桁数は一致した余りの距離(間の桁数)で求まる。

循環の桁数の取得

remainder_listに余りを追加していく。

余りが一致した際に、「循環の桁数=一致した余りの距離」が成り立つのだが、これを求めるのが少々厄介だった。

コード1とコード2でそれぞれ別の方法を取っている。

単にindexを取得すると...

一致する要素のindexを調べるにはindexメソッドがあるが、これは一致する「最初の」値のインデックスしか分からない。

実行結果:

my_index_multi

コード1で使った関数。

参考「 Pythonのリストの要素のインデックス(何番目か)を取得

このサイトを参考にして自作関数を書いた。(丸パクリ)

実行結果:

この関数を使えば検索した値と一致する全ての要素のインデックスを取得出来る。

よって、余りの距離は、求めたインデックスの差を計算することで分かる。

インデックスを記録する変数を導入する

この方法を取ったのがコード2。

indexメソッドでは一致する最初の要素のインデックスしか分からなかったので、二つ目の要素のインデックスを求めるための変数を用意すれば良い。

コード2の変数iがそれである。

これは、この方のコードを参考にした。

Project Euler 26「逆数の循環節 その1」

関数を定義するより簡潔でいい感じ。

main関数

このコードからmain関数を書くようにした。

Problem 27

問題(英語)

うまくコピー出来なかった。

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

問題(日本語)

オイラーは以下の二次式を考案している:

n^2 + n + 41.

この式は, n を0から39までの連続する整数としたときに40個の素数を生成する. しかし, n = 40 のとき 402 + 40 + 41 = 40(40 + 1) + 41 となり41で割り切れる. また, n = 41 のときは 412 + 41 + 41 であり明らかに41で割り切れる.

計算機を用いて, 二次式 n^2 - 79n + 1601 という式が発見できた. これは n = 0 から 79 の連続する整数で80個の素数を生成する. 係数の積は, -79 × 1601 で -126479である.

さて, |a| < 1000, |b| ≤ 1000 として以下の二次式を考える (ここで |a| は絶対値): 例えば |11| = 11 |-4| = 4である.

n^2 + an + b

n = 0 から始めて連続する整数で素数を生成したときに最長の長さとなる上の二次式の, 係数 a, b の積を答えよ.

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

コード

考え方

さすがオイラー、面白いこと考えるよなぁ。

関数をうまく定義すればすっきり書ける。

range関数の範囲指定

aとbが負の場合も検討しなくてはならないので、range関数の範囲指定で第一引数にstartの数を指定する。

この範囲指定は便利なので覚えておくべき。

3つ引数を指定すると飛び飛び(step)の値を生成出来る。

実行結果:

問題はよく読もう...

絶対値を問われていると思ってしばらく-をつけ忘れて、うーんと唸っていた。

問題はよく読もう。

Problem 28

問題(英語)

Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:

21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

It can be verified that the sum of the numbers on the diagonals is 101.

What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?

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

問題(日本語)

1から初めて右方向に進み時計回りに数字を増やしていき, 5×5の螺旋が以下のように生成される:

21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13

両対角線上の数字の合計は101であることが確かめられる.

1001×1001の螺旋を同じ方法で生成したとき, 対角線上の数字の和はいくつか?

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

コード

考え方

たくさんの視点がありそうな問題。

僕は対角線の数の差に注目した。

最初は2ずつ増えていき、次に4ずつ増えていっている。

観察すると、+2,+4,+6,+8,... と増えていくことが分かる。

よって、4つごとに足す数(add_num)に2を足していけば良い。

加速度のような考え方である。

「右上の数」=「(1辺の長さ)^2」が成り立っているので、最後の項は1001^2になる。(この値を上限とする。)

Problem 29

問題(英語)

Consider all integer combinations of ab for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:

22=4, 23=8, 24=16, 25=32
32=9, 33=27, 34=81, 35=243
42=16, 43=64, 44=256, 45=1024
52=25, 53=125, 54=625, 55=3125

If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by ab for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?

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

問題(日本語)

2 ≤ a ≤ 5 と 2 ≤ b ≤ 5について, ab を全て考えてみよう:

  • 22=4, 23=8, 24=16, 25=32
  • 32=9, 33=27, 34=81, 35=243
  • 42=16, 43=64, 44=256, 45=1024
  • 52=25, 53=125, 54=625, 55=3125

これらを小さい順に並べ, 同じ数を除いたとすると, 15個の項を得る:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

2 ≤ a ≤ 100, 2 ≤ b ≤ 100 で同じことをしたときいくつの異なる項が存在するか?

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

コード

考え方

「重複しない」というキーワードが出てきた時はセット型が適切である。

この問題でセット型を知る。

1行でも書ける。

リスト内包表記の[ ]を{ }にするとset型の内包表記になるらしい。

参考「 Project Euler 29「個別のべき乗」

Problem 30

問題(英語)

Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits:

1634 = 14 + 64 + 34 + 44
8208 = 84 + 24 + 04 + 84
9474 = 94 + 44 + 74 + 44

As 1 = 14 is not a sum it is not included.

The sum of these numbers is 1634 + 8208 + 9474 = 19316.

Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.

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

問題(日本語)

驚くべきことに, 各桁を4乗した数の和が元の数と一致する数は3つしかない.

1634 = 14 + 64 + 34 + 44
8208 = 84 + 24 + 04 + 84
9474 = 94 + 44 + 74 + 44

ただし, 1=14 は含まないものとする. この数たちの和は 1634 + 8208 + 9474 = 19316 である.

各桁を5乗した数の和が元の数と一致するような数の総和を求めよ.

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

コード

考え方

便利なstr型とmap関数を使って簡潔に書けているいいコード。

上限

最初は上限が分からず、適当に大きな数を入れて答えを出した。

7桁だと、最高、(9^5)*7=413343<10^(7-1)で元の数に届かない。

よって、6桁まで調べればいいので上限は(9^5)*6となる。

参考「 http://tsumuji.cocolog-nifty.com/tsumuji/2009/07/project-euler-6.html

興味本位で

lsに関するコードは答えには関係ないが興味があったので書いた。

思ったより条件に当てはまる数がたくさんあった。

以上!

段々と数学的にも難しくなってきた。

次の記事↓

Project Euler31〜35をpythonで解く

-Project Euler

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