Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ProjectEuler.netを少しだけ遊んでみた / debut ProjectEuler

tobi00604
November 28, 2023
6

ProjectEuler.netを少しだけ遊んでみた / debut ProjectEuler

tobi00604

November 28, 2023
Tweet

Transcript

  1. ProjectEuler.net とは • プロジェクト オイラー ドットネット と読む • https://projecteuler.net/archives •

    算数や数学のクイズ問題集サイト • ただし手計算で解くのはほぼ不可能な問題ばかり • そこで問題を解くためのプログラムを作ることになる • 問題の答えさえ求まれば良いので、使う言語やツールは自由
  2. 問題一覧を見てみる • ページ上部にメニューがある • Recent ⇒最近追加されたばかりの問題10問 • どれも難しめ • Archives

    ⇒Recent以外の問題すべて • まずはArchivesの第1問からチャレンジしてみるのがよさそう
  3. 3問だけ解いてみる • 下記の3問だけやってみました • Problem 11 Largest Product in a

    Grid • Problem 28 Number Spiral Diagonals • Problem 39 Integer Right Triangles • 今日(当スライド作成日)が 2023/11/28 なので 日付にちなんで、11と、28と、あと 11+28=39 にしてみました…
  4. Problem 11 発想 • 400個の数字を二次元配列で持つ • 「上からi行目、左からj列目」の数を f[i][j] に格納 •

    f[i][j], その隣, その隣, その隣 の積は以下のように計算可能 • 下方向 ⇒ f[i+0][j+0] * f[i+1][j+0] * f[i+2][j+0] * f[i+3][j+0] • 右方向 ⇒ f[i+0][j+0] * f[i+0][j+1] * f[i+0][j+2] * f[i+0][j+3] • 右下方向 ⇒ f[i+0][j+0] * f[i+1][j+1] * f[i+2][j+2] * f[i+3][j+3] • 右上方向 ⇒ f[i+0][j+0] * f[i-1][j+1] * f[i-2][j+2] * f[i-3][j+3]
  5. Problem 11 発想 • 答えを全探索する • 4方向(下・右・右下・右上)だけ見れば良い • 例えば左方向は、別のマスから見た右方向と結果がダブるので無駄 •

    f[i][j]から4方向見る処理を、全てのiとjについて試せば良い for(int i = 0; i < 20; i++) { for(int j = 0; j < 20; j++) { 下方向と右方向と右下方向と右上方向をチェック; } }
  6. Problem 11 考察 • 二次元配列は f[20][20] ではなく f[26][23] でやる •

    4マス見るときの配列外参照を防ぐ • そもそも二次元配列をどう作るか • 400個の “文字列” が半角スペースで区切られて与えられる • ⇒String.split() で区切る • ⇒Integer.parseInt() で数値に変換する • あとは int[][] 型の二次元配列に詰めていく
  7. Problem 28 発想 • 1+3+5+7+9+13+17+21+25+31+37+43+49+ … • 1, 3, 5,

    7, 9 の部分は2ずつ増加している • 9, 13, 17, 21, 25 の部分は4ずつ増加している • 25, 31, 37, 43, 49 の部分は6ずつ増加している • つまり「4個進むたびに、増加量が +2」されている • なぜ4個進むたび? ⇒正方形は辺が4本あるから! • なぜ増加量 +2 ? ⇒渦巻き1周ごとに辺の長さは 2 増加するから!
  8. Problem 28 考察 • ゴールマスの数字は? • 5x5の正方形では 25(=5^2) だった •

    1001x1001の正方形では 1002001(=1001^2) になる • 「4個進むたびに、増加量が +2」のルールに従って、 1002001に到達するまで加算していけば良い • 加算していく値は2000個程度なのでそんなに重い処理でもない
  9. Problem 39 問題概要 • 例えば p=120 のとき、 {20, 48, 52},

    {24, 45, 51}, {30, 40, 50} の 3種類を作れる • 問題:最もたくさんの種類の 直角三角形を作れるのは、 p がいくつのとき? (ただし p は1000以下とする) 40 20 48 52 24 45 51 30 50
  10. Problem 39 発想 • 直角三角形を作れる3辺セットをピタゴラス数という • 例えば {3, 4, 5},

    {30, 40, 50} • ピタゴラス数のうち、3つが互いに素であるものを 原始ピタゴラス数という • 例えば {3, 4, 5} • 「互いに素」とは何か、についてはここでは説明しません…
  11. Problem 39 発想 • また、ユークリッド式というテクニックがある • 2つの自然数 m, n が

    「m>n」かつ「互いに素」かつ「偶奇が異なる」だと、 {m*m-n*n, 2*m*n, m*m+n*n} は原始ピタゴラス数になるというもの • (m*m-n*n)+2*m*n+(m*m+n*n) = 2*m*(m+n) が周の長さとなる • 結局今回の問題では、上記の m, n のペアを全探索して、 周の長さ 2*m*(m+n) を漏れなく生成すればよさそう
  12. Problem 39 考察 • 今回の問題は、周の長さ p は1000以下という制約付き • 2*m*(m+n) が1000以下ということは、mが23以上だとオーバー

    • mは1から22まで調べれば網羅できそう • 2*m*(m+n) をひとつ生成したら、その相似も忘れずに! • 2*m*(m+n) の直角三角形が作れるならば、 それの整数倍、つまり 4*m*(m+n), 6*m*(m+n), … の直角三角形も作れるはず
  13. 感想 • 正解するともちろん嬉しいが、解く過程も面白い! • Problem 28 の「4個進むたびに、増加量が +2」のような ロジックを組み立てる手がかりを発見できるとテンションUP •

    新たな知識が得られ、思考力と実装力が鍛えられる! • Problem 39 で使った「ピタゴラス数」や「ユークリッド式」は 今までまったく知らなかったが、おかげで理解が深まった • 問題ごとに方針を立てて、コードという形にする訓練になる
  14. ほかにも機能は豊富 • まだ私がよく知らないProjectEulerの機能(一例) • フレンド機能 • フレンド登録したユーザの進捗が分かるのだろうか? • スレッド機能 •

    正解済みの問題は、掲示板で他ユーザの意見を閲覧できるっぽい? • 統計機能 • いろいろユーザに関する情報が見れるっぽい?