计算两个平方的和


45

给定一个非负数n,请输出表示n为两个整数平方的和的方式数n == a^2 + b^2OEIS A004018)。请注意,ab可以为正,负或零,并且它们的顺序很重要。最少的字节数获胜。

例如,n=25给出12因为25可以表示为

(5)^2  + (0)^2
(4)^2  + (3)^2
(3)^2  + (4)^2
(0)^2  + (5)^2
(-3)^2 + (4)^2
(-4)^2 + (3)^2
(-5)^2 + (0)^2
(-4)^2 + (-3)^2
(-3)^2 + (-4)^2
(0)^2  + (-5)^2
(3)^2  + (-4)^2
(4)^2  + (-3)^2

这是直到的值n=25。请注意,您的代码适用于n=0

0 1
1 4
2 4
3 0
4 4
5 8
6 0
7 0
8 4
9 4
10 8
11 0
12 0
13 8
14 0
15 0
16 4
17 8
18 4
19 0
20 8
21 0
22 0
23 0
24 0
25 12

这里是直到n=100列表的值。

[1, 4, 4, 0, 4, 8, 0, 0, 4, 4, 8, 0, 0, 8, 0, 0, 4, 8, 4, 0, 8, 0, 0, 0, 0, 12, 8, 0, 0, 8, 0, 0, 4, 0, 8, 0, 4, 8, 0, 0, 8, 8, 0, 0, 0, 8, 0, 0, 0, 4, 12, 0, 8, 8, 0, 0, 0, 0, 8, 0, 0, 8, 0, 0, 4, 16, 0, 0, 8, 0, 0, 0, 4, 8, 8, 0, 0, 0, 0, 0, 8, 4, 8, 0, 0, 16, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 8, 4, 0, 12]

有趣的事实:该序列包含任意高的项,其移动平均值的限制为π。

排行榜:


4
等等,什么?“该序列包含任意高的项,其运行平均值的极限是π。”
Stewie Griffin

@StewieGriffin这两个语句是一致的。考虑顺序1,0,2,0,0,3,0,0,0,4,0,0,0,0,5,...。截取任何非零数字之后的序列,到目前为止的平均值是1。而且,0的游程在序列的后面影响越来越小。
xnor

5
我知道它是一致的。=)发布评论时,我检查了10.000个第一个数字。我不明白的是:为什么地球上它等于Pi?
Stewie Griffin

29
@StewieGriffin直到N的项之和对应于a ^ 2 + b ^ 2 <= N的点(a,b)。这些是半径为sqrt(N)的圆中的晶格点,其面积为πN。
xnor

