首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场

裂变数
EN

Code Golf用户
提问于 2015-05-27 10:52:12
回答 5查看 4K关注 0票数 49

我在OEIS的演化上工作时发现了这个序列,但一直没有把它作为一个答案来发布。在用Mathematica编写了一个参考实现之后,我认为这是一个有趣的练习,可以作为一个单独的挑战来完成,所以我们开始吧。

让我们建造一个数字裂变反应堆!考虑一个正整数N。作为一个例子,我们将看看24。要分裂这个数,我们必须找到最大数目的连续正整数之和为N。在本例中,这是7 + 8 + 9 = 24。所以我们把24分解成三个新的数字。但如果没有连锁反应,这就不是裂变反应堆了。因此,让我们递归地重复这些组件的过程:

代码语言:javascript
运行
复制
       24
       /|\
      / | \
     /  |  \
    7   8   9
   / \     /|\
  3   4   / | \
 / \     /  |  \
1   2   2   3   4
           / \
          1   2

注意,每当数字不能分解为较小的连续整数时,我们就停止处理。还请注意,我们可以将9编写为4 + 5,但是2 + 3 + 4有更多的组件。N的裂变数现在被定义为在这个过程中得到的整数数,包括N本身。上面的树有13个节点,所以是F(24) = 13

此序列为OEIS条目A256504

前40个术语,从N = 1开始,是

代码语言:javascript
运行
复制
1, 1, 3, 1, 5, 6, 5, 1, 6, 7, 12, 10, 12, 11, 12, 1, 8, 16, 14, 17, 18, 18,
23, 13, 21, 18, 22, 23, 24, 19, 14, 1, 22, 20, 23, 24, 31, 27, 25, 26

前1000个术语可以找到在这个烤箱里

挑战

给定一个正整数N,确定它的裂变数F(N)。(所以你不需要覆盖OEIS上列出的领先0。)

您可以编写程序或函数,通过STDIN (或最近的选项)、命令行参数或函数参数获取输入,并通过STDOUT (或最近的选项)、函数返回值或函数(out)参数输出结果。

这是代码高尔夫,所以最短的答案(以字节为单位)获胜。

额外的问题:你能找到这个序列的任何有趣的属性吗?

EN

回答 5

Code Golf用户

发布于 2015-05-27 11:28:52

Python 3,112个字节

代码语言:javascript
运行
复制
def f(n,c=0):
 d=n-c;s=(n-d*~-d/2)/d
 return(s%1or s<1)and f(n,c+1)or+(d<2)or-~sum(f(int(s)+i)for i in range(d))

由于@FryAmTheEggman保存了4个字节。

稍后再解释..。

额外的事实:每个2的幂都有一个裂变数为1。这是因为偶数长度序列的和总是两个中间数之和,这是奇数,乘以序列长度的一半,也就是整数。奇数长度序列之和是中间数乘以序列长度,即奇数。因此,由于2的幂没有奇数除数,它只能表示为自身的和。

票数 10
EN

Code Golf用户

发布于 2015-05-28 09:14:55

Python2,86

代码语言:javascript
运行
复制
f=lambda n,R={1}:n-sum(R)and f(n,R^{[min(R),max(R)+1][n>sum(R)]})or-~sum(map(f,R-{n}))

较少的高尔夫球:

代码语言:javascript
运行
复制
def f(n,R={1}):
    d=sum(R)-n
    if d==0:return (sum(map(f,R-{n}))
    if d<0:return f(n,R|{max(R)+1})
    if d>0:return f(n,R-{min(R)})

其想法是测试与n相加的连续整数的潜在运行情况。运行直接存储为一个集R,而不是通过它的端点。

我们检查当前运行的和如何通过它们的差异与所需的和n进行比较。

  • 如果和太大,我们削减最小的元素在运行。
  • 如果和太小,我们延长运行,使其最大值增大1。
  • 如果和是正确的,我们递归,映射f到运行,求和,并为当前节点添加1。如果运行是{n},我们已经尝试了所有非平凡的可能和,首先通过删除n来停止递归。

感谢Sp3000保存了3个字符。

票数 7
EN

Code Golf用户

发布于 2015-05-31 22:21:12

Go,133个字节

代码语言:javascript
运行
复制
func 算(n int)int{Σ:=1;for i:=0;i<n;i++{for j:=0;j<n;j++{if i*i+i-j*j-j==2*n{for k:=j+1;k<=i;k++{Σ+=算(k)};j,i=n,n}}};return Σ}

这是我第一次打高尔夫球,如果我犯了什么错误,很抱歉。

这使用了这样的想法:裂变“组合”也可以看作是两个有序整数序列之间的区别。例如,以数字13的裂变“组合”为例,它是6,7,但它可以看作是整数1.7减去整数1.5之和的总和。

代码语言:javascript
运行
复制
  A: 1 2 3 4 5 6 7  sum = 28
  B: 1 2 3 4 5      sum = 15 
A-B:           6 7  sum = 13, which is also 28-15 = 13

回想一下高斯学时的公式,sum 1...n=(n^2+n)/2。因此,为了找到给定n的顺序整数的组合,我们也可以说,我们正在沿着范围1. n搜索‘端点’p和q,以便(p^2+p)/2 - (q^2+q)/2 =n。在上面的例子中,我们会搜索‘端点’5和7,因为7^2+7=56/2,5^2+5=30/2,56/2-30/2 = 28-15 = 13。

现在有多种可能的裂变方法--合成一个数字,正如Martin所指出的,9=2+3+4,也有4+ 5。但似乎很明显,“最低”的起始序列也将是最长的,因为与中等大小的数字相比,要将较小的数字加起来需要更少的数字。(不幸的是,我没有证据)

因此,为了找到9的组合,测试每个‘端点对’,p和q,将p和q分别从0迭代到9,并检验p^p+p/2-q^2+q/2=9。或者,更简单地说,将方程乘以2,以避免舍入的除法问题,并将所有的数学保持在整数中。然后我们寻找p和q,使得(p^p+p) - (q^q+q) = 9*2。我们找到的第一个匹配将是裂变合成端点,因为正如前面提到的,最低的一组数也是最长的,我们正在搜索低到高(0到9)。一旦找到匹配,我们就从循环中挣脱出来。

现在递归函数为给定的n找到那些‘易裂变端点’p和q,然后对树中从p到q的每个‘子’进行回顾。对于9,它会找到1和4,(20-2=18),然后重新调用2,3和4,求和结果。对于像4这样的数字,它根本找不到匹配的,因此返回'1‘。这可能是可缩短的,但这就像我的第三个围棋程序,我不是递归专家。

感谢您的阅读。

票数 2
EN
页面原文内容由Code Golf提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codegolf.stackexchange.com/questions/50845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档