Đếm hình vuông đơn vị đi qua


24

Viết chương trình hoặc hàm cho bán kính nguyên r trả về số lượng đơn vị bình phương hình tròn có bán kính r tập trung tại điểm gốc đi qua. Nếu vòng tròn đi chính xác qua một điểm trên lưới không được tính là đi qua các ô vuông đơn vị liền kề.

Đây là một minh họa cho r = 5 :

hình minh họa Minh họa bởi Kival Ngaokrajang, được tìm thấy trên OEIS

Ví dụ:

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



@Luke Tôi vừa mới tìm kiếm cái này, nhưng nó dường như sử dụng một định nghĩa hơi khác (ít nhất là nó không đồng ý N = 50).
Martin Ender

1
@smls Bằng cách đếm trong ô vuông giới hạn. Đảm bảo rằng bạn không đếm các ô vuông trong đó hình tròn chỉ chạm vào một góc. Các con số trên OEIS là sai, tôi có một sự điều chỉnh trong đánh giá ngay bây giờ.
orlp

2
Tôi có một sự thôi thúc bất ngờ để xây dựng mái vòm trong minecraft một lần nữa ...
Patrick Roberts

2
Bạn có phải là người xem 3Blue1Brown đồng nghiệp?
nitro2k01

Câu trả lời:


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)

Hãy thử trực tuyến!

Ít chơi gôn hơn (55 byte) ( TIO )

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

Điều này ước tính đầu ra là 8*r, sau đó sửa chữa cho các giao điểm đỉnh. Kết quả là 8*r-g(r*r), trong đó g(x)đếm số cách viết xdưới dạng tổng của hai hình vuông (trừ g(0)=0).

Nếu vòng tròn không bao giờ đi qua bất kỳ đỉnh nào, số lượng ô được chạm sẽ bằng số cạnh được giao. Vòng tròn đi qua các 2*rđường lưới dọc và đường lưới 2*rngang, đi qua mỗi hướng theo cả hai hướng, với tổng số 8*r.

Nhưng, mỗi giao cắt tại một đỉnh được tính là hai giao điểm cạnh trong khi chỉ nhập một ô mới. Vì vậy, chúng tôi bù bằng cách trừ đi số lượng giao điểm đỉnh. Điều này bao gồm các điểm trên các trục như (r,0)cũng như bộ ba Pythagore như (4,3)cho r=5.

Chúng tôi đếm cho một góc phần tư duy nhất các điểm (x,y)x>=0y>0với x*x+y*y==n, sau đó nhân với 4. Chúng tôi làm điều này bằng cách đếm số của số sqrt(r*r-x*x)đó là toàn bộ số xtrong khoảng [0,r).


5

Toán học, 48 byte

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

Nhìn vào góc phần tư thứ nhất và đếm số lượng ô lưới mà đầu vào nằm giữa các chỉ tiêu của góc dưới bên trái và phía trên bên phải của ô (dĩ nhiên nhân kết quả với 4).


Phương pháp khác là 8#-SquaresR[2,#^2]Sign@#&dựa trên XNOR của bài
dặm

@miles Oh wow, tôi không có manh mối SquaresRtồn tại. Hãy tự đăng bài đó (hoặc để xnor đăng nó).
Martin Ender


3

Thạch , 21 13 12 11 byte

R²ạ²Æ²SạḤ×4

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Làm thế nào nó hoạt động

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

Sử dụng:

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

Chỉ cần một tìm kiếm đơn giản thông qua góc phần tư 1 để tìm tất cả các hộp sẽ giao nhau với vòng tròn. Đối xứng cho phép nhân với 4. Có thể đi từ -$1 to $1, nhưng điều đó sẽ mất nhiều byte hơn và kém hiệu quả hơn. Rõ ràng đây không phải là thuật toán hiệu quả nhất về thời gian, nhưng chỉ mất khoảng 16 giây để chạy vỏ 5525 trên máy của tôi.


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]

Khá đơn giản, đếm số ô vuông nằm giữa (0,0) và (n, n) trong đó phía dưới bên trái nằm trong vòng tròn và trên cùng bên phải nằm ngoài vòng tròn, sau đó nhân với 4.


0

Bình thường , 29 byte

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

Thử nó!

Giải trình

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

Mẻ, 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%

Phần nào lấy cảm hứng từ câu trả lời AWK và Haskell.


Vui vì tôi có thể truyền cảm hứng cho ai đó :)
Robert Benson

0

Tiện ích 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

Hãy thử trực tuyến!

Chỉ cần đi qua tất cả các điểm trong góc phần tư thứ nhất, đếm chúng và nhân với 4. Nó có thể rất chậm, nhưng nó hoạt động.


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)

Có lẽ bạn có thể cạo một vài byte bằng cách đệ quy từ nxuống 0?
Neil

@ Tôi đã thử nhưng không thể thấy được. Muốn sử dụng chỉ một chức năng nhưng vẫn cần lưu trữ cả nbán kính và klặp và tất cả các lần thử đều xuất hiện cùng một byte
George Reith

@Neil Ah tôi thấy những gì bạn đang nói về k<n?...nhưng tôi mất đi những byte sắp xếp lại tại n**2-k++**2vì ưu tiên điều hành là sai khi đi theo hướng ngược lại và trừ là không giao hoán để phía bên trái luôn luôn cần phải có k-1và cần dấu ngoặc đơn. Trừ khi bạn tìm thấy một cách?
George Reith

À, tôi đã bỏ qua phép trừ ... có lẽ bạn có thể nhân toàn bộ mọi thứ với -4 thay vì 4 để giải quyết vấn đề đó? (Mặc dù điều đó vẫn có thể ăn vào khoản tiết kiệm của bạn ...)
Neil
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.