2
@xnor,神奇之处就在于:(
Andras Deak

Answers:


19

Python(59 57 56字节)

lambda n:0**n+sum((-(n%(x-~x)<1))**x*4for x in range(n))

在线演示

与我的CJam答案一样,它使用Möbius反演并以伪准线性时间运行。

多亏了Sp3000节省了2个字节,而feersum节省了1 个字节。


1
那些括号令人讨厌。
lirtosiast

@ThomasKwa,告诉我这件事。在我发布第一个版本时所经历的其中一个版本中,真正使我感到惊讶的是,-1**x它始终是-1。我期望-1它将是单个整数文字标记,而不是低序一元减号后跟一个。
彼得·泰勒

2
恭喜!您的代码比我想出的要短。您的解决方案基于一个全新的,出乎意料的数学思想,这让我很高兴,即使在如此简单明了的挑战中,这也是可能的。与Mobius逆的结果非常漂亮,我很乐意为我。
xnor 2015年

通过将乘法运算后移4可以节省1个字节**x
feersum

@PeterTaylor您能详细说明一下您的算法如何工作/您能指出我一种资源吗?我不太清楚如何将möbius求逆应用于suqares问题的总和。
flawr

15

Mathematica,13个字节

如果允许内置,这就是在Mathematica中的方法。

2~SquaresR~#&

对于0 <= n <= 100

2~SquaresR~# & /@ Range[0, 100]

{1,4,4,0,4,8,0,0,4,4,8,0,0,8,0,0,4,8,4,0,8,0,0,0,0 ,12、8、0、0、8、0、0、4、0、8、0、4、8、0、0、8、8、0、0、0、8、0、0、0、4 ,12、0、8、8、0、0、0、0、8、0、0、8、0、0、4、16、0、0、8、0、0、0、4、8、8 ,0,0,0,0,0,8,4,8,0,0,16,0,0,0,8,8,0,0,0,0,0,0,8,4,0 ,12}


1
因为Mathematica当然具有内置功能。
HyperNeutrino '16

14

Python 2,44字节

f=lambda n,x=1:+(x>n)or(n%x<1)-f(n,x+2)/4<<2

这几乎与xsot的解决方案(基于Peter Taylor的解决方案)相同,但是通过简化处理符号的方式节省了8个字节。

请注意,对于完整的程序,我们可以在函数中节省2个字节,而不会在函数外部产生任何开销:

f=lambda n,x=1:x>n or(n%x<1)-f(n,x+2)/4<<2
print+f(input())

这样,完整程序的另外两个字节:

n=input()
f=lambda x:x>n or(n%x<1)-f(x+2)/4<<2
print+f(1)

因为n > 0有一个非常清晰的40字节解决方案:

f=lambda n,x=1:n/x and(n%x<1)*4-f(n,x+2)

1
恭喜您获得了赏金!递归减法是一种表达奇数除数的交替和的简洁明了的方法,而无需从除数本身提取符号。同样,由于xsot简化了Peter Taylor对n = 0的巧妙处理的递归解决方案的贡献,因此值得赞扬。
xnor 2015年


12

J,16个字节

+/@,@:=+&*:/~@i:

这是一元动词(换句话说,一元函数)。 在线尝试查看通过所有测试案例

说明

+/@,@:=+&*:/~@i:  Denote input by n
              i:  The array of integers from -n to n
           /~@    Take outer product wrt the following function:
       +           the sum of
        &*:        squares of both inputs
                  This results in a 2D array of a^2+b^2 for all a, b between -n and n
      =           Replace by 1 those entries that are equal to n, and others by 0
   ,@:            Flatten the binary matrix
+/@               Take its sum

11

Python 2,69 55 53 52字节

f=lambda n,x=1:+(x>n)or(2-x%4)*(n%x<1)+f(n,x+2)/4<<2

这是基于Peter Taylor出色解决方案的递归函数。


1
这是一个很大的改进。但是,还有一种方法可以缩短它,我鼓励您寻找它。
xnor 2015年

1
@xnor另一个字节向下。希望您不再袖手旁观。
xsot

2
我不知道是否应该回答这个问题,这只是您的解决方案和一个技巧:f=lambda n,x=1:+(x>n)or(n%x<1)-f(n,x+2)/4<<2。另外,我想我们是否不在乎超出默认的最大递归深度?
米奇·施瓦兹

1
@MitchSchwartz我认为这是一个令人难以置信的改进,值得悬赏,而且可能是xnor考虑到的最终优化。
xsot 2015年

1
@MitchSchwartz是的,这就是我正在考虑的优化!xsot的/4<<2技巧使它比我拥有的要短。
xnor 2015年

8

朱莉娅,40个字节

n->n>0?4sum(i->(n-i^2)^.5%1==0,1:n^.5):1

取消高尔夫:

function f(n)
  if n==0
    return 1           # Handle special case of n=0
  else
    m=0                # Start the counter at zero
    for i=1:sqrt(n)    # Loop over the values (i) whose squares are
                       # less than n (except zero)
      k=sqrt(n-i^2)    # Find k such that n=k^2+i^2
      if k==floor(k)   # if k is an integer, we've found a pair
        m+=4           # Add one for each of k^2+i^2, (-k)^2+(-i)^2, and the other two
      end
    end
    return m           # Return the resulting count
  end
end

请注意,循环不包含i==0,因为当n是正方形时,它已经包含在其中i=sqrt(n),并且该形式(0^2+k^2, 0^2+(-k)^2, k^2+0^2, (-k)^2+0^2)只有四个而不是八个。


7

果酱 25 23字节

Zri:R#Ym*{Rf-Yf#:+R=},,

这是理论解,需要O(9 n时间和内存来存储输入n

以一个额外的字节为代价(总共24个字节),我们可以将复杂度降低为O(n 2

ri:R)Y*Ym*{Rf-Yf#:+R=},,

在线尝试!

这个怎么运作

要么

Z                  Push 3.
 ri:R              Read an integer from STDIN and save it in R.
     #             Compute 3**R.

要么

ri:R               Read an integer from STDIN and save it in R.
    )Y*            Add 1 and multiply by 2.

然后

Ym*                Take the second Cartesian power, i.e., compute all pairs.
   {          },   Filter the pairs:
    Rf-              Subtract R from each.
       Yf#           Square the differences.
          :+         Add the squares.
            R=       Compare with R.
                   If = pushed 1, keep the pair.
                ,  Count the kept pairs.

只需节省一个字节,就可以将复杂度降低到Õ(n)
Peter Taylor

是的,我看到了。太棒了。
丹尼斯

7

CJam(25 24 22 21字节)

{:X!X{X\2*)%!4*\-}/z}

在线演示

它以伪准线性时间*运行,并使用OEIS中的语句

Moebius变换是周期4序列[4,0,-4,0,...]。-Michael Somos,2007年9月17日

输入 0显然是一种特殊情况(莫比乌斯变换和an灭者并不能很好地融合在一起),但最终只花费了一个字符。

*伪-因为它在输入值上是准线性的,而不是输入的大小;之所以准是因为它对Theta(n)大小约为整数的整数进行运算n; 一个b位模操作应采取b lg b的时间,所以总体而言,这需要Theta(n lg n lg lg n)时间。


6

Japt42 37 33字节

JaptJa vaScri pt的缩写。口译员

V=Un oU+1;Vr@X+(Vf_p2 +Y*Y¥U)l ,0

这个怎么运作

           // Implicit: U = input number
V=Un oU+1  // Set variable V to range(-U, U+1). Ends up like [-U,-U+1,...,U-1,U]
Vr@    ,0  // Reduce each item Y in V with this function, starting at 0:
X+(     l  //  Return the previous value X + the length of:
Vf_p2      //   V filtered by items Z where Z*Z
+Y*Y==U)   //    + Y*Y equals U.
           // This ends up as the combined length of all fitting pairs of squares.
           // Implicit: return last expression

也许有更好的技术。欢迎提出建议。


6

Python 3,68 61 60字节

lambda n:0**n+4*sum(i**.5%1+(n-i)**.5%1==0for i in range(n))

使用两个嵌套列表推导太昂贵了。而是检查半径sqrt(n)的圆上的两个坐标是否都是整数。

彼得·泰勒(Peter Taylor)通过基于Moebius反转的方法克服了这一难题


做得好。我在修改递归函数,但无法n=0优雅地解决。
xsot


5

Haskell,42个字节

f n|q<-[-n..n]=sum[1|a<-q,b<-q,a*a+b*b==n]

用法示例:

*Main> map f [0..25]
[1,4,4,0,4,8,0,0,4,4,8,0,0,8,0,0,4,8,4,0,8,0,0,0,0,12]
*Main> 

3
绑定q后卫很聪明,我会记住这个技巧。
xnor

5

朱莉娅89 79 63字节

g(x)=cos(π*x^.5)^2÷1
a(n)=(n==0)+4sum([g(i)g(n-i)for i=1:n])

这是一个命名函数a,它接受整数并返回浮点数。它调用一个辅助函数g

取消高尔夫:

function g(x::Integer)
    floor(cos(π*sqrt(x))^2)
end

function a(n::Integer)
    (n == 0) + 4*sum([g(i)*g(n-i) for i=1:n])
end

此处的方法使用了OEIS中列出的Wesley Ivan Hurt公式的简化形式。简化是由Glen O发现的,他是从该答案中删掉26个字节的同一个人!


使用x^.5而不是sqrt(x)保存3个字节。并(n==0)节省2个字节以上1÷(n+1)。而且您可以使用cos(π*sqrt(x))^2÷1而不是来保存4个字符floor(cos(π*sqrt(x))^2)。另外,请使用1:n/2而不是1:n÷2,因为使用浮点数不会造成任何损害,g(x)并且i无论如何它将被锁定为整数。并且sum(i->g(i)g(n-i),1:n/2)还将剃除更多字符。
Glen O

@GlenO很棒的建议,谢谢。该sum招失败了n=0,虽然,所以我一直阵列的理解。
Alex A.

1
因此,它可以恢复-如果让i=0案件总数发生,则可以打开符号4g(n)。因此(n==0)-4g(n)-4g(n/2)+8sum(i->g(i)g(n-i),0:n/2),这不会遇到错误。但是,通过注意对称性,您甚至可以做得更好(n==0)+4sum([g(i)g(n-i)for i=1:n])
Glen O

@GlenO这种简化是严重的天才。我建议您将其提交为OEIS序列的替代公式!
Alex A.

4

Pyth,16 15字节

lfqQs^R2T^}_QQ2

