LoginSignup
0
0

More than 3 years have passed since last update.

Project Euler 011を解いてみる。「格子内の最大の積」

Last updated at Posted at 2019-09-10

Project Euler 011

011

下の 20×20 の格子のうち, 斜めに並んだ4つの数字が赤くマークされている.
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
それらの数字の積は 26 × 63 × 78 × 14 = 1788696 となる.
上の 20×20 の格子のうち, 上下左右斜めのいずれかの方向で連続する4つの数字の積のうち最大のものはいくつか?

->次の問題

考え方

格子上の配列を1次元配列と考え、インデックスを割り振ると

[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99...]

この中から起点となる1箇所を選び、そこから右・下・右下・左下方向の配列を取得するとします。
例:起点=[3]
fig.png
このとき、右、下、右下、左下の列のインデックスは

右:[3,4,5,6] = 起点から+1ずつ
下:[3,23,43,63] = 起点から+20ずつ
右下:[3,24,45,66] = 起点から+21ずつ
左下:[3,22,41,60] = 起点から+19ずつ
となります。
配列の一部を取得する際には、arr[開始:終了:ステップ]とすることで開始インデックスから終了インデックスの1つ手前まで、ステップ数ごとに要素を選択した配列を得ることができます。(listでもnumpy.ndarrayでも可)

#例
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
arr[1:9:2]
#->[1, 3, 5, 7] index[1]から始まり2ずつ進み、index[8]までで終わる

これを利用して、起点iからそれぞれの方向の配列を以下のように取得できます。

arr[i:i + 4]      #右
arr[i:i + 80:20]  #下
arr[i:i + 84:21]  #右下
arr[i:i + 76:19]  #左下

コード

euler011.py
import numpy as np


def main():
    numbers_grid = """\
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48"""
    numbers_grid = numbers_grid.replace('\n', ' ')  # 改行コードをスペースに置換
    numbers_arr = np.array([int(num) for num in numbers_grid.split(' ')])  # スペース区切りで1次元配列に変換
    ans = 0 #答え用の変数
    for i in range(400): # 実際にはi=396までしか必要ではない([89,19,67,48]が最後)
        # 右方向, 右に3つ以上要素がある場合 = i%20 < 17
        if i % 20 < 17:
            product = np.prod(numbers_arr[i:i + 4])
            if ans < product:
                ans = product
        # 下方向, 下に3つ以上要素がある場合 = i < 17*20
        if i < 17 * 20:
            product = np.prod(numbers_arr[i:i + 80:20])
            if ans < product:
                ans = product
            # 右下方向, 下と右にそれぞれ3つ以上要素がある場合
            if i % 20 < 17:
                product = np.prod(numbers_arr[i:i + 84:21])
                if ans < product:
                    ans = product
            # 左下方向, 下と左に3つ以上要素がある場合
            if i % 20 > 2:
                product = np.prod(numbers_arr[i:i + 76:19])
                if ans < product:
                    ans = product
    print(ans)


if __name__ == '__main__':
    main()

結果
70600674
main処理時間: 0.0072519779205322266 sec.

venv環境が壊れて入れ直してたので投稿が遅くなってしまいました。個人的に1日1問投稿目標。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0