การนับจำนวนหน่วยสี่เหลี่ยมวงกลมผ่าน


24

เขียนโปรแกรมหรือฟังก์ชั่นที่กำหนดรัศมีจำนวนเต็มrส่งคืนจำนวนหน่วยสี่เหลี่ยมวงกลมที่มีรัศมีrอยู่กึ่งกลางที่จุดกำเนิดผ่าน หากวงกลมผ่านจุดใดจุดหนึ่งบนกริดที่ไม่นับรวมผ่านหน่วยสี่เหลี่ยมที่อยู่ติดกัน

นี่คือภาพประกอบสำหรับr = 5 :

ภาพประกอบ ภาพประกอบโดย Kival Ngaokrajang พบได้ใน OEIS

ตัวอย่าง:

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



@ ลุคฉันเพิ่งไปค้นหาสิ่งนี้ แต่ดูเหมือนว่าจะใช้คำจำกัดความที่แตกต่างกันเล็กน้อย (อย่างน้อยก็ไม่เห็นด้วยN = 50)
Martin Ender

1
@smls ด้วยการนับในตารางที่มีขอบเขต ตรวจสอบให้แน่ใจว่าคุณไม่นับสี่เหลี่ยมที่วงกลมสัมผัสเพียงมุมเดียว ตัวเลขใน OEIS ไม่ถูกต้องฉันมีการแก้ไขในการตรวจสอบในขณะนี้
orlp

2
ฉันมีกระตุ้นอย่างฉับพลันเพื่อสร้างโดมใน Minecraft อีกครั้ง ...
แพทริคโรเบิร์ต

2
คุณเป็นเพื่อนร่วม 3Blue1Brown
nitro2k01

คำตอบ:


12

Python 2 , 54 ไบต์

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

ลองออนไลน์!

หักกอล์ฟน้อยลง (55 ไบต์) ( TIO )

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

สิ่งนี้ประมาณเอาท์พุทเป็น8*rแล้วแก้ไขการข้ามจุดสุดยอด ผลที่ได้คือ8*r-g(r*r)ที่g(x)นับจำนวนวิธีที่จะเขียนxเป็นผลรวมของสองสี่เหลี่ยม (ยกเว้นg(0)=0)

หากวงกลมไม่ผ่านจุดยอดใด ๆ จำนวนของเซลล์ที่สัมผัสจะเท่ากับจำนวนของขอบที่ไขว้กัน วงกลมผ่าน2*rเส้นแนวตั้งและเส้นแนวนอนผ่านแต่ละคนในทั้งสองทิศทางรวมของ2*r8*r

แต่การข้ามแต่ละครั้งที่จุดสุดยอดจะนับเป็นจุดผ่านสองจุดในขณะที่เข้าสู่เซลล์ใหม่เพียงเซลล์เดียว ดังนั้นเราชดเชยด้วยการลบจำนวนจุดตัดยอด ซึ่งรวมถึงการจุดบนแกนเหมือน(r,0)เช่นเดียวกับพีทาโกรัสอเนกประสงค์เช่นสำหรับ(4,3)r=5

เรานับเป็นวอดเดียวจุด(x,y)ด้วยx>=0และy>0ด้วยx*x+y*y==nแล้วคูณด้วย 4. เราทำเช่นนี้โดยการนับ numer ของsqrt(r*r-x*x)ที่มีจำนวนทั้งหมดสำหรับในช่วงเวลาx[0,r)


5

Mathematica, 48 ไบต์

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

ดูที่จตุภาคแรกและนับจำนวนของกริดเซลล์ที่อินพุตตกระหว่างบรรทัดฐานของมุมล่างซ้ายและขวาของเซลล์ (คูณผลลัพธ์ด้วย 4 แน่นอน)


อีกวิธีหนึ่งคือ8#-SquaresR[2,#^2]Sign@#&ขึ้นอยู่กับ XNOR โพสต์
ไมล์

@miles โอ้ว้าวฉันไม่มีเงื่อนงำSquaresRอยู่แล้ว อย่าลังเลที่จะโพสต์ด้วยตัวคุณเอง (หรือปล่อยให้ xnor โพสต์ไว้)
Martin Ender


3

เยลลี่ , 21 13 12 11 ไบต์

R²ạ²Æ²SạḤ×4

ลองออนไลน์!

มันทำงานอย่างไร

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 bytes

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

มันทำงานอย่างไร

->\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 ไบต์

{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

การใช้งาน:

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

เพียงแค่ค้นหาง่ายๆผ่านจตุภาคที่ 1 เพื่อค้นหาช่องทั้งหมดที่จะตัดกันวงกลม Symmetry อนุญาตให้คูณด้วย 4 ได้จากไป-$1 to $1แต่นั่นอาจใช้ไบต์มากขึ้นและมีประสิทธิภาพน้อยลง เห็นได้ชัดว่านี่ไม่ใช่อัลกอริธึมที่มีประสิทธิภาพสูงสุด แต่ใช้เวลาเพียง 16 วินาทีในการรันเคส 5525 บนเครื่องของฉัน


1

Haskell, 74 ไบต์

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]

ตรงไปตรงมานับจำนวนกำลังสองระหว่าง (0,0) และ (n, n) โดยที่ด้านล่างซ้ายอยู่ในวงกลมและด้านบนขวาอยู่นอกวงกลมแล้วคูณด้วย 4


0

Pyth , 29 ไบต์

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

ลองมัน!

คำอธิบาย

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

แบตช์ 147 ไบต์

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

ค่อนข้างแรงบันดาลใจจากคำตอบ AWK และ Haskell


ดีใจที่ฉันสามารถสร้างแรงบันดาลใจให้ใครสักคนได้บ้าง :)
Robert Benson

0

ยูทิลิตีBash + Unix ขนาด 127 ไบต์

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

ลองออนไลน์!

เพิ่งผ่านทุกจุดในจตุภาคแรกนับมันขึ้นมาแล้วคูณด้วย 4 มันอาจช้ามาก แต่ก็ใช้งานได้


0

JavaScript (ES7), 76 ไบต์

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)

คุณสามารถโกนหนวดสักสองสามไบต์ได้โดยการวนซ้ำจากnล่างเป็น0หรือไม่
Neil

@ ไม่มีฉันลอง แต่ไม่เห็นทางเลย ต้องการใช้เพียงฟังก์ชั่นเดียว แต่ยังจำเป็นต้องเก็บทั้งnรัศมีและkการวนซ้ำและความพยายามทั้งหมดออกมาเป็นไบต์เดียวกัน
George Reith

@ Neil Ah ฉันเห็นสิ่งที่คุณกำลังพูดถึงk<n?...แต่ฉันสูญเสียไบต์ที่เรียงลำดับใหม่n**2-k++**2เนื่องจากลำดับความสำคัญของตัวดำเนินการผิดเมื่อไปในการย้อนกลับและการลบไม่ใช่แบบสลับกันดังนั้นด้านซ้ายจะต้องมีk-1และต้องการวงเล็บ ถ้าคุณไม่พบวิธี?
George Reith

อาฉันมองข้ามการลบ ... บางทีคุณอาจคูณทั้งหมดด้วย -4 แทน 4 เพื่อหลีกเลี่ยงสิ่งนั้น? (แม้ว่ามันอาจจะยังกินการออมของคุณ ... )
Neil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.