Problem28

30分プログラム、その301。Problem28 via Project Euler

1から初めて右方向に進み時計回りに数字を増やしていき, 5×5の螺旋が以下のように生成される:

21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13

両対角線上の数字の合計は101であることが確かめられる.
1001×1001の螺旋を同じ方法で生成したとき, 対角線上の数字の合計はともにいくつだろうか?

直接解かなくても、じっくり考えたら素敵な方法がありそうだったので考えてみた。

n 一辺の長さ 対角線 公差 初項
1 1 1 ? 1
2 3 3,5,7,9 2 3
3 5 13,17,21,25 4 13
..
n 2n-1 size(n)-1 {size(n-1)}^2+size(n)-1

size(n)はn番目の四角形の一辺の長さ。
表から、n番目の四角形の対角線の初項と公差がわかった。項数は4であるのが自明なので、n番目の対角線の和が簡単にもとまる。あとは、500番目(1001x1001)までの和を求めてやればいい。

使い方

$ ghc --make problem28
[1 of 1] Compiling Main             ( problem28.hs, problem28.o )
Linking problem28 ...

$ time ./problem28
669171001
./problem28  0.01s user 0.02s system 24% cpu 0.115 total

ソースコード

diag size = if size == 1 then
                take 1 xs
            else
                take 4 xs
    where
      xs = [a,a+k..]
      k = size - 1
      prev = size - 2
      a = prev * prev + k

solve = let xs = [1,3..1001]
        in
          sum $ concat $ map diag xs

main = print solve