Code Golf:Fractran

Nic*_*son 49 code-golf esoteric-languages

挑战

编写一个充当Fractran解释器的程序.任何语言的字符数最短的翻译都是赢家.你的程序必须有两个输入:要执行的fractran程序和输入整数n.该程序可以是任何方便您的程序的形式 - 例如,2元组列表或平面列表.输出必须是单个整数,是执行结束时寄存器的值.

Fractran

Fractran是John Conway发明的一种微不足道的深奥语言.fractran程序由一系列正分数和一个初始状态n组成.解释器维护一个程序计数器,最初指向列表中的第一个部分.Fractran程序以下列方式执行:

  1. 检查当前状态的产品和当前在程序计数器下的分数是否为整数.如果是,则将当前状态乘以当前分数,并将程序计数器重置为列表的开头.
  2. 推进程序计数器.如果到达列表的末尾,则暂停,否则返回步骤1.

有关Fractran如何以及为何如此工作的详细信息,请参阅esolang条目以及关于良好数学/错误数学的此条目.

测试向量

节目: [(3,2)]
输入: 72(2 3 3 2)
输出: 243(3 5)

节目: [(3,2)]
输入: 1296(2 4 3 4)
输出: 6561(3 8)

节目: [(455,33),(11,13),(1,11),(3,7),(11,2),(1,3)]
输入: 72(2 3 3 2)
输出: 15625(5 6)

奖金测试矢量:

您的提交无需正确执行此最后一个程序即可成为可接受的答案.但是如果有的话会感到荣幸!

节目: [(455,33),(11,13),(1,11),(3,7 ),(11,2 ),(1,3)]
输入: 60466176(2 10 3 10)
输出: 7888609052210118054117285652827862296732064351090230047702789306640625(5 100)

提交和评分

程序严格按字符长度排列 - 最短是最好的.随意提交一个布局合理,文档化和代码的"缩小"版本,以便人们可以看到正在发生的事情.

语言'J'不可接受.这是因为在其中一个链接页面上已经有一个众所周知的J解决方案.如果你是J粉丝,抱歉!

然而,作为额外奖励,任何能够 fractran中提供工作分形翻译的人都将获得500点声望点奖励.在不太可能发生多个自托管解释器的情况下,分数最短的解释器将获得赏金.

获奖者

在提交包含1779个分数的自托管fractran解决方案之后,官方获胜者是Jesse Beder的解决方案.实际上,解决方案太慢,甚至不能执行1 + 1.

令人难以置信的是,这已被另一个fractran解决方案击败 - Amadaeus的解决方案只有84个分数!在我的参考Python解决方案上运行时,它能够在几秒钟内执行前两个测试用例.它使用了一种新颖的分数编码方法,值得仔细研究.

荣誉提及:

  • Stephen Canon的解决方案,包含165个字符的x86汇编(28字节的机器代码)
  • Jordan的解决方案是52个字符的红宝石 - 处理长整数
  • 无用的解决方案,使用87个字符的Python,虽然不是最短的Python解决方案,但它是少数几个不递归的解决方案之一,因此可以轻松处理更难的程序.它也非常易读.

Jes*_*der 45

Fractran - 1779分数

(编辑:修复)

(我希望人们仍然关注这个话题,因为这需要一段时间!)

它似乎不会让我发布一些东西,所以我在这里发布了Fractran来源.

输入指定如下:

首先,我们m/n = p_0^a0... p_k^ak通过以下方式编码分数:

  • 从1开始.然后,每个ai:
  • 乘以p_2i^aiif 乘以ai > 0
  • 乘以p_2i+1^{-ai}if 乘以a_i < 0

这样,我们将任何分数编码为正整数.现在,给定一个progoram(编码分数序列F0,F1,...),我们编码

p_0^F0 p1^F1 ...
Run Code Online (Sandbox Code Playgroud)

最后,解释器的输入由下式给出:

2^(program) 3^(input) 5
Run Code Online (Sandbox Code Playgroud)

其中programinput编码如上.例如,在第一个测试问题中,3/2被编码为15,所以程序被编码为2^15; 和108被编码为500.所以,我们通过

2^{2^15} 3^500 5
Run Code Online (Sandbox Code Playgroud)

到该计划.输出,然后是形式

2^(program) 3^(output)
Run Code Online (Sandbox Code Playgroud)

所以在第一个例子中,它将是

