코드-골프 : 원 안의 격자 점


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]에 대해 1 분 미만이라고합시다.

가장 짧은 코드가 승리합니다. 일반적인 코드 골프 규칙이 적용됩니다.

예를 들어 f [1001]의 계산 및 타이밍을 게시하십시오.



답변:


9

J, 21 19 18

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

-x-xj에서 x + xj까지의 컴플렉스를 빌드하고 크기를 사용합니다.

편집 : >:

편집 2 : hook 및 monadic 사용 ~. 어떤 이유로 든 몇 배 느리게 실행되지만 f (1000)의 경우 여전히 10 초입니다.


어이, 나는 몰랐다 i:, 나는 너무 도둑질, 감사합니다!
JB

@JB : 응, 음 ... 나는 훔치고있다 >:. derp
제시 Millikan

모자를 훔치기에 충분한 캡을 이해했으면 좋겠다 O :-)
JB

이 답변은 매우 짧습니다 (짧거나 골프 랭귀지를 배우려고하지 않은 사람에게) >:. 그러나 이건 멋진 답변입니다! :)
기금 모니카의 소송

5

J, 27 21

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

매우 잔인 함 : [-n, n] 범위에서 sqrt (x² + y²) 를 계산하고 항목 ≤n을 계산합니다 . 여전히 1000에 허용되는 시간입니다.

편집 : i:y보다 약간 짧습니다 y-i.>:+:y. 제시 Millikan 감사합니다 !


하아! 그것은 적절한 성능을 요구하는 배후의 아이디어였습니다! 그냥 궁금해서 : 1000의 타이밍은 무엇입니까?
Dr. belisarius

1
@ 벨리 사리우스 : 0.86 초. 10 년 된 하드웨어 2000 년 3.26 초.
JB

4

루비 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

파이썬 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

3

하스켈, 41 바이트

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

사분면의 점을 세고 4 x>=0, y>0를 곱하면 중심점이 1이됩니다.


2

하스켈, 44 바이트

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

Haskell을 처음 사용합니다. w<-[-n..n]부울 값이있는 위치를 어떻게 작성할 수 있습니까?
flawr

1
@flawr 이들은 패턴 가드로 , 패턴이 일치하면 성공하지만 더 짧은 let으로 골프에 사용할 수 있습니다. 이 팁을 참조하십시오 .
xnor

고마워, 나는이 스레드를 몰랐다!
flawr

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

파이썬 2, 48 바이트

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

마찬가지로 fR0DDY의 솔루션 ,하지만 재귀, 반환 부동. int를 반환하는 것은 51 바이트입니다.

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


1

APL (Dyalog Extended) , 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

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.

ungolfed 코드 :

/**
 * 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;
}

$n*($n+1)포인트 를 확인 하고 1000 f(1001)초 느리게 실행하지만 여전히 0.5 초 미만으로 계산 하는 순진한 구현 과 테스트 스위트 (질문에 제공된 샘플 데이터 사용)는 github 에서 찾을 수 있습니다 .


0

Clojure / ClojureScript, 85 자

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

Brute는 x 축이 아닌 y 축을 포함하여 1 사분면을 강제합니다. 모든 점에 대해 4를 생성 한 다음 원점에 대해 1을 더합니다. 1000을 입력하기 위해 2 초 이내에 실행됩니다.

for변수를 정의하고 몇 개의 문자를 저장하기 위해 지옥을 남용합니다 . 별칭을 만들기 위해 동일하게 range수행해도 문자가 저장되지 않으며 (더 느리게 실행) 사각형 기능을 만들어서 아무것도 저장하지 않을 것 같습니다.


이것은 꽤 오래된 질문입니다.이 답변이 당시에 효과가 있었을 것입니까?
Blue

@ muddyfish 나는 나이를 눈치 채지 못했고, 정상 근처에서 보았습니다. Clojure가 질문보다 오래되었지만 언어 변경에 대해 알 수있는 역사를 모르겠습니다.
MattPutnam



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각 단계에서 피타고라스 정리를 사용하여 최대 y 를 계산하는 사분면 I에 대한 루프 . 결과는 합의 4 배에 1을 더한 것 (중심점)입니다.

프로그램의 크기는 r 값에 따라 다릅니다 . 교체 {1001 0 -1}"$argv 0 -1" 당신은에 대한 명령 줄 인수 값으로 실행할 수 있습니다 R .

f (1001) 계산 → 3147833.0 약 1030 마이크로 초, AMD Sempron 130 2.6GHz 64 비트 프로세서, Windows 7로 계산합니다.

명백하게, 반경이 클수록 PI에 대한 근사치가 PI에 더 가깝습니다. f (10000001)은 약 30 초 내에 실행되어 15 자리 값을 생성하는데 이는 IEEE 배정도의 정밀도입니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.