Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ProjectEuler.netを少しだけ遊んでみた / debut ProjectEuler
Search
tobi00604
November 28, 2023
0
6
ProjectEuler.netを少しだけ遊んでみた / debut ProjectEuler
tobi00604
November 28, 2023
Tweet
Share
More Decks by tobi00604
See All by tobi00604
「PG0」触ってみた / debut PG0
tobi00604
0
10
MicrosoftのAI製品がCopilotに改名した件 / microsoft copilot brand
tobi00604
0
5
砂糖には防腐効果がある / preservative effect of sugar
tobi00604
0
19
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
788
250k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.8k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Code Review Best Practice
trishagee
64
17k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
Intergalactic Javascript Robots from Outer Space
tanoku
268
27k
YesSQL, Process and Tooling at Scale
rocio
168
14k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.3k
Writing Fast Ruby
sferik
627
61k
Optimising Largest Contentful Paint
csswizardry
33
2.9k
Transcript
ProjectEuler.net を少しだけ遊んでみた これ、面白いです 2023/11/28
ProjectEuler.net とは • プロジェクト オイラー ドットネット と読む • https://projecteuler.net/archives •
算数や数学のクイズ問題集サイト • ただし手計算で解くのはほぼ不可能な問題ばかり • そこで問題を解くためのプログラムを作ることになる • 問題の答えさえ求まれば良いので、使う言語やツールは自由
ProjectEuler.net とは • 週に1問のペースで新しい問題が追加されている • 2023/11/28 現在、問題数は865問 • 2023/12/03 に第866問が追加される予定のようだ
• すべて無料 • すべて英語 • とはいえググれば日本語解説サイトとかも見つかる
会員登録してみる • ページ上部のメニューから Registerをクリック • 必要事項を入力 • 超簡単 • メールアドレス不要
• 本人確認も不要
問題一覧を見てみる • ページ上部にメニューがある • Recent ⇒最近追加されたばかりの問題10問 • どれも難しめ • Archives
⇒Recent以外の問題すべて • まずはArchivesの第1問からチャレンジしてみるのがよさそう
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 にしてみました…
Problem 11 問題概要 • 右図のような 20マス x 20マス =400個の数が 与えられる
Problem 11 問題概要 • この中から、並んでいる4マスを選んで 積を計算(掛け算)することを考える • 並ぶ方向はタテorヨコorナナメ • 例えば右図の赤い字の4つの場合、
26 * 63 * 78 * 14 = 1788696 • 問題:作れる積のうち最大のものを求めよ
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]
Problem 11 発想 • 答えを全探索する • 4方向(下・右・右下・右上)だけ見れば良い • 例えば左方向は、別のマスから見た右方向と結果がダブるので無駄 •
f[i][j]から4方向見る処理を、全てのiとjについて試せば良い for(int i = 0; i < 20; i++) { for(int j = 0; j < 20; j++) { 下方向と右方向と右下方向と右上方向をチェック; } }
Problem 11 考察 • 二次元配列は f[20][20] ではなく f[26][23] でやる •
4マス見るときの配列外参照を防ぐ • そもそも二次元配列をどう作るか • 400個の “文字列” が半角スペースで区切られて与えられる • ⇒String.split() で区切る • ⇒Integer.parseInt() で数値に変換する • あとは int[][] 型の二次元配列に詰めていく
None
Problem 11 提出 • このプログラムを動かして出力された答えを提出 • ソースコード自体を提出するわけではない • 正解でした
Problem 28 問題概要 • 中央の1から順に時計回りの渦巻き状に数字を並べていき 正方形を作ることを考える
Problem 28 問題概要 • このとき対角線上に位置する数字 (右図の赤い数字)の合計は 1+3+5+7+9+13+17+21+25=101 • 問題:これを5x5の正方形ではなく 1001x1001の正方形でやったら
合計はいくつになるか?
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 増加するから!
Problem 28 考察 • ゴールマスの数字は? • 5x5の正方形では 25(=5^2) だった •
1001x1001の正方形では 1002001(=1001^2) になる • 「4個進むたびに、増加量が +2」のルールに従って、 1002001に到達するまで加算していけば良い • 加算していく値は2000個程度なのでそんなに重い処理でもない
None
Problem 28 提出 • 正解でした
Problem 39 問題概要 • 周の長さが p であるような直角三角形を作る、 ただし3辺の長さはいずれも整数とする • つまり小数とかはダメ
• 例えば p=12 のとき、作れる直角三角形は 3辺の長さが {3, 4, 5} の1種類だけ 3 4 5
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
Problem 39 発想 • 直角三角形を作れる3辺セットをピタゴラス数という • 例えば {3, 4, 5},
{30, 40, 50} • ピタゴラス数のうち、3つが互いに素であるものを 原始ピタゴラス数という • 例えば {3, 4, 5} • 「互いに素」とは何か、についてはここでは説明しません…
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) を漏れなく生成すればよさそう
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), … の直角三角形も作れるはず
None
Problem 39 提出 • 正解でした
感想 • 正解するともちろん嬉しいが、解く過程も面白い! • Problem 28 の「4個進むたびに、増加量が +2」のような ロジックを組み立てる手がかりを発見できるとテンションUP •
新たな知識が得られ、思考力と実装力が鍛えられる! • Problem 39 で使った「ピタゴラス数」や「ユークリッド式」は 今までまったく知らなかったが、おかげで理解が深まった • 問題ごとに方針を立てて、コードという形にする訓練になる
感想 • サイトのUIがシンプルで使いやすい! • アカウント登録も簡単だし、各ページも見やすい • 「プログラミングで数学を解く」が気軽にできる! • そういうのが好きな人はハマるはず •
作りたいものがないプログラマーにはうってつけのサービス • ただ、数学や英語が苦痛な人にはオススメできないかも
ほかにも機能は豊富 • まだ私がよく知らないProjectEulerの機能(一例) • フレンド機能 • フレンド登録したユーザの進捗が分かるのだろうか? • スレッド機能 •
正解済みの問題は、掲示板で他ユーザの意見を閲覧できるっぽい? • 統計機能 • いろいろユーザに関する情報が見れるっぽい?
終わりに • 問題の解き方は人それぞれ • 当スライドで紹介した解法・コードは あくまで一例で、最高効率ではない • 読者の皆様もぜひ! 以上 レオンハルト・オイラー
(1707-1783)