O círculo de quadrados da unidade de contagem passa por

24

Escreva um programa ou função que, dado um raio inteiro r, retorne o número de unidades ao quadrado do círculo, com o raio r centrado na origem. Se o círculo passar exatamente por um ponto na grade que não conta como passando pelos quadrados da unidade adjacente.

Aqui está uma ilustração para r = 5 :

ilustração Ilustração de Kival Ngaokrajang, encontrada na OEIS

Exemplos:

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

orlp
fonte
@ Lucas Eu apenas fui procurar isso, mas parece usar uma definição um pouco diferente (pelo menos não concorda N = 50).
Martin Ender
11
@smls Contando no quadrado delimitador. Certifique-se de não contar quadrados onde o círculo toca apenas um canto. Os números no OEIS estão errados, tenho uma correção em revisão no momento.
orlp
2
Eu tenho uma vontade súbita de cúpulas construção em Minecraft novamente ...
Patrick Roberts
2
Você é um colega visualizador do 3Blue1Brown?
nitro2k01 31/01

Respostas:

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)

Experimente online!

Menos golfe (55 bytes) ( TIO )

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

Isso estima a saída como 8*r, em seguida, corrige os cruzamentos de vértice. O resultado é 8*r-g(r*r), onde g(x)conta o número de maneiras de escrever xcomo uma soma de dois quadrados (exceto g(0)=0).

Se o círculo nunca passou por nenhum vértice, o número de células tocadas seria igual ao número de arestas cruzadas. O círculo passa pelas 2*rlinhas de grade verticais e 2*rhorizontais, passando cada uma nas duas direções, num total de 8*r.

Porém, cada cruzamento em um vértice conta como dois cruzamentos de borda, enquanto apenas entra em uma nova célula. Assim, compensamos subtraindo o número de cruzamentos de vértices. Isso inclui os pontos nos eixos (r,0), assim como os triplos pitagóricos, como (4,3)para r=5.

Contamos para um único quadrante os pontos (x,y)com x>=0e y>0com x*x+y*y==n, em seguida, multiplicar por 4. Fazemos isso através da contagem do numer de sqrt(r*r-x*x)que são número inteiro para xno intervalo [0,r).

xnor
fonte
5

Mathematica, 48 bytes

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

Examina o primeiro quadrante e conta o número de células da grade para as quais a entrada fica entre as normas dos cantos inferior esquerdo e superior direito da célula (multiplicando o resultado por 4, é claro).

Martin Ender
fonte
Outro método é 8#-SquaresR[2,#^2]Sign@#&baseado no post de xnor
milhas
@ Miles Oh uau, eu não tinha idéia SquaresRexiste. Sinta-se livre para postar você mesmo (ou deixe o xnor publicá-lo).
Martin Ender
3

Geléia , 21 13 12 11 bytes

R²ạ²Æ²SạḤ×4

Experimente online!

Como 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
fonte
2

Perl 6, 61 bytes

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

Como 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
fonte
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

Basta uma simples pesquisa no quadrante 1 para encontrar todas as caixas que cruzam o círculo. A simetria permite a multiplicação por 4. Poderia passar -$1 to $1, mas isso exigiria mais bytes e seria menos eficiente. Obviamente, esse algoritmo não é o mais eficiente em termos de tempo, mas leva apenas 16 segundos para executar o gabinete 5525 na minha máquina.

Robert Benson
fonte
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]

Bem simples, conte o número de quadrados entre (0,0) e (n, n) onde a parte inferior esquerda está dentro do círculo e a parte superior direita está fora do círculo, e multiplique por 4.

Joshua David
fonte
0

Pyth , 29 bytes

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

Tente!

Explicação

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
LevitatingLion
fonte
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%

Um pouco inspirado pelas respostas do AWK e Haskell.

Neil
fonte
Eu contente tanto pode inspirar alguém :)
Robert Benson
0

Utilitários Bash + Unix, 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

Experimente online!

Basta percorrer todos os pontos do primeiro quadrante, contá-los e multiplicar por 4. Pode ser muito lento, mas funciona.

Mitchell Spector
fonte
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
fonte
Você pode economizar alguns bytes recorrendo de nbaixo para 0?
Neil
@ Neil eu tentei, mas não conseguia ver uma maneira. Queria usar apenas uma função, mas ainda precisava armazenar o nraio e a kiteração, e todas as tentativas saíram com os mesmos bytes.
George Reith
@ Neil Ah, eu entendo o que você está dizendo, k<n?...mas perco esses bytes ao reordenar n**2-k++**2porque a precedência do operador está errada quando ocorre a inversão e a subtração não é comutativa, portanto o lado esquerdo sempre precisa ter k-1parênteses. A menos que você tenha encontrado um caminho?
George Reith
Ah, eu ignorei a subtração ... talvez você possa multiplicar a coisa toda por -4 em vez de 4 para contornar isso? (Apesar de que ainda pode comer-se em sua poupança ...)
Neil