我最近找到了一份关于Python程序员的F#的演示文稿,看完后,我决定自己实现“蚂蚁难题”的解决方案。
有一只蚂蚁可以在平面网格上行走。蚂蚁每次可以向左、右、上或下移动一个空间。也就是说,从单元格(x,y),蚂蚁可以到达单元格(x+1,y)、(x-1,y)、(x,y+1)和(x,y-1)。当x和y坐标的数字之和大于25时,这些点对蚂蚁不可达。例如,点(59,79)不可达,因为5+9+7+9=30,大于25。问题是:如果蚂蚁从(1000,1000)开始,包括(1000,1000)本身,它能够访问多少个点?
我用OCaml first实现了我的解决方案,并尝试了一下:
$ ocamlopt -unsafe -rectypes -inline 1000 -o puzzle ant.ml
$ time ./puzzle
Points: 148848
real 0m0.143s
user 0m0.127s
sys 0m0.013s
我的结果和Leonardo的D和C++实现一样整洁。与Leonardo的C++实现相比,OCaml版本运行速度大约慢了两倍。这还好,考虑到Leonardo使用队列来消除递归。
然后,我将代码翻译成了F# ... 这是我的结果:
Thanassis@HOME /g/Tmp/ant.fsharp
$ /g/Program\ Files/FSharp-2.0.0.0/bin/fsc.exe ant.fs
Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
Thanassis@HOME /g/Tmp/ant.fsharp
$ ./ant.exe
Process is terminated due to StackOverflowException.
Quit
Thanassis@HOME /g/Tmp/ant.fsharp
$ /g/Program\ Files/Microsoft\ F#/v4.0/Fsc.exe ant.fs
Microsoft (R) F# 2.0 Compiler build 4.0.30319.1
Copyright (c) Microsoft Corporation. All Rights Reserved.
Thanassis@HOME /g/Tmp/ant.fsharp
$ ./ant.exe
Process is terminated due to StackOverflowException
我在我的计算机上安装了两个版本的F#,结果遇到了栈溢出问题。 出于好奇,我将生成的二进制文件(ant.exe)在Arch Linux/Mono下运行:
$ mono -V | head -1
Mono JIT compiler version 2.10.5 (tarball Fri Sep 9 06:34:36 UTC 2011)
$ time mono ./ant.exe
Points: 148848
real 1m24.298s
user 0m0.567s
sys 0m0.027s
令人惊讶的是,它在Mono 2.10.5下运行(即没有堆栈溢出)-但需要84秒,即比OCaml慢587倍-糟糕。
所以这个程序...
- 在OCaml下运行良好
- .NET/F#下完全不起作用
- 在Mono/F#下工作,但速度非常慢。
为什么?
编辑:奇怪的事情继续发生-使用“--optimize+ --checked-”可以解决问题,但仅适用于ArchLinux/Mono; 在Windows XP和Windows 7/64位下,即使是优化版本的二进制文件也会导致堆栈溢出。
最终编辑:我自己找到了答案-请参见下文。