2^{2^15} 3^3125
Run Code Online (Sandbox Code Playgroud)

它是如何工作的?

我写了一个元语言,编译成Fractran.它允许函数(简单的Fractran和其他函数序列),以及while循环和if语句(为方便起见!).可以在此处找到该代码.

如果你想自己编译代码到Fractran,我的(C++)程序可以在这里找到[tar.gz].在令人惊叹的dogfooding(和炫耀)展示中,我使用了我的C++ YAML解析器yaml-cpp,所以你必须下载并链接它.对于yaml-cpp和"编译器",你需要CMake来生成跨平台的makefile.

该程序的用法是:

./fracc interpreter.frp
Run Code Online (Sandbox Code Playgroud)

它从标准输入读取函数的名称,并将相应的"伪分数"(我将在一秒内解释)写入标准输出.因此,要编译解释器(Interpret函数),您可以运行

echo "Interpret" | ./fracc interpreter.frp > interpret
Run Code Online (Sandbox Code Playgroud)

输出("pseudo-Fractran")将是一系列行,每行都有一串空格分隔的数字.一条线对应一个分数:如果该n行中的第一个数字是an,则该分数是该分数的乘积p_n^an.

将它转换为Fractran非常容易,但如果你很懒,可以使用to-fractions.py.[ 注意:早些时候我有一个C++程序,我不小心忽略了整数溢出.我把它翻译成Python以避免这种情况.]

关于输入的注意事项:如果要以这种方式测试不同的函数,则约定始终相同.它在伪Fractran中有许多参数(通常是函数上面的注释解释这个),所以给它想要的东西,加上1下一个槽上的一个(所以在普通的Fractran中,乘以它赢得的第一个素数一次不使用).这是函数开始前进的"信号"位.


然而,

