代码高尔夫:圆内的晶格点


15

下图显示了该问题:

在此处输入图片说明

编写一个函数,给定一个整数作为圆半径,该函数计算中心圆(包括边界)内的晶格点数。

该图显示:

f[1] = 5  (blue points)
f[2] = 13 (blue + red points)  

用于检查/调试的其他值:

f[3]    = 29
f[10]   = 317
f[1000] = 3,141,549
f[2000] = 12,566,345  

应该有合理的表现。假设f [1000]不到一分钟。

最短的代码获胜。通常使用Code-Golf规则。

请以f [1001]的计算和时序为例。



Answers:


9

J,21 19 18

+/@,@(>:|@j./~@i:)

建立从-x-xj到x + xj的复合体并取幅值。

编辑:与 >:

编辑2:带钩子和monadic ~。由于某种原因,运行速度慢了几倍,但f(1000)仍然要慢10秒钟。


哦,嘿,我不知道i:,我偷了,谢谢!
JB

@JB:是的,嗯...我在偷东西>:derp
Jesse Millikan

我希望我能很好地理解帽子以至于也可以偷那些帽子O :-)
JB

这个答案令人沮丧地简短(对于从来没有想要学习简短和/或打高尔夫球的人来说)>:。但是,嘿,这是一个很酷的答案!:)
基金莫妮卡的诉讼

5

J,27 21

3 :'+/,y>:%:+/~*:i:y'

非常残酷:在[-n,n]范围内计算sqrt(x²+y²)并计数≤n的项。仍然非常可接受的时间为1000。

编辑i:yy-i.>:+:y。谢谢杰西·米利坎(Jesse Millikan)


哈!那就是要求表现出色的想法!只是好奇:1000的时机是什么?
belisarius博士2011年

1
@belisarius:0.86秒。使用10年的旧硬件。2000
JB

4

Ruby 1.9, 62 58 54个字符

f=->r{1+4*eval((0..r).map{|i|"%d"%(r*r-i*i)**0.5}*?+)}

例:

f[1001]
=> 3147833

t=Time.now;f[1001];Time.now-t
=> 0.003361411

4

Python 55个字符

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

f=lambda n:1+4*sum(int((n*n-i*i)**.5)for i in range(n))短17个字符。
Ventero 2011年

3

Haskell,41个字节

f n=1+4*sum[floor$sqrt$n*n-x*x|x<-[0..n]]

计算象限中的点x>=0, y>0,乘以4,将1加到中心点。


2

Haskell,44个字节

f n|w<-[-n..n]=sum[1|x<-w,y<-w,x*x+y*y<=n*n]

我是Haskell的新手:您如何写w<-[-n..n](通常)有布尔值的地方?
瑕疵的

1
@flawr这些是花样后卫,如果匹配了花样,则将成功,但可以在打高尔夫球时用作较短的出手。看到这个技巧
xnor

谢谢,我不知道这个线程!
瑕疵的

1

JavaScript(ES6),80字节(非竞争,因为ES6太新了)

n=>(a=[...Array(n+n+1)].map(_=>i--,i=n)).map(x=>a.map(y=>r+=x*x+y*y<=n*n),r=0)|r

备用版本,也为80字节:

n=>[...Array(n+n+1)].map((_,x,a)=>a.map((_,y)=>r+=x*x+(y-=n)*y<=n*n,x-=n),r=0)|r

ES7版本,也是80个字节:

n=>[...Array(n+n+1)].map((_,x,a)=>a.map((_,y)=>r+=(x-n)**2+(y-n)**2<=n*n),r=0)|r

1

Python 2,48个字节

f=lambda n,i=0:i>n or(n*n-i*i)**.5//1*4+f(n,i+1)

类似于fR0DDY的solution,但是是递归的,并返回浮点数。返回一个int是51个字节:

f=lambda n,i=0:i>n or 4*int((n*n-i*i)**.5)+f(n,i+1)

1

C(gcc),60个字节

r,a;f(x){for(a=r=x*x;a--;)r-=hypot(a%x+1,a/x)>x;x=4*r+1;}

在线尝试!

在第一个象限上循环,将结果乘以4,然后加一个。少打高尔夫球

r,a;
f(x){
  for(a=r=x*x;a--;)
    r-=hypot(a%x+1,a/x)>x;
  x=4*r+1;
}

1

APL(Dyalog扩展),14字节

