のてすきあ − 完全独習非プログラマー −

Haskell で Project Euler を解く素人遊び

Problem 20

100! の各桁を数の合計を求める またしても僕らのIntegerの恩恵を受ける問題である。むしろそのために全く面白みのない問題となってしまったと言えるだろう。唯一のトピックスは、Data.Char.digitToIntの出番ということだろうか。 秒殺☆

Problem 19

20世紀(1901.1.1 - 2000.12.31)において、1日が日曜日となる月は何回あるか うるう年は4年に1回と思いがちだが、実際は400年に99回という壮大かつ半端な周期である。僕達はミレニアムのうるう年を過ごしたが、実は400年に1度の貴重な「400で割れる年」だっ…

Problem 18

頂点から下へ降りていく中で通った数の和が最大となるときの和はいくつか。 自画自賛も甚だしいが、自分でもよくこの解法を思いついたというくらい、解けて嬉しかった問題。元々はいかに上手にデータ構造を作れば効率よくルート検索できるだろうか…と考えて…

Problem 16

21000の各桁の和を求める。 例) 215 = 32768 → 3+2+7+6+8 = 26 21000ともなるとかなり巨大な数になることが予想されるが、全く問題ない。だって僕達にはIntegerがあるんだから。 数字を桁ごとに分ける操作 breakToDigits がちょっとした小技かも知れない。…

Problem 15

20☓20の格子を左上から右下まで辿る経路の総数を求める 高校で数学を習った日本人なら秒殺の問題がたまに出るのもProject Euler。階乗の計算も教科書通り。こういう時、Integerで何も考えずに巨大な数を扱えるHaskellは大変心強い。 これは簡単☆

Problem 14

100万までの数の中で、最も長いコラッツ列を生成する数を求める コラッツ列: cn が偶数なら cn+1 = cn/2, 奇数ならcn+1 = 3*cn+1 ... と続く数列 まずは素直に書いてみる。 これで答えは出る。ただし時間が掛かる。私のデスクトップで、答えが出るまで3分ち…

Re:Problem 11

下の20☓20の数字列からタテ・ヨコ・ナナメいずれかに4つ並んだ数字の積を取ったときの最大値を求める。 2020/04/11追記: なんとData.Listに標準でtranspose関数があることが判明。しかもそちらの方が優秀で、それを使えばナナメ成分を拾うのが格段に簡単にな…

Problem 13

以下の50桁の数を100個足した答えのはじめの10桁を求める (50桁の数:省略) …? なんの工夫もいらない。唯一の注意点は "Use Integer!" である。 あとは、10桁を取る際に、Stringにしてtake10する方法と、Integer のままで10桁になるまで10で割り続ける方…

Problem 12

三角数列で約数の数が500を超える最初の数を求める まず思いつく方針は、与えられた数nに対して約数のリストを返す関数fを作り、それを三角数列のリストに対してmap (length.f)してやるというもの。ただしこれは時間が掛かる。ハッキリ言って一晩計算を回し…

Problem 11

下の20☓20の数字列からタテ・ヨコ・ナナメいずれかに4つ並んだ数字の積を取ったときの最大値を求める。 2020/04/11追記: なんとData.Listに標準でtranspose関数があることが判明。しかもそちらの方が優秀で、それを使えばナナメ成分を拾うのが格段に簡単にな…

Problem 10

2,000,000以下の全ての素数の和を求める 素数列の生成は problem 7 で用いたものを使う。 mitstream.hatenablog.jp あとは足すだけ…だよね?すごく時間が掛かるんですけど、原理的に高速化する方法がないように思えます。何かあるんでしょうか?どこかに無駄…

Problem 9

a < b < c a2 + b2 = c2 a + b + c = 1000 を満たす唯一の整数の組 (a,b,c) を見つけ、その積 abc を求める これはリスト内包表記のもとにズバッと一刀両断で終了。 ズバッ…っと ズバッ…と? 計算が終わらない。落ち着いて考えたらこれだとO(n3)あるのではな…

Problem 8

次の1000個の数字の中からひと続きの13個の数字の積を取る。積の最大値はいくらか。 非プログラマーの自分としては、 IO アクションにはどうも苦手意識がある。do構文も苦手である。だからこの問題は1000桁の数字をコピペして最初から[Int]型として扱うこと…

Problem 7

10001番目の素数を求める まずは伝統的なアレを使ってまっすぐやってみる。当然これで解決するが、思いの外計算が重い。素数列の生成に関しては速いパッケージが存在するので、それを使えばいいじゃないかという(内なる)声もあるが、人のふんどしでパズル…

Problem 6

100までの数の”2乗の総和”と”総和の2乗”の差を求める これはなんのヒネリもない問題。ごくごく素直に2乗の総和と総和の2乗を求めるだけ。計算量を削る工夫も不要。関数sumに感謝しながらパチパチとコードを書きましょう。 foldl を使ったり、ポイントフ…

Problem 5

1から20までのすべての数で割り切れる最小の数を求める Project Euler たまにこういうプログラミング不要の問題が出る。 一応方針らしきものを述べると、pn (pは素数、nは自然数)が20以下となるべきを全て掛けあわせれば良い。数が大きい場合はプログラム…

Problem 4

3桁の数同士の積で得られる最大の回分数を求める まずはリストが回分かどうかは判定するisPalindromeを準備する。これは鉄板。一応補足しておくと、こいつの型は[a] -> Bool でリストを引数に取る。1つの数(型で言うとInt)を評価することはできない。よっ…

Problem 3

大きな数の最大素因数を求める 最初に浮かんだ方針は、 1. 素数のリストを生成 2. filter と使って「大きな数」の素因数を抽出 3. その中で最大のものを拾う シンプルに行けると嬉しかったが、実際やってみると計算量が多すぎて一向に答えが出てこない。もう…

Problem 2

4,000,000を超えない偶数のフィボナッチ数の総和 まず"four million"っていくつだっけ?というところで間違いそうなので、最初に確認。フィボナッチ数列は泥臭く書き下す方がパッと見分かりやすいが、昔どこかでzipWithを使った小洒落たのを見たことがあった…

Problem 1

1000未満の3または5の倍数を全部足したらいくつになるか? ある条件を満たす自然数の列を相手にするときは、リスト内包表記から入ってみるのが自分の中では自然な流れ。「または」だけ気をつけて、あとは深く考えずにいってみる。 うまくいきました☆