Project Euler – 問題33

49/98は面白い分数である。経験の足りない数学家が間違ったやり方で簡約しよ うとして9を取り除いたとき、49/98=4/8となりこれは正しい。

30/50=3/5のようなものは自明な場合とする。

分子と分母が2桁で値が1より小さい分数で、自明ではないこのタイプの分数が ちょうど4つ存在する。

これらの4つの分数の積が規約分数で与えられたときの分母を求めよ。

Haskellには有理数が用意されているのでこれを用いることにする。import Ratioで使用可能になる。リストの内包表記で対象となる分数のリストを生成し、 productで積を求め、denominatorで分母が求まる。値は自動的に既約分数となる。 分数の値は%で生成できる。

ソースコード的な美しさは全くないが、分子の10の位をa、1の位をb、分母の 10の位をc、1の位をdとして、問題の条件を以下のようなコードにする。2桁の 数なので10の位に0はこない。また自明な場合は対象にならないので1の位も0は 含まない。ある数字を取り除く操作があるので、10の位と1の位は同じ値になら ない。分数の値は1より小さい。自明な場合意外ということで、分数の値をxと したときa==dでb/c=xの場合とb==cでa/d=xの場合がありえる。この条件で生成 された分数を最初に書いた処理をすれば答えが求まる。

euler033 = denominator $ product [(a * 10 + b) % (c * 10 + d)
                                  | a <- [1..9], b <- [1..9],
                                  c <- [1..9], d <- [1..9],
                                  curious a b c d]
    where curious a b c d = a /= b && c /= d && x < 1
                            && ((a == d && b % c == x)
                                || (b == c && a % d == x))
              where x = (a * 10 + b) % (c * 10 + d)