Code-Golf: Points de réseau à l'intérieur d'un cercle

15

L'image suivante montre le problème:

entrez la description de l'image ici

Écrivez une fonction qui, étant donné un entier comme rayon du cercle, calcule le nombre de points de réseau à l'intérieur du cercle centré (y compris la frontière).

L'image montre:

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

autres valeurs pour votre vérification / débogage:

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

Devrait avoir une performance raisonnable. Disons moins d'une minute pour f [1000].

Le code le plus court gagne. Les règles habituelles du Code-Golf s'appliquent.

Veuillez poster le calcul et le timing de f [1001] comme exemple.

Dr. belisarius
la source
4
oeis.org/A328
msh210
Version triangulaire .
user202729

Réponses:

9

J, 21 19 18

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

Construit des complexes de -x-xj à x + xj et prend de l'ampleur.

Modifier: avec >:

Edit 2: Avec crochet et monadique ~. Fonctionne quelques fois plus lentement pour une raison quelconque, mais reste 10 secondes pour f (1000).

Jesse Millikan
la source
Oh hé, je ne savais pas i:, je vole tellement que, merci!
JB
@JB: Ouais, eh bien ... je vole >:. derp
Jesse Millikan
J'aimerais bien comprendre les majuscules assez bien pour les voler aussi O :-)
JB
Cette réponse est tristement courte (pour quelqu'un qui n'a jamais pris la peine d'apprendre une langue courte et / ou golfique) >:. Mais bon, c'est une bonne réponse! :)
Action en justice de Fund Monica
5

J, 27 21

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

Très brutal: calcule sqrt (x² + y²) sur la plage [-n, n] et compte les éléments ≤n . Temps encore très acceptable pour 1000.

Edit : i:yest un peu plus court que y-i.>:+:y. Merci Jesse Millikan !

JB
la source
Ha! C'était l'idée derrière demander une performance décente! Juste curieux: quel est le timing pour 1000?
Dr belisarius
1
@belisarius: 0,86 s. Sur du matériel vieux de 10 ans. 3,26 s pour 2000.
JB
4

Ruby 1.9, 62 58 54 caractères

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

Exemple:

f[1001]
=> 3147833

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

Python 55 caractères

f=lambda n:1+4*sum(int((n*n-i*i)**.5)for i in range(n))
fR0DDY
la source
f=lambda n:1+4*sum(int((n*n-i*i)**.5)for i in range(n))est de 17 caractères plus court.
Ventero
3

Haskell, 41 octets

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

Compte les points dans le quadrant x>=0, y>0, multiplie par 4, ajoute 1 pour le point central.

xnor
la source
2

Haskell, 44 octets

f n|w<-[-n..n]=sum[1|x<-w,y<-w,x*x+y*y<=n*n]
Damien
la source
Je suis nouveau chez Haskell: comment pouvez-vous écrire w<-[-n..n]où (généralement) il y a une valeur booléenne?
flawr
1
@flawr Ce sont des protections de motif qui réussissent si un motif est apparié, mais qui peuvent être utilisées en golf comme une location plus courte. Voir cette astuce .
xnor
Merci, je n'étais pas au courant de ce fil!
flawr
1

JavaScript (ES6), 80 octets (non concurrent car ES6 est trop nouveau)

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

Version alternative, également 80 octets:

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

Version ES7, également 80 octets:

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

Python 2, 48 octets

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

Comme la solution de fR0DDY , mais récursive, et renvoie un flottant. Le retour d'un int est de 51 octets:

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

C (gcc) , 60 octets

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

Essayez-le en ligne!

Boucle sur le premier quadrant, multiplie le résultat par 4 et en ajoute un. Un peu moins golfé

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

APL (Dyalog Extended) , 14 octets

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

Essayez-le en ligne!

Malgré l'absence de la i:gamme intégrée (de -n à n) de J, APL Extended a une syntaxe plus courte dans d'autres domaines.

{≢⍸⍵≥|⌾⍀⍨⍵…-⍵}            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
la source
1

Japt -x , 12 octets

òUn)ï Ëx²§U²

Essayez-le en ligne!

Explication:

ò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
la source
1
12 octets
Shaggy
1

PHP, 85 83 octets

Le code:

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

Son résultat (consultez https://3v4l.org/bC0cY pour plusieurs versions PHP):

f(1001)=3147833
time=0.000236 seconds.

Le code non golfé:

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

Une implémentation naïve qui vérifie les $n*($n+1)points (et s'exécute 1000 plus lentement mais calcule toujours f(1001)en moins de 0,5 seconde) et la suite de tests (en utilisant les données d'exemple fournies dans la question) peuvent être trouvées sur github .

axiaque
la source
0

Clojure / ClojureScript, 85 caractères

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

Brute force le premier quadrant, y compris l'axe y mais pas l'axe x. Génère un 4 pour chaque point, puis les ajoute avec 1 pour l'origine. Fonctionne en moins de 2 secondes pour une entrée de 1000.

Abuse l'enfer forpour définir une variable et enregistrer quelques caractères. Faire la même chose pour créer un alias pour rangen'enregistre aucun caractère (et le rend beaucoup plus lent), et il semble peu probable que vous allez enregistrer quoi que ce soit en créant une fonction carrée.

MattPutnam
la source
C'est une question assez ancienne, êtes-vous sûr que cette réponse aurait fonctionné à l'époque?
Bleu
@muddyfish Je n'ai pas remarqué l'âge, je l'ai vu près du sommet. Clojure est antérieur à la question, mais je ne connais pas suffisamment son histoire pour connaître les changements de langue.
MattPutnam
0

Pyke, 14 octets, non concurrent

QFXQX-_,B)s}}h

Essayez-le ici!

Bleu
la source
0

Mathematica, 35 caractères

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

Tiré de https://oeis.org/A000328

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

SquaresR[2,k]est le nombre de façons de représenter k comme la somme de deux carrés, ce qui est le même que le nombre de points de réseau sur un cercle de rayon k ^ 2. Somme de k = 0 à k = n ^ 2 pour trouver tous les points sur ou à l'intérieur d'un cercle de rayon n.

Sparr
la source
1
2~SquaresR~k~Sum~{k,0,#^2}&pour le raccourcir
jaeyong chanté le
0

Tcl, 111 octets

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

Boucle x discrète simple sur le quadrant I, comptant le plus grand y en utilisant le théorème de Pythagore à chaque étape. Le résultat est 4 fois la somme plus un (pour le point central).

La taille du programme dépend de la valeur de r . Remplacez {1001 0 -1}par "$argv 0 -1"et vous pouvez l'exécuter avec n'importe quelle valeur d'argument de ligne de commande pour r .

Calcule f (1001) → 3147833.0en environ 1030 microsecondes, processeur 64 bits AMD Sempron 130 2,6 GHz, Windows 7.

De toute évidence, plus le rayon est grand, plus l'approximation de PI: f (10000001) s'exécute en environ 30 secondes, produisant une valeur à 15 chiffres, ce qui correspond à la précision d'un double IEEE.

Dúthomhas
la source