我不建议实际尝试运行Fractran解释器(唉).我测试了它的许多组件,例如,函数IncrementPrimes,它接受一对素数并返回接下来的两个素数,运行大约需要8分钟,使用我的傻C++解释器(无需发布:).另外,它在函数调用的数量上(至少)是二次方的 - 函数调用的数量加倍使得它至少需要四倍的时间(如果有while循环或if语句则更多).所以我猜测运行翻译至少需要几天,如果不是几年:(

那么我怎么知道它有效呢?嗯,当然我不是百分百肯定,但我非常接近.首先,我测试了很多很多组件,特别是,我非常彻底地测试了元语言的所有元素(函数ifwhile语句的序列).

此外,元语言很容易翻译成您喜欢的语言,甚至更容易翻译成C++,因为函数的所有参数都是通过引用传递的.如果你再次感到懒惰,你可以在这里下载我的翻译[tar.gz](没有makefile;它只是两个.cpp文件,所以直接调用gcc就可以了).

所以你可以比较两个解释器,运行C++版本(它还需要伪Fractran中的输入/输出),检查它是否有效,然后说服自己元语言也可以工作.


要么!

如果您感到受到启发,并且真的希望看到这个解释器被解释,您可以根据我们得到的Fractran输出类型编写一个"聪明的"Fractran解释器.输出是非常结构化的 - 函数序列是使用信号实现的,所以如果你以某种方式缓存解释器所在的位置,如果没有重要的改变,你可以立即跳转到那里.我认为,这将大大加快计划的速度(可能会减少一个或多个权力的运行时间).

但是,我不确定如何做到这一点,我对所做的事感到满意,所以我将把它作为读者的练习.


Hai*_*inh 41

Fractran:84个分数

FTEVAL = [197*103/(2^11*101), 101/103, 103*127/(2*101), 101/103, 109/101,
  2*23/(197*109), 109/23, 29/109,197*41*47/(31*59), 11^10*53/(127*197), 197/53,
  37/197, 7^10*43/(11^10*37), 37/43, 59/(37*47), 59/47, 41*61/59, 31*67/(41*61),
  61/67, 7*67/(127*61), 61/67,101/71, 73/(127^9*29), 79/(127^2*73),
  83/(127*73), 89/(2*29), 163/29, 127^11*89/79, 337/83, 2*59/89, 71/61,
  7*173/(127*163), 163/173, 337*167/163, 347/(31*337), 337/347, 151/337,
  1/71,19*179/(3*7*193), 193/179, 157/(7*193), 17*181/193, 7*211/(19*181),
  181/211, 193/181, 157/193, 223/(7*157), 157/223, 281*283/239,
  3*257*269/(7*241), 241/269, 263/241, 7*271/(257*263), 263/271, 281/263,
  241/(17*281), 1/281, 307/(7*283), 283/307, 293/283, 71*131/107, 193/(131*151),
  227/(19*157), 71*311/227, 233/(151*167*311), 151*311/229, 7*317/(19*229),
  229/317, 239*331/217, 71*313/157, 239*251/(151*167*313), 239*251/(151*313),
  149/(251*293), 107/(293*331), 137/199, 2^100*13^100*353/(5^100*137),
  2*13*353/(5*137), 137/353, 349/137, 107/349, 5^100*359/(13^100*149),
  5*359/(13*149), 149/359, 199/149]
Run Code Online (Sandbox Code Playgroud)

这完全是手工编写的.我确实编写了一种伪语言,能够更清楚地表达事物,但我没有编写编译器并选择直接编写优化的Fractran代码.

FTEVAL接受输入3^initial_state * 5^encoded_program * 199,产生中间结果3^interpreted_program_state * 199,并在可被整除的数字处完全停止233.

解释的程序被嵌入作为单个基数11数字内的基数10的数字列表,使用数字"a"来标记边界,除了在最后.加法程序[3/2]编码为

int("3a2", 11) = 475.
Run Code Online (Sandbox Code Playgroud)

乘法程序[455/33,11/13,1/11,3/7,11/2,1/3]被编码为

int("1a3a11a2a3a7a1a11a11a13a455a33", 11) = 3079784207925154324249736405657
Run Code Online (Sandbox Code Playgroud)

这是一个真正的大数字.

第一个测试向量在不到一秒的时间内完成,在4545次迭代后产生所需的结果,并在6172次迭代后停止.这是完整的输出.

不幸的是,当我尝试第二个测试向量时,sage segfaulted(但我认为它将使用Prime指数向量在Nick的实现下工作).

这里的空间实在太小,无法解释一切.但这是我的伪代码.我希望在几天内写下我的过程.

# Notations:
# %p
#     designates the exponent of prime factor p that divides the
#     current state.
# mov x y
#     directly translates to the fraction y/x; its meaning: test if x divides
#     the current state, if so divide the current state by x and multiply it by
#     y.  In effect, the prime exponents of x and y are exchanged.  A Fractran
#     program only comprises of these instructions; when one is executable, the
#     program continues from the beginning.
# dec x => mov x, 1
#     wipes out all factors of x
# inc x => mov 1, x
#     this form is here for the sake of clarity, it usually appears in a
#     loop's entry statement and is merged as such when compiled
# sub n ret m {...}
#     conceptually represents a Fractran sub-program, which will execute just
#     like a normal Fractran program, that is, the sub-program's statements
#     execute when triggered and loop back.  The sub-program only exits when none of
#     its statement is executable, in which occasion we multiply the program's
#     state by m.  We can also explicitly break out early on some conditions.
#     It is also possible to enter a sub-prorgram via multiple entry points and
#     we must take care to avoiding this kind of behavior (except in case where
#     it is desirable).

# entry point 101: return 29
# Divide %2 modulo 11:
#   - quotient is modified in-place
#   - remainder goes to %127
sub 101 ret 101 { mov 2^11, 197 }
sub 101 ret 109 { mov 2, 127 }
sub 109 ret 29 { mov 197, 2 }

# entry point 59: return 61
# Multiply %127 by 10^%31 then add result to %7,
# also multiply %31 by 10 in-place.
sub 59 ret 41*61 {
  mov 31, 197*41
  sub 197 ret 37 { mov 127, 11^10 }
  sub 37 { mov 11^10, 7^10 }
}
sub 61 ret 61 { mov 41, 31 }
sub 61 ret 61 { mov 127, 7 } # the case where %31==0

# entry point 71: return 151 if success, 151*167 if reached last value
# Pop the interpreted program stack (at %2) to %7.
sub 71 {
  # call sub 101
  inc 101

  # if remainder >= 9:
  mov 29*127^9, 73
  #     if remainder == 11, goto 79
  mov 73*127^2, 79
  #     else:
  #         if remainder == 10, goto 83
  mov 73*127, 83
  #         else:
  #             if quotient >= 1: goto 89
  mov 29*2, 89
  #             else: goto 163
  mov 29, 163

  # 79: restore remainder to original value, then goto 89
  mov 79, 127^11*89

  # 83: reached a border marker, ret
  mov 83, 337

  # 89: the default loop branch
  # restore quotient to original value, call 59 and loop when that rets
  mov 2*89, 59
  mov 61, 71

  # 163: reached stack bottom,
  # ret with the halt signal
  sub 163 ret 337*167 { mov 127, 7 }

  # 337: clean up %31 before ret
  sub 337 ret 151 { dec 31 }
}

# entry point 193, return 157
# Divide %3 modulo %7:
#   - quotient goes to %17
#   - remainder goes to %19
sub 193 ret 17*181 {
  mov 3*7, 19
}
mov 7*193, 157
sub 181 ret 193 { mov 19, 7 }
mov 193, 157
sub 157 ret 157 { dec 7 }

# entry point 239: return 293
# Multiply %17 by %7, result goes to %3
mov 239, 281*283
sub 241 { mov 7, 3*257 }
sub 263 ret 281 { mov 257, 7 }
mov 281*17, 241
sub 283 ret 293 { dec 7 }

# entry point 107: return 149 if success, 233 if stack empty
# Pop the stack to try execute each fraction
sub 107 {
  # pop the stack
  inc 71*131

  # 151: popped a value
  # call divmod %3 %7
  mov 131*151, 193

  # if remainder > 0:
  mov 19*157, 227
  #     pop and throw away the numerator
  mov 227, 71*311
  #     if stack is empty: halt!
  mov 151*167*311, 233
  #     else: call 239 to multiply back the program state and gave loop signal
  mov 151*311, 229
  sub 229 ret 239*331 { mov 19, 7 }
  # else: (remainder == 0)
  #     pop the numerator
  mov 157, 71*313
  #     clear the stack empty signal if present
  #     call 239 to update program state and gave ret signal
  mov 151*167*313, 239*251
  mov 151*313, 239*251

  # after program state is updated
  # 313: ret
  mov 293*251, 149
  # 331: loop
  mov 293*331, 107
}

# main
sub 199 {
  # copy the stack from %5 to %2 and %13
  sub 137 ret 137 { mov 5^100, 2^100*13^100 }
  sub 137 ret 349 { mov 5, 2*13 }

  # call sub 107
  mov 349, 107

  # if a statement executed, restore stack and loop
  sub 149 ret 149 { mov 13^100, 5^100 }
  sub 149 ret 199 { mov 13, 5 }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*non 20

x86_64程序集,165个字符(28个字节的机器代码).

状态在%rdi中传递,Program(指向以null结尾的分数数组的指针)在%rsi中.根据通常的C风格调用约定,结果以%rax返回.使用非标准的调用约定或Intel语法(这是AT&T语法)会丢弃更多的字符,但我很懒惰; 别人可以做到这一点.通过重新安排控制流程几乎可以肯定地保存一两条指令,如果有人想这样做,请随意.

中间计算(state*numerator)最大可达128位,但仅支持64位状态.

_fractran:
0:  mov     %rsi,   %rcx    // set aside pointer to beginning of list
1:  mov    (%rcx),  %rax    // load numerator
    test    %rax,   %rax    // check for null-termination of array
    jz      9f              // if zero, exit
    mul     %rdi
    mov   8(%rcx),  %r8     // load denominator
    div     %r8
    test    %rdx,   %rdx    // check remainder of division
    cmovz   %rax,   %rdi    // if zero, keep result
    jz      0b              // and jump back to program start
    add     $16,    %rcx    // otherwise, advance to next instruction
    jmp     1b
9:  mov     %rdi,   %rax    // copy result for return
    ret
Run Code Online (Sandbox Code Playgroud)

删除注释,无关的空格以及_fractran最小化版本的详细标签.


Jor*_*ing 16

红宝石, 58 57 56 53 52个字符

这是我有史以来的第一个高尔夫球场,所以请保持温和.

def f(n,c)d,e=c.find{|i,j|n%j<1};d ?f(n*d/e,c):n end
Run Code Online (Sandbox Code Playgroud)

用法:

irb> f 108, [[455, 33], [11, 13], [1,11], [3,7], [11,2], [1,3]]
=> 15625

irb> f 60466176, [[455, 33], [11, 13], [1, 11], [3, 7], [11, 2], [1, 3]]
=> 7888609052210118054117285652827862296732064351090230047702789306640625
Run Code Online (Sandbox Code Playgroud)

漂亮版(252):

def fractran(instruction, program)
  numerator, denominator = program.find do |numerator, denominator|
    instruction % denominator < 1
  end

  if numerator
    fractran(instruction * numerator / denominator, program)
  else
    instruction
  end
end
Run Code Online (Sandbox Code Playgroud)

红宝石, 53 52使用Rational

gnibbler解决方案的启发,我能够使用Rational获得解决方案53 52个字符. 仍然比上面的(不那么优雅)解决方案更长.

def f(n,c)c.map{|i|return f(n*i,c)if i*n%1==0};n end
Run Code Online (Sandbox Code Playgroud)

用法:

irb> require 'rational'
irb> f 60466176, [Rational(455, 33), Rational(11, 13), Rational(1, 11), Rational(3, 7), Rational(11, 2), Rational(1, 3)]
=> Rational(7888609052210118054117285652827862296732064351090230047702789306640625, 1)
Run Code Online (Sandbox Code Playgroud)

(to_i调用更漂亮的输出会增加5个字符.)

  • `def f(n,c)(j = c.find {| i | i*n%1 == 0})?f(n*j,c):n end` - 48 (2认同)
  • `def f(n,c)c.find {| i |($ j = i*n)%1 == 0}?f($ j,c):n end` - 48 (2认同)

Joh*_*ooy 12

Golfscript - 32

    
    {:^{1=1$\%!}?.1={~@\/*^f}{}if}:f

    ; 108 [[3 2]] f p
    # 243
    ; 1296 [[3 2]] f p
    # 6561
    ; 108 [[455 33][11 13][1 11][3 7][11 2][1 3]] f p
    # 15625
    ; 60466176 [[455 33][11 13][1 11][3 7][11 2][1 3]] f p
    # 7888609052210118054117285652827862296732064351090230047702789306640625


eph*_*ent 7

Haskell,102个字符

import List
import Ratio
l&n=maybe n((&)l.numerator.(n%1*).(!!)l)$findIndex((==)1.denominator.(n%1*))l
Run Code Online (Sandbox Code Playgroud)
$ ghci
Prelude> :m List Ratio
Prelude List Ratio> let l&n=maybe n((&)l.numerator.(n%1*).(!!)l)$findIndex((==)1.denominator.(n%1*))l
Prelude List Ratio> [3%2]&108
243
Prelude List Ratio> [3%2]&1296
6561
Prelude List Ratio> [455%33,11%13,1%11,3%7,11%2,1%3]&108
15625

88对输入/输出格式有宽松的限制.

import List
import Ratio
l&n=maybe n((&)l.(*)n.(!!)l)$findIndex((==)1.denominator.(*)n)l
Run Code Online (Sandbox Code Playgroud)
Prelude List Ratio> let l&n=maybe n((&)l.(*)n.(!!)l)$findIndex((==)1.denominator
Prelude List Ratio> [455%33,11%13,1%11,3%7,11%2,1%3]&108
15625 % 1


eph*_*ent 6

C,159 153 151 131 111 110个字符

v[99],c,d;main(){for(;scanf("%d",v+c++););while(d++,v[++d])
*v%v[d]?0:(*v=*v/v[d]*v[d-1],d=0);printf("%d",*v);}
Run Code Online (Sandbox Code Playgroud)
$ cc f.c
$ echo 108 3 2 . | ./a.out; echo
243
$ echo 1296 3 2 . | ./a.out; echo
6561
$ echo 108 455 33 11 13 1 11 3 7 11 2 1 3 . | ./a.out; echo
15625


Pēt*_*une 6

Python,83 82 81 72 70个字符.

将输入作为fractions.Fraction对象很方便.与Ruby解决方案中的想法相同.

def f(n,c):d=[x for x in c if x*n%1==0];return d and f(n*d[0],c) or n

# Test code:
from fractions import Fraction as fr
assert f(108, [fr(3, 2)]) == 243
assert f(1296, [fr(3, 2)]) == 6561
assert f(108, [fr(455, 33), fr(11, 13), fr(1, 11), fr(3, 7), fr(11, 2), fr(1, 3)]) == 15625
assert f(60466176, [fr(455, 33), fr(11, 13), fr(1, 11), fr(3, 7), fr(11, 2), fr(1, 3)]) == 7888609052210118054117285652827862296732064351090230047702789306640625
Run Code Online (Sandbox Code Playgroud)


Joh*_*ooy 5

Python - 53

感谢Paul的改进

f=lambda n,c:next((f(n*x,c)for x in c if x*n%1==0),n)
Run Code Online (Sandbox Code Playgroud)

测试用例

from fractions import Fraction as fr
assert f(108, [fr(3, 2)]) == 243
assert f(1296, [fr(3, 2)]) == 6561
assert f(108, [fr(455, 33), fr(11, 13), fr(1, 11), fr(3, 7), fr(11, 2), fr(1, 3)]) == 15625
assert f(60466176, [fr(455, 33), fr(11, 13), fr(1, 11), fr(3, 7), fr(11, 2), fr(1, 3)]) == 7888609052210118054117285652827862296732064351090230047702789306640625
Run Code Online (Sandbox Code Playgroud)

Python - 54不使用分数

f=lambda n,c:next((f(n*i/j,c)for i,j in c if n%j<1),n)
Run Code Online (Sandbox Code Playgroud)

Python - 55

这个有点理论化.前两种情况运行正常,但另外两种情况从递归深度失败.也许有人可以使用生成器表达式来使用它

f=lambda n,c:([f(n*i/j,c)for i,j in c if n%j<1]+[n])[0]
Run Code Online (Sandbox Code Playgroud)

这是一种可能性,但即使不包括导入也会增长到65

from itertools import chain
f=lambda n,c:(chain((f(n*i/j,c)for i,j in c if n%j<1),[n])).next()
Run Code Online (Sandbox Code Playgroud)


cfe*_*ern 5

F#:80个字符

let rec f p=function|x,(e,d)::t->f p (if e*x%d=0I then(e*x/d,p)else(x,t))|x,_->x
Run Code Online (Sandbox Code Playgroud)

这是一个扩展版本,match pattern with |cases而不是function:

//program' is the current remainder of the program
//program is the full program
let rec run program (input,remainingProgram) =
    match input, remainingProgram with
        | x, (e,d)::rest -> 
            if e*x%d = 0I then //suffix I --> bigint
                run program (e*x/d, program) //reset the program counter
            else    
                run program (x, rest) //advance the program
        | x, _ -> x //no more program left -> output the state   
Run Code Online (Sandbox Code Playgroud)

测试代码:

let runtests() = 
    [ f p1 (108I,p1) = 243I
      f p1 (1296I,p1) = 6561I
      f p2 (108I,p2) = 15625I
      f p2 (60466176I,p2) = pown 5I 100] 
Run Code Online (Sandbox Code Playgroud)

结果(在F#交互式测试中):

> runtests();;
val it : bool list = [true; true; true; true]
Run Code Online (Sandbox Code Playgroud)

编辑让我们有更多的乐趣,并计算一些素数(见起始帖子中的链接页面).我写了一个新函数g,它产生了状态的中间值.

//calculate the first n primes with fractran
let primes n = 
    let ispow2 n = 
        let rec aux p = function
            | n when n = 1I -> Some p
            | n when n%2I = 0I -> aux (p+1) (n/2I)
            | _ -> None
        aux 0 n

    let pp = [(17I,91I);(78I,85I);(19I,51I);(23I,38I);(29I,33I);(77I,29I);(95I,23I); 
              (77I,19I);(1I,17I);(11I,13I);(13I,11I);(15I,14I);(15I,2I);(55I,1I)]

    let rec g p (x,pp) =
        seq { match x,pp with 
                |x,(e,d)::t -> yield x
                               yield! g p (if e*x%d=0I then (e*x/d,p) else (x,t))
                |x,_ -> yield x }

    g pp (2I,pp)
    |> Seq.choose ispow2
    |> Seq.distinct
    |> Seq.skip 1 //1 is not prime
    |> Seq.take n
    |> Seq.to_list
Run Code Online (Sandbox Code Playgroud)

需要惊人的4.7秒来咳出前10个素数:

> primes 10;;
Real: 00:00:04.741, CPU: 00:00:04.005, GC gen0: 334, gen1: 0, gen2: 0
val it : int list = [2; 3; 5; 7; 11; 13; 17; 19; 23; 29]
Run Code Online (Sandbox Code Playgroud)

毫无疑问,这是我写过的最离奇,最慢的素数发生器.我不确定这是好事还是坏事.