El círculo de unidades cuadradas pasa a través

24

Escriba un programa o función que, dado un radio entero r, devuelva el número de cuadrados unitarios que atraviesa el círculo con radio r centrado en el origen. Si el círculo pasa exactamente a través de un punto en la cuadrícula que no cuenta como pasar a través de los cuadrados de las unidades adyacentes.

Aquí hay una ilustración para r = 5 :

ilustración Ilustración de Kival Ngaokrajang, encontrada en OEIS

Ejemplos:

0 → 0
1 → 4
4 → 28
5 → 28
49 → 388
50 → 380
325 → 2540
5524 → 44180
5525 → 44020

orlp
fuente
@Luke Acabo de buscar esto, pero parece usar una definición ligeramente diferente (al menos no está de acuerdo N = 50).
Martin Ender
1
@smls Contando en el cuadro delimitador. Asegúrate de no contar cuadrados donde el círculo solo toque una esquina. Los números en OEIS están equivocados, tengo una corrección en revisión en este momento.
orlp
2
Tengo una repentina urgencia de volver a construir cúpulas en Minecraft ...
Patrick Roberts
2
¿Eres un espectador compañero de 3Blue1Brown?
nitro2k01

Respuestas:

12

Python 2 , 54 bytes

f=lambda r,x=0:r-x and-~((r*r-x*x)**.5%1>0)*4+f(r,x+1)

Pruébalo en línea!

Menos golf (55 bytes) ( TIO )

lambda r:8*r-4*sum((r*r-x*x)**.5%1==0for x in range(r))

Esto estima la salida como 8*r, luego corrige los cruces de vértices. El resultado es 8*r-g(r*r), donde g(x)cuenta el número de formas de escribir xcomo una suma de dos cuadrados (excepto g(0)=0).

Si el círculo nunca atravesara ningún vértice, el número de celdas tocadas sería igual al número de bordes cruzados. El círculo pasa a través de 2*rlíneas verticales y 2*rhorizontales, pasando cada una en ambas direcciones, para un total de 8*r.

Pero, cada cruce en un vértice cuenta como dos cruces de borde mientras solo ingresa a una nueva celda. Entonces, compensamos restando el número de cruces de vértices. Esto incluye los puntos en ejes (r,0)como así como triples pitagóricos como (4,3)para r=5.

Contamos para un solo cuadrante los puntos (x,y)con x>=0y y>0con x*x+y*y==n, luego multiplicamos por 4. Hacemos esto contando los sqrt(r*r-x*x)números que son números enteros xen el intervalo [0,r).

xnor
fuente
5

Mathematica, 48 bytes

4Count[Range@#~Tuples~2,l_/;Norm[l-1]<#<Norm@l]&

Mira el primer cuadrante y cuenta el número de celdas de la cuadrícula para las cuales la entrada cae entre las normas de las esquinas inferiores izquierda y superior derecha de la celda (por supuesto, multiplicando el resultado por 4).

Martin Ender
fuente
Otro método se 8#-SquaresR[2,#^2]Sign@#&basa en la publicación de xnor
millas del
@miles Oh wow, no tenía ni idea SquaresR. Siéntase libre de publicarlo usted mismo (o deje que xnor lo publique).
Martin Ender
3

Jalea , 21 13 12 11 bytes

R²ạ²Æ²SạḤ×4

Pruébalo en línea!

Cómo funciona

R²ạ²Æ²SạḤ×4  Main link. Argument: r

R            Range; yield [1, 2, ..., r].
 ²           Square; yield [1², 2², ..., r²].
   ²         Square; yield r².
  ạ          Absolute difference; yield [r²-1², r²-2², ..., r²-r²].
    Ʋ       Test if each of the differences is a perfect square.
      S      Sum, counting the number of perfect squares and thus the integer
             solutions of the equation x² + y² = r² with x > 0 and y ≥ 0.
        Ḥ    Un-halve; yield 2r.
       ạ     Subtract the result to the left from the result to the right.
         ×4  Multiply by 4.
Dennis
fuente
2

Perl 6, 61 bytes

->\r{4*grep {my &n={[+] $_»²};n(1 X+$_)>r²>.&n},(^r X ^r)}

Cómo funciona

->\r{                                                    } # Lambda (accepts the radius).
                                                (^r X ^r)  # Pairs from (0,0) to (r-1,r-1),
                                                           #   representing the bottom-left
                                                           #   corners of all squares in
                                                           #   the top-right quadrant.
       grep {                                 }            # Filter the ones matching:
             my &n={[+] $_»²};                             #   Lambda to calculate the norm.
                              n(1 X+$_)>r²                 #   Top-right corner is outside,
                                          >.&n             #   and bottom-left is inside.
     4*                                                    # Return length of list times 4.
smls
fuente
1

AWK, 90 bytes

{z=$1*$1
for(x=$1;x>=0;x--)for(y=0;y<=$1;y++){d=z-x*x-y*y
if(d>0&&d<2*(x+y)+2)c++}$0=4*c}1

Uso:

awk '{z=$1*$1
    for(x=$1;x>=0;x--)for(y=0;y<=$1;y++){d=z-x*x-y*y
    if(d>0&&d<2*(x+y)+2)c++}$0=4*c}1' <<< 5525

