86問目
http://projecteuler.net/index.php?section=problems&id=86
6 × 5 × 3 の部屋を隅から反対の隅まで壁伝いに移動するとき、最短距離は 10 で整数となる。m × m × m 以下の大きさの部屋について、最短距離が整数となる部屋の数を考えると、M=100 のとき 2060 となり、初めて 2000 を超える。
この数が初めて百万を超えるのは M がいくつのときか求める。
ピタゴラス数(a, b, c)を生成して、条件(a ≦ m, b ≦ 2a)を満たすものを抽出していきます。
import Data.List main = print euler086 euler086 :: Integer euler086 = fst $ head $ dropWhile ((< 1000000) . snd) $ zip sizes paths where ts = rightAngles 10000 sizes = map (fst . head) ts paths = scanl1 (+) $ map (sum . map integerPath) ts integerPath :: (Integer, Integer) -> Integer integerPath (a, b) = (div b 2) + (min (a-b+1) 0) rightAngles :: Integer -> [[(Integer, Integer)]] rightAngles m = groupBy (\ a b -> fst a == fst b) $ sort $ concat $ map (\ (a, b) -> [ (a*n, b*n) | n <- [1..(div m a)] ]) $ filter (\ (a, b) -> a <= m && b <= 2*a) $ concat [ [(x^2-y^2, 2*x*y), (2*x*y, x^2-y^2)] | x <- [1..m], y <- [1..min (div m x) (x-1)], gcd x y == 1, mod x 2 /= mod y 2]