Project Euler 11

http://projecteuler.net/index.php?section=problems&id=11


行列をリストのリストで表してもいいですが、インデックスでランダムアクセスしやすい2次元配列を使いましょう。(リストなら線形時間かかる)
2次元配列はリストのリストがあれば簡単に作れます。

let a = array2D [ for i in 0..2 -> [ for j in 0..3 -> i + j ] ]

インデックスによるアクセスは、

printfn "%d" a.[1,2]    // 3
let ss = [
   "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08";
   "49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00";
   ...
   "01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48";
]

let product a = List.fold (fun x y -> x * y) 1 a

let rec split str r k =
   if k = String.length str then [r]
   else if str.[k] = ' ' then [r] @ (split str "" (k + 1))
   else split str (r + str.[k..k]) (k + 1)

let matrix sss = array2D [ for ss in sss -> [ for s in ss -> int s ] ]

let length = 4
let size = List.length ss
let m = matrix [ for s in ss -> split s "" 0 ]
let max_r =
      List.max [ for y in 0..size-1 do
                  for x in 0..size-length
                  -> product [ for i in 0..length-1 -> m.[y,x+i] ] ]
let max_d =
      List.max [ for x in 0..size-1 do
                  for y in 0..size-length
                  -> product [ for i in 0..length-1 -> m.[y+i,x] ] ]
let max_rd1 =
      List.max [ for p in 0..size-length do
                  for q in 0..size-p-length
                  -> product [ for i in 0..length-1 -> m.[q+i,p+q+i] ] ]
let max_rd2 =
      List.max [ for p in 1..size-length do
                  for q in 0..size-p-length
                  -> product [ for i in 0..length-1 -> m.[p+q+i,q+i] ] ]
let max_ru1 =
      List.max [ for p in 0..size-length do
                  for q in 0..size-p-length
                  -> product [ for i in 0..length-1 -> m.[size-q-i-1,p+q+i] ] ]
let max_ru2 =
      List.max [ for p in 1..size-length do
                  for q in 0..size-p-length
                  -> product [ for i in 0..length-1 -> m.[size-p-q-i-1,q+i] ] ]
printfn "%d" (List.max [ max_r; max_d; max_rd1; max_rd2; max_ru1; max_ru2 ])