费马多边形数定理


24

Fermat的多边形数定理指出,每个正整数都可以表示为最多n 多边形的和。这意味着每个正整数都可以表示为最多三个三角形,四个正方形,五个五角形等的总和。您的任务是取一个正整数和一个整数,并输出相加为整数。nxs3sx

第个角整数,其中和可以用两种方法定义。非数学-Y方式是个 -gonal数可以构造为正多边形与两侧,各有长度的。例如,对于(三角数):nsn1s3nssns=3

三角形

请参阅此处以获取具有更大示例。s

math-y定义是通过使用的公式,它得出第个角数:P(n,s)ns

P(n,s)=n2(s2)n(s4)2

这是在维基百科页面给出这里

输入项

两个正整数和,条件为。您可以用您的语言以最自然的表示形式输入这些整数(十进制,一进制,教堂数字,整数值浮点数等)。sxs3

输出量

整数列表,最大长度为,其中L的总和等于xL所有整数都是s-角整数。同样,整数可以用您的语言以自然表示形式输出,并带有任何不同的,一致的分隔符(因此,十进制输出使用非小数字符,一进制输出使用不同的字符等)。LsLxLs

规则

  • 输入或输出将永远不会超出您语言的整数限制
  • L不必订购
  • 如果有多个可能的输出,则任何一个或全部都可以接受
  • 这是因此以字节为单位的最短代码获胜

测试用例

   x,  s => L
   1,  s => 1
   2,  s => 1, 1
   5,  6 => 1, 1, 1, 1, 1
  17,  3 => 1, 6, 10
  17,  4 => 1, 16
  17,  5 => 5, 12
  36,  3 => 36
  43,  6 => 15, 28
 879, 17 => 17, 48, 155, 231, 428
4856, 23 => 130, 448, 955, 1398, 1925


输出可以有一些零填充吗?例如,如果我们考虑x=17, s=5可以输出5,12,0,0,0而不是仅输出5,12
flawr

@flawr只要阵列不超过长度,即使填充,这很好s
凯尔德coinheringaahing

是否允许重复或我应该Q在提交的内容中添加一个?
乔纳森·艾伦

@JonathanAllan重复输出非常好(如果输出多个解决方案)
caird coinheringaahing

Answers:


6

Haskell78 80 77字节

我们计算前n s角数的笛卡尔积,然后找到总和为n的第一个条目。

s#n=[x|x<-mapM(map(\n->s*(n^2-n)`div`2+n*(2-n)))([0..n]<$[1..s]),sum x==n]!!0

在线尝试!


6

JavaScript(ES6), 83个  80字节

快速递归搜索,可最大化输出的最小项。

将输入作为(s)(x)

s=>g=(x,n=0,a=[],y=~n*(~-n-n*s/2))=>x<y?x|a[s]?0:a:g(x,n+1,a)||g(x-y,n,[...a,y])

在线尝试!

事实证明,使用基于0的公式来计算JS中的s角数会更短,即从n=0开始并计算P(n+1,s)

P(n+1,s)=((n+1)2(s2)(n+1)(s4))/2=(n2(s2)+ns+2)/2=(n+1)((n1)ns/2)

可以写成14个字节:

~n*(~-n-n*s/2)

已评论

s =>                         // main function taking s
  g = (                      // recursive function g
    x,                       // taking x
    n = 0,                   // start with n = 0
    a = [],                  // a[] = list of s-gonal numbers
    y =                      // y = P(n + 1, s)
      ~n * (~-n - n * s / 2) //   = -(n + 1) * ((n - 1) - n * s / 2)
  ) =>                       //
    x < y ?                  // if x is less than P(n + 1, s):
      x | a[s] ?             //   if x is not equal to 0 or a[] is too long:
        0                    //     failed: return 0
      :                      //   else:
        a                    //     success: return a[]
    :                        // else:
                             //   process recursive calls:
      g(x, n + 1, a) ||      //   preferred: try to increment n
      g(x - y, n, [...a, y]) //   fallback : try to use the current s-gonal number

@AZTECCO我稍后可能会尝试修复它。暂时删除。
Arnauld

谢谢。等待中!
AZTECCO


4

Haskell,55个字节

n%s=[l|l<-mapM(\_->scanl(+)0[1,s-1..n])[1..s],sum l==n]

在线尝试!

输出所有可能的解决方案。将s角形数字定义为算术级数的累加和

1, s-2, 2*s-3, 3*s-4, ...

3

果冻,17 个字节

x’2;’ÄÄx⁸ŒPS⁼¥Ƈ⁹Ḣ

一个(非常低效的)二元链接s在左侧和x右侧接受,它会以整数列表(排序为升序)产生尽可能短的答案。

在线尝试!-尝试更高的价值没有多大意义!

怎么样?

