Menghitung lingkaran kotak kuadrat melaluinya


24

Tulis sebuah program atau fungsi yang diberi radius bilangan bulat r mengembalikan jumlah unit kuadrat lingkaran dengan jari-jari r berpusat pada titik asal melewati. Jika lingkaran melewati titik pada grid yang tidak dihitung sebagai melewati kuadrat unit yang berdekatan.

Berikut ilustrasi untuk r = 5 :

ilustrasi Ilustrasi oleh Kival Ngaokrajang, ditemukan di OEIS

Contoh:

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



@ Lukas Saya hanya pergi mencari ini, tetapi tampaknya menggunakan definisi yang sedikit berbeda (setidaknya tidak setuju N = 50).
Martin Ender

1
@ smls Dengan menghitung di kotak pembatas. Pastikan Anda tidak menghitung kotak di mana lingkaran hanya menyentuh sudut. Angka-angka pada OEIS salah, saya memiliki koreksi dalam tinjauan sekarang.
orlp

2
Tiba-tiba saya memiliki keinginan untuk membangun kubah di minecraft ...
Patrick Roberts

2
Apakah Anda sesama penampil 3Blue1Brown?
nitro2k01

Jawaban:


12

Python 2 , 54 byte

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

Cobalah online!

Kurang golf (55 byte) ( TIO )

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

Ini memperkirakan output sebagai 8*r, kemudian mengoreksi penyeberangan verteks. Hasilnya adalah 8*r-g(r*r), di mana g(x)dihitung jumlah cara untuk menulis xsebagai jumlah dari dua kotak (kecuali g(0)=0).

Jika lingkaran tidak pernah melewati simpul, jumlah sel yang disentuh akan sama dengan jumlah tepi yang dilintasi. Lingkaran melewati 2*rgridlines vertikal dan gridlines 2*rhorisontal, melewati masing-masing di kedua arah, dengan total 8*r.

Tapi, masing-masing persimpangan pada titik dihitung sebagai dua persimpangan tepi sementara hanya memasuki satu sel baru. Jadi, kami mengimbanginya dengan mengurangi jumlah penyeberangan titik. Ini termasuk titik pada sumbu seperti (r,0)serta tiga kali lipat Pythagoras seperti (4,3)untuk r=5.

Kami menghitung untuk kuadran tunggal poin (x,y)dengan x>=0dan y>0dengan x*x+y*y==n, lalu kalikan dengan 4. Kami melakukan ini dengan menghitung angka sqrt(r*r-x*x)yang merupakan bilangan bulat untuk xdalam interval [0,r).


5

Mathematica, 48 byte

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

Lihat kuadran pertama dan hitung jumlah sel kisi di mana input berada di antara norma sudut kiri bawah dan kanan atas sel (tentu saja mengalikan hasilnya dengan 4, tentu saja).


Metode lain 8#-SquaresR[2,#^2]Sign@#&didasarkan pada posting xnor
miles

@miles Oh wow, saya tidak punya petunjuk SquaresR. Jangan ragu untuk memposting itu sendiri (atau biarkan xn mempostingnya).
Martin Ender


3

Jelly , 21 13 12 11 byte

R²ạ²Æ²SạḤ×4

Cobalah online!

Bagaimana itu bekerja

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.

2

Perl 6, 61 byte

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

Bagaimana itu bekerja

->\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.

1

AWK, 90 byte

{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

Pemakaian:

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

Cukup pencarian sederhana melalui kuadran 1 untuk menemukan semua kotak yang akan memotong lingkaran. Simetri memungkinkan untuk dikalikan dengan 4. Bisa dari -$1 to $1, tetapi itu akan membutuhkan lebih banyak byte dan kurang efisien. Jelas ini bukan algoritma yang paling efisien waktu, tetapi hanya membutuhkan waktu sekitar 16 detik untuk menjalankan case 5525 pada mesin saya.


1

Haskell, 74 byte

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]

Cukup mudah, hitung jumlah kotak antara (0,0) dan (n, n) di mana kiri bawah di dalam lingkaran dan kanan atas di luar lingkaran, lalu kalikan dengan 4.


0

Pyth , 29 byte

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

Cobalah!

Penjelasan

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

0

Batch, 147 byte

@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%

Agak terinspirasi oleh jawaban AWK dan Haskell.


Senang saya bisa menginspirasi seseorang :)
Robert Benson

0

Utilitas Bash + Unix, 127 byte

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

Cobalah online!

Ikuti saja semua poin di kuadran pertama, hitung, dan kalikan dengan 4. Ini bisa sangat lambat, tetapi berhasil.


0

JavaScript (ES7), 76 byte

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)

Bisakah Anda mencukur beberapa byte dengan mengulang dari nbawah ke 0?
Neil

@Neil saya memang mencoba tetapi tidak bisa melihat jalan. Ingin menggunakan hanya satu fungsi tetapi masih perlu menyimpan njari-jari dan kiterasi dan semua upaya keluar dengan byte yang sama
George Reith

@Neil Ah saya mengerti apa yang Anda katakan, k<n?...tetapi saya kehilangan byte-byte yang dipesan ulang n**2-k++**2karena prioritas operator salah ketika mundur dan pengurangan tidak komutatif sehingga sisi kiri selalu perlu memiliki k-1dan membutuhkan tanda kurung. Kecuali Anda sudah menemukan jalan?
George Reith

Ah, saya mengabaikan pengurangan ... mungkin Anda bisa mengalikan semuanya dengan -4 bukannya 4 untuk mengatasinya? (Meskipun itu mungkin masih memakan tabunganmu ...)
Neil
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.