Pyth编译器中在线尝试。

这个怎么运作

lfqQs^R2T^}_QQ2

          }_QQ   Compute the inclusive range from -Q to Q (input).
         ^    2  Take the second Cartesian power, i.e., compute all pairs.
 f               Filter; for each T in the list of pairs:
     ^R2T          Compute the squares of T's elements.
    s              Add the squares.
  qQ               Compare the sum with Q.
                 If q returned True, keep T.
l                Count the kept pairs.

4

TI-BASIC,23个字节

sum(seq(Σ(X²+Y²=Ans,X,-Ans,Ans),Y,-Ans,Ans

非常简单。 Σ(是总结。

奇怪的是,sum(seq(sum(seq(抛出ERR:ILLEGAL NEST,等等Σ(Σ(,但是sum(seq(Σ(很好。我选择将其Σ(放在里面以保存近亲。


sum和之间有什么区别Σ
alephalpha

1
@alephalphaΣ(进行求和,将X²+Y²=AnsX -Ans和之间的所有X值相加。sum Ans(是列表的总和,因此我们需要首先使用seq(...,Y,-Ans,Ans
lirtosiast

4

JavaScript(ES6),66 60字节

n=>eval("for(r=0,a=~n;a++<n;)for(b=~n;b++<n;)r+=a*a+b*b==n")

由于节省了6个字节 @ edc65

说明

n=>eval(`              // use eval to allow for loops in an unparenthesised arrow function
  for(r=0,             // r = number of pairs
    a=~n;a++<n;        // a = first number to square
  )
      for(b=~n;b++<n;) // b = second number to square
        r+=a*a+b*b==n  // add one to the result if a^2 + b^2 == n
                       // implicit: return r
`)

测试

n = <input type="number" oninput='result.innerHTML=(

n=>eval("for(r=0,a=~n;a++<n;)for(b=~n;b++<n;)r+=a*a+b*b==n")

)(+this.value)' /><pre id="result"></pre>


1
60:n=>eval('for(r=0,a=~n;a++<n;)for(b=~n;b++<n;)r+=a*a+b*b==n')
edc65

@ edc65不错!我没想到要使用循环eval将其for放入没有括号的箭头函数中。我也忘记了~接线员哈哈。
user81655 2015年

4

Python 3、93 62 69字节

Itertools无法正常工作,因此我再次使用了两个范围,但将范围移出以节省字节。

编辑:以前的代码实际上不起作用,因为我在定义n之前定义了n范围。

lambda n:sum(i*i+j*j==n for i in range(-n,n+1)for j in range(-n,n+1))

2

APL,23 20 19字节

{+/⍵=∊∘.+⍨×⍨0,,⍨⍳⍵}

说明:

{+/⍵=∊∘.+⍨×⍨0,,⍨⍳⍵}        Monadic function:
                 ⍳⍵          1 2 3 ... ⍵
               ,⍨            Duplicate
             0,              Concatenate to 0
          ×⍨                 Square everything
      ∘.+⍨                   Make an addition table
     ∊                       Flatten
   ⍵=                        1s where equal to the input
 +/                          Sum up the 1s

除了APL没有J的事实 i:(从-n到n的数字)外,这非常类似于J答案。

我们不能坐火车,因为 -\⍳2×⍵进行解析,(-\) ⍳ (2×⍵)将花费3个字节。与其他一对atops类似。所有这些括号使常规函数更短。

在这里尝试。1均值的输出将匹配所有值。


2

Matlab 41字节

与以前的答案一样小

@(n)nnz(~mod(sqrt(n-(1:n^.5).^2),1))*4+~n

从本质上讲,Agawa001的答案已替换为电源和sqrt


2

糖果17 14字节

最初将输入推入堆栈

~TbAT1C(sWs+Aeh)Z

~T0C(sWs+Aeh)Z

peekA    # copy arg from stack to register A
range2   # create double sided range on stack, -A, 1-A, ... A-1, A
digit0   # prefix argument to 'cart', 
cart     # cartesian product of current stack(0), and other stack(0)
while    # while stack not empty
  sqr    # pop and square and push
  swap   # swap two stack elements
  sqr    # pop and square and push
  add    # pop and pop and add and push
  pushA  # push original argument
  equal  # equality test 0/1
  popAddZ  # Z := Z + pop
endwhile
pushZ    # push Z onto stack, will be output to stdout on termination

2

CJam,28岁

qi_mF{3a>},{~)\4%2-&}%4+:*1?

不是很短,但是很有效。例如15625的结果立即为28。使用OEIS中基于因式分解的公式。
在线尝试

说明:

qi       read input and convert to integer
_        make a copy (will be used to handle the 0 case at the end)
mF       factorize into [prime exponent] pairs
{…},     filter the array of pairs
  3a>    with the condition that the pair is greater than [3]
          which means the prime factor must be ⩾3
{…}%     transform each pair as follows:
  ~      dump the prime factor and exponent onto the stack
  )      increment the exponent
  \      swap with the prime
  4%     get the remainder mod 4 (it will be 1 or 3)
  2-     subtract 2 (resulting in -1 or 1)
  &      bitwise AND with the incremented exponent (see below)
4+       append a 4 to the array
:*       multiply all
1?       if the input was 0, use 1, else use the above result

有关计算的一些详细信息:

  • 如果素数是1 mod 4,则代码​​将计算 (exponent + 1) & -1,即exponent + 1
  • 如果素数是3 mod 4,则代码​​将计算(exponent + 1) & 1,如果指数是奇数,则为0,如果是偶数,则为1

所有这些值相乘并乘以4就是OEIS公式。


2

Python 2,68个字节

def x(n):r=range(-n,n+1);print sum(a*a+b*b==n for a in r for b in r)

定义一个称为 x() n。

在线尝试。 http://ideone.com/aRoxGF


您缺少printreturn语句。
Zgarb 2015年

谢谢,我完全忘了。该链接虽然具有打印语句。我在编写代码时编辑了代码。
Rɪᴋᴇʀ

好的不用担心。但这似乎也为n=0和提供错误的结果n=1(0和2代替1和4)。也许范围限制需要调整?
Zgarb

@Zgarb是的,他们应该以结尾n+1
lirtosiast

1
我会寻找。
Rɪᴋᴇʀ

2

Pyth,41 35 33 30 27字节

在线尝试。

编辑:感谢isaacg,我m*F工作!是!

?Q*F+4m.&tt%ed4hhdr-PQ2 8 1
                                (implicit) Q = input()
?Q                              If Q != 0
      m                           Map to d (exponent, prime) from ...
                  r-PQ2 8         run-length-encoded(PQ with 2's removed)
       .&                           Bitwise and
           %ed4                       d[-1] % 4
         tt                           -2
                hd                  with d[0]
               h                      +1
    +4                            Append 4 to the resulting array
  *F                              Then multiply it all together
                          1     Else 1

编辑:按位放回以节省更多字节!我也删除了所有“以前”的东西。它开始变得混乱。

感谢aittsu和他的CJam解决方案,以及maltysen和他的技巧(有一天我会m*Fd上班。有一天...)

J4Vr-PQ2 8=J*J.&tt%eN4hhN;?QJ1
                                (implicit) Q=input()
J4                              J=4
    -PQ2                        Remove all 2's from the prime factorization of Q
   r     8                      run-length encode (exponent, prime factor)
  V                      ;      For N in range( the above ):
          =J*J                      J = J * ...
                tt%eN4                N[-1] mod 4 -2 
                      hhN             (exponent + 1)
              .&                    bitwise and
                          ?QJ1  if Q != 0 print(J) else print(1)

注意,

  • 如果素数是1 mod 4,我们得到-1 & (exponent + 1),即exponent + 1

  • 但是如果素数是3 mod 4,我们得到1 & (exponent + 1),即0指数是奇数,1甚至是

将它们全部相乘(在开始时乘以4),我们得到两个平方的和数加到我们的输入中。


2

Python,57个字节

很好的挑战。不幸的是,我现在没有比这更短的时间了。

lambda n:0**n+sum(2-d%4for d in range(1,n+1)if d%2>n%d)*4

2

PARI / GP,34个 28字节

使用生成函数:

多亏了Mitch Schwartz节省了6个字节。

n->sum(i=-n,n,x^i^2)^2\x^n%x

使用内置的33个字节(由于Mitch Schwartz节省了1个字节):

n->if(n,2*qfrep(matid(2),n)[n],1)

qfrep(q,B,{flag = 0}):向量的(一半)是整数和定二次数q的从1到B的范数的向量。如果flag为1,则计数从1到2B的偶范数的向量。



matid(2)保存一个字节。
米奇·施瓦兹

1
生成函数方法降至28:n->sum(i=-n,n,x^i^2)^2\x^n%x
Mitch Schwartz


1

Matlab,63 50字节

@(y)nnz(~mod(sqrt(y-power((1:sqrt(y)),2)),1))*4+~y

  • 这确实击败了其他相同的授权代码,因此我将其命名为:D。

  • 程序将找到正整数解,然后乘以4以包含负整数。

  • 它可以执行所有25个第一个测试用例

    for i=1:25 ans(i)
    end
    
       1
    
       4
    
       4
    
       0
    
       4
    
       8
    
       0
    
       0
    
       4
    
       4
    
       8
    
       0
    
       0
    
       8
    
       0
    
       0
    
       4
    
       8
    
       4
    
       0
    
       8
    
       0
    
       0
    
       0
    
       0
    
       12
    


谢谢@StewieGriffin我确实将它包括在与路易斯一号有关的公平竞赛中
Abr001am 2015年

提示:当您打算发布MATLAB的结果时,请使用format compact=)
Stewie Griffin

1

JavaScript,89个字节

n=prompt()
p=Math.pow
for (x=c=(+n?0:1);x<=n;x++)if(x&&p(n-p(x,2),.5)%1===0)c+=4
alert(c)

我知道即使我要删除I / O行,这也不是最短的JavaScript答案,但我确实认为这是性能最好的JS答案,它在几秒钟内为我提供了一百万的结果(一千万花费了大约分钟)。


您可以使用==代替===吗?
lirtosiast

我可以,只要使用最佳做法,哈哈。
亚当·达利

1

PHP,70字节,不竞争

for($x=-1;$x++<=$n=$argv[1];)$s+=(-($n%($x-~$x)<1))**$x*4;echo$n?$s:1;

从一个Python答案中盗取的算法...我忘记了哪一个;我想在发布之前至少部分了解正在发生的事情。


for(;$x<=$n=$argv[1];)$s+=(-($n%(2*$x+1)<1))**$x++*4;echo$n?$s:1;节省5个字节。$x-~$x等于2*$x+1,您现在就可以开始而不分配变量。
约尔格Hülsermann
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.