x’2;’ÄÄx⁸ŒPS⁼¥Ƈ⁹Ḣ - Link: s, x                    e.g.  5, 17
x                 - repeat (s) (x) times                [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
 ’                - decrement (vectorises)              [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
  2;              - prepend a two                       [2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
    ’             - decrement (vectorises)              [1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
     Ä            - cumulative sums                     [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52]
      Ä           - cumulative sums                     [1, 5, 12, 22, 35, 51, 70, 92, 117, 145, 176, 210, 247, 287, 330, 376, 425, 477]
       x⁸         - repeat (each of those) (s) times    [1, 1, 1, 5, ..., 425, 477, 477, 477]
         ŒP       - power-set                           [[], [1], [1], ..., [1, 1], ..., [5, 22, 70], ... etc]
                      (this has 2^(x(s+1)) entries ...this example would have 2^(17(5+1)) = 2^102 = 5070602400912917605986812821504 entries!)
                      (Note: the lengths increase left to right)
              Ƈ   - filter keep if:
             ¥    -   last two links as a dyad:
           S      -     sum
            ⁼  ⁹  -     equals (x)?                     [[5,12], ... , [5,12], [1, 1, 5, 5, 5], ... , [1, 1, 5, 5, 5], [1, 1, 1, 1, 1, 12], ...]
                Ḣ - head                                [5,12]

@AZTECCO很好,它在TIO上的超时时间为60秒(我敢肯定,输入数字比这还要小得多)。正如我在回答中指出的那样,这“效率非常低”,“为获得更高的价值而尝试它没有多大意义!”。请记住,为代码高尔夫解决方案提供的代码只需要在资源无限的情况下工作。
乔纳森·艾伦

好的,我用s = 3和n = 5进行了测试,耗时12秒!我喜欢这个效率低下的解决方案,即使您几乎无法测试它,我也会信任您。:)谢谢!
AZTECCO

1
xs

3

红宝石,79字节

n ss

n2(s2)n(s4)2n(ns2ns+4)2

->n,s{a=(0..n).map{|i|i*(i*s-2*i-s+4)/2};a.product(*[a]*~-s).find{|a|a.sum==n}}

在线尝试!



2

视网膜,111字节

\d+
*
~(`$
$"
0%["^_+ "|""]'$L$`\G_(?<=(?=___(_*))_+)
((_(?($.(2*$>`))$1\$.(2*$>`)))$*)
1%|' L$`\G_
$$.$.($`$>`

在线尝试!链接包括测试用例。按顺序接受输入s n。说明:

\d+
*

转换为一元。

~(`

处理完其余阶段后,将它们视为Retina程序,并在相同的输入上执行它们。

$
$"

复制行。

0%["^_+ "|""]'$L$`\G_(?<=(?=___(_*))_+)
((_(?($.(2*$>`))$1\$.(2*$>`)))$*)

用正则表达式替换第一个副本,该正则表达式会跳过第一个数字,然后匹配- s s多边形。数字本身被捕获在奇数捕获组中,偶数捕获组用于确保所有数字都是- s多边形。

1%|' L$`\G_
$$.$.($`$>`

用空格分隔的奇数捕获组列​​表替换第二个副本。

例如,输入的生成代码5 17如下:

^_+ ((_(?(2)__\2))*)((_(?(4)__\4))*)((_(?(6)__\6))*)((_(?(8)__\8))*)((_(?(10)__\10))*)$
$.1 $.3 $.5 $.7 $.9

1

APL(NARS),149个字符,298个字节

r←f w;n;s;i;k
(n s)←w⋄r←⍬⋄→0×⍳s<3⋄i←1
→0×⍳n<k←2÷⍨(i×i×s-2)-i×s-4⋄r←r,k⋄i+←1⋄→2

h←{0=≢b←((v←↑⍵)=+/¨a)/a←{0=≢⍵:⊂⍬⋄m,(⊂1⌷⍵),¨m←∇1↓⍵}f⍵:v⍴1⋄k←↑⍋≢¨b⋄k⊃b}

如果没有找到解决方案“ 0 =≢b”,则返回(ns)个输入,n乘以1;否则它将返回加数较少的s个数字的总和...

测试:

  h 1 3
1 
  h 2 8
1 1 
  h 5 6
1 1 1 1 1 
  h 17 3
1 6 10 
  h 17 4
1 16 
  h 17 5
5 12 
  h 36 3
36 
  h 43 6
15 28 
  h 879 17
17 48 155 231 428 
  h 4856 23
321 448 596 955 2536 
  +/h 4856 23
4856

问题是:找不到总和重复的数字...


0

C ++(clang),198字节

#import<vector>
using V=std::vector<int>;V f(int n,int s){V _{0};int z=1,a=0,b=1,i,t;for(;a<n;b+=s-2)_.push_back(a+=b),++z;V o;for(t=a=0;t-n;b=++a)for(o=V(s),t=i=0;b;b/=z)t+=o[i++]=_[b%z];return o;}

在线尝试!

V=vector<int> 
V _{0}; // initialized with one element =0 
int z=1, // vector size 
a=0,b=1,i,t;for(;a<n;b+=s-2)_.push_back(a+=b),++z;
// pushes polygons in V
V o; // vector to be returned 
for(t=a=0;t-n;b=++a) // ends when t=n
// loop to generate multi-dimension indexes
// for example a=1234 z=10
// a%z->4 , a/=z , a%z-> 3 , ... 2 , 1
for(o=V(s),t=i=0;b;b/=z)// loop to extract indexes
t+=o[i++]=_[b%z]; // put the sum in t and values in o
return o
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.