解码因子树


11

如果您错过了编码因子树,这是因子树的定义:

  • 空字符串为1。
  • 串联表示乘法。
  • 括号(或任何成对的字符)中包含的数字n表示第n个质数,其中2是第一个质数。
    • 请注意,这是递归完成的:第n个素数是括号中n的因数树。
  • 数量的因数应按从小到大的顺序排列。

例如,以下是2到10的因子树:

()
(())
()()
((()))
()(())
(()())
()()()
(())(())
()((()))

这个挑战使用了类似的格式。然而,这个挑战是这些结构进行解码

测试用例

无耻地被盗 改变用途从上个挑战。

除了上面的9个之外……

()()((()))((())) => 100
(()(()(()))) => 101
(()())(((())))(()(())) => 1001
(((((((()))))))) => 5381
(()())((((()))))(()()(())(())) => 32767
()()()()()()()()()()()()()()() => 32768

规则

  • 输入中的成对字符是您选择的括号,方括号,大括号或尖括号。如果要求,我可以允许其他格式(例如XML标记)。
  • 您应该能够处理2到2 15或32768中任何数字的因子树。
  • 由于这是,因此以字节为单位的最短答案会获胜。

Answers:



8

序言(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和的乘积BB只是左边的子句的值,并且YN第素数,其中N括号内的子句的值是。

该规则涵盖因子树的两个形成规则

  • 串联相乘
  • 外壳采用第n个素数

现在为谓词定义。在非高尔夫版本中,有两个谓词在起作用(在我的实际代码中,我将这些谓词向前链接在一起)。这里的两个相关谓词是isprime/1,它匹配一个素数,而和prime/2,给定NY,匹配YN素数。首先我们有

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个字节\


2

Python 3中125个 110字节

lambda s:eval(s.replace("]","1]*").replace("[","p[1*")+"1")
p=2,
k=P=1
while k<1e4:
 if P%k:p+=k,
 P*=k*k;k+=1

在线尝试!

使用xnor的 Wilson定理方法实现来生成素数。替代品()[]


1

JavaScript(ES6),98个字节

notjagan的Python答案启发。将输入表达式转换为巨大且难看的可执行字符串。

s=>eval(s.split`)(`.join`)*(`.split`(`.join`(g=(n,k)=>(C=d=>n%--d?C(d):k-=d<2)(++n)?g(n,k):n)(1,`)

Cg功能合并为一个可能会节省一些字节,但是将需要更多的递归。

测试用例

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.