序言(SWI) ,134个 128 127 124字节
这个答案是我和0'之间合作的一部分。我们俩共同努力,我发布的唯一原因是我赢了Rock,Paper和Scissors。
\Q-->{Q=1};"(",\N,")",\B,{findnsols(N,I,(between(2,inf,I),\+ (between(3,I,U),0=:=I mod(U-1))),L)->append(_,[Y],L),Q is Y*B}.
在线尝试!
说明
这个答案很好地说明了打高尔夫球的乐趣。
该答案使用Prologs功能强大的系统来处理定句语法。这是我们的语法略显不足。
head(1)-->[].
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
第一条构造规则是:
head(1)-->[].
这告诉Prolog空字符串对应于1。
我们的第二个构造规则稍微复杂一点。
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
这告诉我们,任何非空字符串在具有这些相同规则的子句的右边,都包含一个带有这些相同规则的子句的括号。
它还告诉我们,此子句(Q)的值遵循以下规则:
{prime(N,Y),Q is Y*B}
细分Q为2个数字Y和的乘积B。 B只是左边的子句的值,并且Y是N第素数,其中N括号内的子句的值是。
该规则涵盖因子树的两个形成规则
现在为谓词定义。在非高尔夫版本中,有两个谓词在起作用(在我的实际代码中,我将这些谓词向前链接在一起)。这里的两个相关谓词是isprime/1,它匹配一个素数,而和prime/2,给定N和Y,匹配Y是N素数。首先我们有
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
这项工作非常标准地定义了素数,我们坚持认为2与之间没有数字I,包括2但不I存在除法I。
下一个谓词也很简单
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
我们findnsols用来查找第一个N素数,然后返回最后一个。这里的技巧是虽然findnsols不能保证找到最小的 N素数,但是由于SWI处理的方式,between它总是会更快地找到较小的素数。但是,这意味着我们必须减少以防止它找到更多的素数。
高尔夫
我们可以两次在代码中转发原因。因为isprime仅在其定义可以移入时使用一次prime。下一步骤是prime直接移入DCG内部,但是由于我们采用切入方式prime来防止findnsols产生过多的素数,因此存在一些问题。削减,削减了整个DCG,而不仅仅是我们想要的。经过一些文档挖掘,我们发现once/1可以将其仅用于剪切这部分,而不能剪切整个DCG。但是,更多的文档挖掘表明,->操作员也可以用来执行类似的任务。该->运算符大致等于,,!,因此我们将剪切移动到的另一侧append/3并替换为->。
在SWI-Prolog中,谓词(和规则)可以作为运算符的名称,使我们可以删除通常需要的括号。因此,我们可以通过调用规则来节省6个字节\。