Code-Golf: Gitterpunkte innerhalb eines Kreises

15

Das folgende Bild zeigt das Problem:

Bildbeschreibung hier eingeben

Schreiben Sie eine Funktion, die mit einer Ganzzahl als Kreisradius die Anzahl der Gitterpunkte innerhalb des zentrierten Kreises (einschließlich der Grenze) berechnet .

Das Bild zeigt:

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

andere Werte für das Prüfen / Debuggen:

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

Sollte eine angemessene Leistung haben. Sagen wir weniger als eine Minute für f [1000].

Kürzester Code gewinnt. Es gelten die üblichen Code-Golf-Regeln.

Bitte geben Sie die Berechnung und das Timing von f [1001] als Beispiel an.

Dr. belisarius
quelle
4
oeis.org/A328
msh210
Dreieckige Version .
user202729

Antworten:

9

J, 21, 19, 18

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

Bildet Komplexe von -x-xj bis x + xj und nimmt die Größe an.

Edit: Mit >:

Edit 2: Mit Hook und Monadic ~. Läuft aus irgendeinem Grund ein paar Mal langsamer, aber immer noch 10 Sekunden für f (1000).

Jesse Millikan
quelle
Oh hey, ich wusste nicht , i:ich bin so , dass Diebstahl, danke!
JB
@JB: Ja, nun ... ich klaue >:. derp
Jesse Millikan
Ich wünschte, ich hätte Kappen gut genug verstanden, um diese auch zu stehlen O :-)
JB
Diese Antwort ist deprimierend kurz (für jemanden, der sich nie die Mühe gemacht hat, eine kurze und / oder Golf-Sprache zu lernen) >:. Aber hey, das ist eine coole Antwort! :)
Fund Monica Klage
5

J 27, 21

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

Sehr brutal: Berechnet sqrt (x² + y²) über den Bereich [-n, n] und zählt Elemente ≤n . Immer noch sehr akzeptable Zeiten für 1000.

Bearbeiten :i:y ist ziemlich viel kürzer als y-i.>:+:y. Danke Jesse Millikan !

JB
quelle
Ha! Das war die Idee, um eine anständige Leistung zu bitten! Nur neugierig: Was ist der Zeitpunkt für 1000?
Dr. Belisarius
1
@belisarius: 0,86 s. Auf 10 Jahre alter Hardware. 3,26s für 2000.
JB
4

Ruby 1.9, 62 58 54 Zeichen

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

Beispiel:

f[1001]
=> 3147833

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

Python 55 Zeichen

f=lambda n:1+4*sum(int((n*n-i*i)**.5)for i in range(n))
fR0DDY
quelle
f=lambda n:1+4*sum(int((n*n-i*i)**.5)for i in range(n))ist 17 Zeichen kürzer.
Ventero
3

Haskell, 41 Bytes

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

Zählt Punkte im Quadranten x>=0, y>0, multipliziert mit 4 und addiert 1 für den Mittelpunkt.

xnor
quelle
2

Haskell, 44 Bytes

f n|w<-[-n..n]=sum[1|x<-w,y<-w,x*x+y*y<=n*n]
Damien
quelle
Ich bin neu in Haskell: Wie kann man schreiben, w<-[-n..n]wo (normalerweise) ein boolescher Wert ist?
Fehler
1
@flawr Dies sind Pattern Guards , die erfolgreich sind, wenn ein Pattern übereinstimmt, aber beim Golfen als Short-Let verwendet werden können. Siehe diesen Tipp .
xnor
Danke, mir war dieser Thread nicht bekannt!
Fehler
1

JavaScript (ES6), 80 Byte (nicht konkurrierend, da ES6 zu neu ist)

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

Alternative Version, auch 80 Bytes:

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-Version, auch 80 Bytes:

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

Python 2, 48 Bytes

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

Wie die Lösung von fR0DDY , aber rekursiv, und gibt einen Float zurück. Die Rückgabe eines Int ist 51 Bytes:

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

C (gcc) , 60 Bytes

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

Probieren Sie es online!

Durchläuft den ersten Quadranten, multipliziert das Ergebnis mit 4 und addiert eins. Etwas weniger golfen

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