{≢⍸⍵≥|⌾⍀⍨⍵…-⍵}

在线尝试!

尽管缺少i:J的内置(从-n到n的范围),APL Extended在其他方面的语法更短。

{≢⍸⍵≥|⌾⍀⍨⍵…-⍵}            Monadic function taking an argument n.
           ⍵…-⍵             n, n-1, ..., -n
      ⌾⍀                   Make a table of complex numbers
                            (equivalent to ∘.{⍺+1J×⍵} in Dyalog APL)
                           with both real and imaginary parts from that list.
      |                       Take their magnitudes.
    ⍵≥                        1 where a magnitude are is at most n, and 0 elsewhere.
                            Get all indices of truthy values.
                            Find the length of the resulting list.

1

Japt -x,12个字节

òUn)ï Ëx²§U²

在线尝试!

说明:

òUn)            #Get the range [-input ... input]
    ï           #Get each pair of numbers in that range
      Ë         #For each pair:
       x        # Get the sum...
        ²       # Of the squares
         §      # Check if that sum is less than or equal to...
          U²    # The input squared
                #Output the number of pairs that passed the check


1

PHP,85 83字节

代码:

function f($n){for($x=$n;$x;$c+=$x,$y++)for(;$n*$n<$x*$x+$y*$y;$x--);return$c*4+1;}

结果(检查多个PHP版本的https://3v4l.org/bC0cY):

f(1001)=3147833
time=0.000236 seconds.

未经处理的代码:

/**
 * Count all the points having x > 0, y >= 0 (a quarter of the circle)
 * then multiply by 4 and add the origin.
 *
 * Walk the lattice points in zig-zag starting at ($n,0) towards (0,$n), in the
 * neighbourhood of the circle. While outside the circle, go left.
 * Go one line up and repeat until $x == 0.
 * This way it checks about 2*$n points (i.e. its complexity is linear, O(n))
 *
 * @param int $n
 * @return int
 */
function countLatticePoints2($n)
{
    $count = 0;
    // Start on the topmost right point of the circle ($n,0), go towards the topmost point (0,$n)
    // Stop when reach it (but don't count it)
    for ($y = 0, $x = $n; $x > 0; $y ++) {
        // While outside the circle, go left;
        for (; $n * $n < $x * $x + $y * $y; $x --) {
            // Nothing here
        }
        // ($x,$y) is the rightmost lattice point on row $y that is inside the circle
        // There are exactly $x lattice points on the row $y that have x > 0
        $count += $x;
    }
    // Four quarters plus the center
    return 4 * $count + 1;
}

可以在github上找到一个检查$n*($n+1)点的天真的实现(运行速度慢了1000个,但仍然可以f(1001)在0.5秒内完成计算)和测试套件(使用问题中提供的示例数据)。


0

Clojure / ClojureScript,85个字符

#(apply + 1(for[m[(inc %)]x(range 1 m)y(range m):when(<=(+(* x x)(* y y))(* % %))]4))

蛮力强制第一象限,包括y轴但不包括x轴。为每个点生成一个4,然后将它们与1相加。在2秒内运行,输入1000。

滥用地狱for来定义变量并保存一些字符。进行相同的操作以为其创建别名range不会保存任何字符(并使它的运行明显变慢),并且似乎不太可能通过制作平方函数来保存任何内容。


这是一个很老的问题,您确定这个答案在当时会奏效吗?
蓝色

@muddyfish我没有注意到年龄,只是在顶部附近看到了。Clojure早于该问题,但我对它的历史了解不足以了解语言变化。
MattPutnam '16



0

Tcl,111个字节

lassign {1001 0 -1} r R x
while {[incr x]<$r} {set R [expr {$R+floor(sqrt($r*$r-$x*$x))}]}
puts [expr {4*$R+1}]

简单的离散x在象限I上循环,在每一步使用勾股定理计算最大y。结果是总和的4倍加1(对于中心点)。

程序的大小取决于r的值。替换为{1001 0 -1}"$argv 0 -1"然后可以使用r的任何命令行参数值运行它。

3147833.0在约1030微秒内计算f(1001)→ ,AMD Sempron 130 2.6GHz 64位处理器,Windows 7。

显然,半径越大,与PI的近似值越接近:f(10000001)在大约30秒钟内运行,产生15位数字的值,大约是IEEE精度的两倍。


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.