Solo una simple búsqueda a través del cuadrante 1 para encontrar todos los cuadros que se cruzarán con el círculo. La simetría permite la multiplicación por 4. Podría pasar de -$1 to $1, pero eso tomaría más bytes y sería menos eficiente. Obviamente, este no es el algoritmo más eficiente en tiempo, pero solo lleva unos 16 segundos ejecutar el caso 5525 en mi máquina.

Robert Benson
fuente
1

Haskell, 74 bytes

f n=sum[4|x<-[0..n],y<-[0..n],(1+n-x)^2+(1+n-y)^2>n^2,(n-x)^2+(n-y)^2<n^2]

Bastante sencillo, cuente el número de cuadrados entre (0,0) y (n, n) donde la parte inferior izquierda está dentro del círculo y la parte superior derecha está fuera del círculo, luego multiplique por 4.

Joshua David
fuente
0

Pyth , 29 bytes

Lsm*ddb*4lf}*QQrhyTym+1dT^UQ2

¡Intentalo!

Explicación

Lsm*ddb*4lf}*QQrhyTym+1dT^UQ2  # implicit input: Q
Lsm*ddb                        # define norm function
 s                             # sum
  m   b                        #     map each coordinate to
   *dd                         #                            its square
                         ^UQ2  # cartesian square of [0, 1, ..., Q - 1]
                               #     -> list of coordinates of all relevant grid points
          f                    # filter the list of coordinates T where:
           }*QQ                # square of Q is in
               r               #     the range [
                hyT            #         1 + norm(T),
                               #                  ^ coordinate of lower left corner
                   ym+1dT      #         norm(map({add 1}, T))
                               #              ^^^^^^^^^^^^^^^ coordinate of upper right corner
                               #     ) <- half-open range
         l                     # size of the filtered list
                               #     -> number of passed-through squares in the first quadrant
       *4                      # multiply by 4
                               # implicit print
Levitando León
fuente
0

Lote, 147 bytes

@set/an=0,r=%1*%1
@for /l %%i in (0,1,%1)do @for /l %%j in (0,1,%1)do @set/a"i=%%i,j=%%j,a=i*i+j*j-r,i+=1,j+=1,a&=r-i*i-j*j,n-=a>>31<<2
@echo %n%

Algo inspirado por las respuestas de AWK y Haskell.

Neil
fuente
Me alegro de poder inspirar a alguien :)
Robert Benson
0

Bash + Unix utilidades, 127 bytes

c()(d=$[(n/r+$1)**2+(n%r+$1)**2-r*r];((d))&&echo -n $[d<0])
r=$1
bc<<<`for((n=0;n<r*r;n++));{ c 0;c 1;echo;}|egrep -c 01\|10`*4

Pruébalo en línea!

Simplemente revise todos los puntos en el primer cuadrante, cuéntelos y multiplique por 4. Puede ser muy lento, pero funciona.

Mitchell Spector
fuente
0

JavaScript (ES7), 76 bytes

n=>4*(G=k=>k<n?Math.ceil((n**2-k++**2)**0.5)-(0|(n**2-k**2)**0.5)+G(k):0)(0)
George Reith
fuente
¿Tal vez puedas recortar un par de bytes recurriendo de nabajo a 0?
Neil
@Neil Lo intenté pero no pude ver una manera. Quería usar solo una función, pero aún necesito almacenar tanto el nradio como la kiteración y todos los intentos salieron en los mismos bytes
George Reith
@Neil Ah, veo lo que estás diciendo, k<n?...pero pierdo el orden de esos bytes n**2-k++**2porque la prioridad del operador es incorrecta al ir en reversa y la resta no es conmutativa, por lo que el lado izquierdo siempre necesita tener k-1paréntesis. ¿A menos que hayas encontrado un camino?
George Reith
Ah, pasé por alto la resta ... ¿tal vez puedas multiplicar todo por -4 en lugar de 4 para evitar eso? (Aunque eso aún podría consumir tus ahorros ...)
Neil