LoginSignup
1
0

More than 3 years have passed since last update.

Project Euler 018, 067を解いてみる。「最大経路の和」

Last updated at Posted at 2019-09-17

Project Euler 018

018

以下の三角形の頂点から下の行の隣接する数字を通って下まで移動するとき, その数値の和の最大値は23になる.


   3
  7 4
 2 4 6
8 5 9 3

この例では 3 + 7 + 4 + 9 = 23.
以下の三角形を頂点から下まで移動するとき, その最大の和を求めよ.

              75
             95 64
            17 47 82
           18 35 87 10
          20 04 82 47 65
         19 01 23 75 03 34
        88 02 77 73 07 63 67
       99 65 04 28 06 16 70 92
      41 41 26 56 83 40 80 70 33
     41 48 72 33 47 32 37 16 94 29
    53 71 44 65 25 43 91 52 97 51 14
   70 11 33 28 77 73 17 78 39 68 17 57
  91 71 52 38 17 14 91 43 58 50 27 29 48
 63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23

Problem 67 は同じ問題だが100行ある

->次の問題
018と067は問題のサイズが異なるだけでアルゴリズムは同一なので一緒に解きます。
関数は018でも067でも解けるようにし、018の数列もテキストファイルから読み込むようにしました。

考え方

一番下とその上の段をまず考えてみます。
左端は


 63
04 62

となっていますが、合計が大きなルートを考えるのであれば必然的に62を選ぶことになります。
必ず62が選ばれるということは上段の63は実質63+62=125と考えることができます。
その他の数字も同様に、下段の数字の大きい方を選び上段に加算していくと

125 164 102 95 112 123 165 128 166 109 122 147 100 54

となります。ここからまた2個並んだ数字の大きい方を選んで一つ上の列に加算を繰り返していくことで、最上段に到達したときに最大の和を求めることができます。
処理としては、
上からn段目(n個の数値)で、端からi番目とi+1番目を比較し大きい方を選択する
→これをn-1回行う
→n-1個の数列ができる(n-1段目と同じ)
→n-1段目の数列にそれぞれ加算
これを繰り返していきます。

コード

euler018.py
import numpy as np


def main018():
    file = 'p018_triangle.txt'
    print(solve_triangle_problem(file))


def main067():
    file = 'p067_triangle.txt'
    print(solve_triangle_problem(file))


def solve_triangle_problem(file: str):
    """load_triangleでロードした三角形から最大となる和を返す
    1つ下の段の2つから大きい方を上段に加算、
    これを繰り返すことで最大の和を返す
    Args:
        file: 問題の三角形を記載したtxt file
    Returns:
        int: 最大となる和
    """
    triangle_arr_list = load_triangle(file)  # 数列をtxt fileからload
    best_sum_list = [0] * triangle_arr_list[0].size  # 最大値を入れる配列を初期化
    for arr in triangle_arr_list:
        arr += best_sum_list  # 上段の数列に下段の数列の中から大きい方を加算
        # 加算した配列(n個)から大きい方を選んだ配列(n-1個)をbest_sum_arrとする
        best_sum_list = [arr[i] if arr[i] > arr[i + 1] else arr[i + 1] for i in range(len(arr) - 1)]
    return triangle_arr_list[-1][0]  # 最上段の数値を返す


def load_triangle(filepath: str) -> list:
    """txt fileから問題の三角形をロードする関数
    Args:
        filepath: file path
    Returns:
        list: int型の2次元配列、各段を格納
    """
    triangle_list = []
    with open(filepath) as file:
        for txt in file.readlines():
            txt = txt.strip()
            txt = txt.split(' ')
            txt = np.array([int(t) for t in txt], dtype=int)
            triangle_list.insert(0, txt)

    return triangle_list


if __name__ == '__main__':
    main018()
    main067()

Mac book proにて実行
結果
1074
main018処理時間: 0.0005071163177490234 sec.
7273
main067処理時間: 0.0067751407623291016 sec.

1
0
0

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
1
0