APL (Dyalog Extended) , 14 Byte

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

Probieren Sie es online!

Obwohl i:der in J integrierte (inklusive Bereich von -n bis n) fehlt, hat APL Extended in anderen Bereichen eine kürzere Syntax.

{≢⍸⍵≥|⌾⍀⍨⍵…-⍵}            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.
Lirtosiast
quelle
1

Japt -x , 12 Bytes

òUn)ï Ëx²§U²

Probieren Sie es online!

Erläuterung:

ò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
Kamil Drakari
quelle
1
12 Bytes
Shaggy
1

PHP, 85 83 Bytes

Der Code:

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

Das Ergebnis (siehe https://3v4l.org/bC0cY für mehrere PHP-Versionen):

f(1001)=3147833
time=0.000236 seconds.

Der ungolfed Code:

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

Eine naive Implementierung, die $n*($n+1)Punkte überprüft (und 1000 f(1001)Sekunden langsamer ausgeführt wird, aber dennoch in weniger als 0,5 Sekunden berechnet wird ), und die Testsuite (unter Verwendung der in der Frage angegebenen Beispieldaten) finden Sie auf github .

Axiac
quelle
0

Clojure / ClojureScript, 85 Zeichen

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

Brute erzwingt den ersten Quadranten einschließlich der y-Achse, aber nicht der x-Achse. Erzeugt eine 4 für jeden Punkt und addiert sie dann mit 1 für den Ursprung. Läuft in weniger als 2 Sekunden für die Eingabe von 1000.

Missbraucht die Hölle, forum eine Variable zu definieren und ein paar Zeichen zu speichern. Wenn Sie dasselbe tun, um einen Alias ​​für zu erstellen range, werden keine Zeichen gespeichert (und die Ausführung wird erheblich verlangsamt), und es ist unwahrscheinlich, dass Sie durch die Erstellung einer quadratischen Funktion etwas speichern werden.

MattPutnam
quelle
Dies ist eine ziemlich alte Frage, sind Sie sicher, dass diese Antwort zu der Zeit funktioniert hätte?
Blau
@muddyfish Ich habe das Alter nicht bemerkt, sah es nur in der Nähe der Spitze. Clojure geht der Frage voraus, aber ich kenne seine Geschichte nicht genug, um über Sprachänderungen Bescheid zu wissen.
MattPutnam
0

Mathematica, 35 Zeichen

f[n_]:=Sum[SquaresR[2,k],{k,0,n^2}]

Aufgehoben von https://oeis.org/A000328

https://reference.wolfram.com/language/ref/SquaresR.html

SquaresR[2,k]ist die Anzahl der Möglichkeiten, k als Summe von zwei Quadraten darzustellen, was der Anzahl der Gitterpunkte auf einem Kreis mit dem Radius k ^ 2 entspricht. Summiere von k = 0 bis k = n ^ 2, um alle Punkte auf oder innerhalb eines Kreises mit dem Radius n zu finden.

Sparr
quelle
1
2~SquaresR~k~Sum~{k,0,#^2}&um es kürzer zu machen
Jaeyong gesungen
0

Tcl, 111 Bytes

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}]

Einfache diskrete x- Schleife über Quadrant I, wobei bei jedem Schritt das größte y nach dem Satz von Pythagoras gezählt wird. Das Ergebnis ist das 4-fache der Summe plus eins (für den Mittelpunkt).

Die Größe des Programms hängt vom Wert von r ab . Ersetzen Sie {1001 0 -1}durch "$argv 0 -1"und Sie können es mit jedem Befehlszeilenargumentwert für r ausführen .

Berechnet f (1001) → 3147833.0in ungefähr 1030 Mikrosekunden, AMD Sempron 130 2,6-GHz-64-Bit-Prozessor, Windows 7.

Je größer der Radius ist, desto näher läuft die Annäherung an PI: f (10000001) in ungefähr 30 Sekunden und ergibt einen 15-stelligen Wert, der ungefähr der Genauigkeit eines IEEE-Double entspricht.

Dúthomhas
quelle