Code-Golf: Lattice Points ภายในวงกลม


15

ภาพต่อไปนี้แสดงปัญหา:

ป้อนคำอธิบายรูปภาพที่นี่

เขียนฟังก์ชันที่ให้เลขจำนวนเต็มเป็นรัศมีวงกลมคำนวณจำนวนจุดขัดแตะภายในวงกลมกลาง (รวมถึงขอบเขต)

ภาพแสดง:

f[1] = 5  (blue points)
f[2] = 13 (blue + red points)  

ค่าอื่น ๆ สำหรับการตรวจสอบ / การดีบักของคุณ:

f[3]    = 29
f[10]   = 317
f[1000] = 3,141,549
f[2000] = 12,566,345  

ควรมีประสิทธิภาพที่สมเหตุสมผล สมมติว่าน้อยกว่าหนึ่งนาทีสำหรับ f [1000]

รหัสที่สั้นที่สุดชนะ มีการใช้กฎเกณฑ์ของสนามกอล์ฟตามปกติ

กรุณาโพสต์การคำนวณและเวลาของ f [1001] เป็นตัวอย่าง



รุ่นสามเหลี่ยม
user202729

คำตอบ:


9

J, 21 19 18

+/@,@(>:|@j./~@i:)

สร้างคอมเพล็กซ์จาก -x-xj ถึง x + xj และรับความสำคัญ

แก้ไข: ด้วย >:

แก้ไข 2: ~ด้วยตะขอและเอก ทำงานช้าลงสองสามครั้งด้วยเหตุผลบางอย่าง แต่ยังคง 10 วินาทีต่อวินาทีสำหรับ f (1,000)


โอ้โหฉันไม่รู้เรื่องi:นี้ฉันก็เลยขโมยไปขอบคุณ!
JB

@JB: ใช่ดี ... >:ฉันขโมย derp
Jesse Millikan

ฉันหวังว่าฉันเข้าใจตัวพิมพ์ใหญ่มากพอที่จะขโมย O :-) ได้เช่นกัน
JB

คำตอบนี้หงอยสั้น ๆ (กับคนที่ไม่เคยใส่ใจที่จะเรียนรู้ในระยะสั้นและ / หรือการเล่นกอล์ฟ >:lang) แต่เฮ้นั่นเป็นคำตอบที่ยอดเยี่ยม! :)
คดีของกองทุนโมนิกา

5

J, 27 21

3 :'+/,y>:%:+/~*:i:y'

โหดร้ายมาก: คำนวณsqrt (x² + y²)มากกว่า[-n, N]ช่วงและนับรายการ≤n ยังคงเป็นเวลาที่ยอมรับได้มากสำหรับ 1,000

แก้ไข : ไม่น้อยที่สั้นกว่าi:y y-i.>:+:yขอบคุณJesse Millikan !


ฮา! นั่นคือความคิดที่อยู่เบื้องหลังการขอให้มีประสิทธิภาพที่ดี! แค่อยากรู้อยากเห็น: เวลาสำหรับ 1,000 คืออะไร?
ดร. เบลิซาเรี

1
@belisarius: 0.86s เกี่ยวกับฮาร์ดแวร์อายุ 10 ปี 3.26s สำหรับปี 2000
JB

4

ทับทิม 1.9 62 58 54 ตัวอักษร

f=->r{1+4*eval((0..r).map{|i|"%d"%(r*r-i*i)**0.5}*?+)}

ตัวอย่าง:

f[1001]
=> 3147833

t=Time.now;f[1001];Time.now-t
=> 0.003361411

4

Python 55 ตัวอักษร

f=lambda n:1+4*sum(int((n*n-i*i)**.5)for i in range(n))

f=lambda n:1+4*sum(int((n*n-i*i)**.5)for i in range(n))สั้นกว่า 17 ตัวอักษร
Ventero

3

Haskell, 41 ไบต์

f n=1+4*sum[floor$sqrt$n*n-x*x|x<-[0..n]]

นับคะแนนในจตุภาคx>=0, y>0คูณด้วย 4 เพิ่ม 1 สำหรับจุดศูนย์กลาง


2

Haskell, 44 ไบต์

f n|w<-[-n..n]=sum[1|x<-w,y<-w,x*x+y*y<=n*n]

ฉันใหม่กับ Haskell: คุณจะเขียนได้อย่างไรw<-[-n..n]ว่าที่ไหนมีค่าบูลีน (ปกติ)
ข้อบกพร่อง

1
@ flawr เหล่านี้เป็นยามรูปแบบซึ่งประสบความสำเร็จหากรูปแบบการจับคู่ แต่สามารถใช้ในการเล่นกอล์ฟเป็นให้สั้นลง ดูเคล็ดลับนี้
xnor

ขอบคุณฉันไม่ได้ตระหนักถึงหัวข้อนี้!
ข้อบกพร่อง

1

JavaScript (ES6), 80 ไบต์ (ไม่แข่งขันเนื่องจาก ES6 ใหม่เกินไป)

n=>(a=[...Array(n+n+1)].map(_=>i--,i=n)).map(x=>a.map(y=>r+=x*x+y*y<=n*n),r=0)|r

รุ่นทางเลือก 80 ไบต์เช่นกัน:

n=>[...Array(n+n+1)].map((_,x,a)=>a.map((_,y)=>r+=x*x+(y-=n)*y<=n*n,x-=n),r=0)|r

รุ่น ES7, 80 ไบต์เช่นกัน:

n=>[...Array(n+n+1)].map((_,x,a)=>a.map((_,y)=>r+=(x-n)**2+(y-n)**2<=n*n),r=0)|r


1

C (gcc) , 60 ไบต์

r,a;f(x){for(a=r=x*x;a--;)r-=hypot(a%x+1,a/x)>x;x=4*r+1;}

ลองออนไลน์!

วนซ้ำเหนือจตุภาคแรกคูณผลลัพธ์ด้วย 4 และเพิ่มหนึ่งอัน ตีกอล์ฟน้อยลงเล็กน้อย

r,a;
f(x){
  for(a=r=x*x;a--;)
    r-=hypot(a%x+1,a/x)>x;
  x=4*r+1;
}

1

APL (Dyalog Extended) , 14 ไบต์

{≢⍸⍵≥|⌾⍀⍨⍵…-⍵}

ลองออนไลน์!

แม้จะไม่มี built-in i:(รวมตั้งแต่ -n ถึง n) ของ J แต่ APL Extended มีไวยากรณ์ที่สั้นกว่า

{≢⍸⍵≥|⌾⍀⍨⍵…-⍵}            Monadic function taking an argument n.
           ⍵…-⍵             n, n-1, ..., -n
      ⌾⍀                   Make a table of complex numbers
                            (equivalent to ∘.{⍺+1J×⍵} in Dyalog APL)
                           with both real and imaginary parts from that list.
      |                       Take their magnitudes.
    ⍵≥                        1 where a magnitude are is at most n, and 0 elsewhere.
                            Get all indices of truthy values.
                            Find the length of the resulting list.


1

PHP, 85 83 ไบต์

รหัส:

function f($n){for($x=$n;$x;$c+=$x,$y++)for(;$n*$n<$x*$x+$y*$y;$x--);return$c*4+1;}

ผลลัพธ์ของมัน (ตรวจสอบhttps://3v4l.org/bC0cYสำหรับ PHP หลายเวอร์ชัน):

f(1001)=3147833
time=0.000236 seconds.

รหัสที่ไม่ดีนัก:

/**
 * Count all the points having x > 0, y >= 0 (a quarter of the circle)
 * then multiply by 4 and add the origin.
 *
 * Walk the lattice points in zig-zag starting at ($n,0) towards (0,$n), in the
 * neighbourhood of the circle. While outside the circle, go left.
 * Go one line up and repeat until $x == 0.
 * This way it checks about 2*$n points (i.e. its complexity is linear, O(n))
 *
 * @param int $n
 * @return int
 */
function countLatticePoints2($n)
{
    $count = 0;
    // Start on the topmost right point of the circle ($n,0), go towards the topmost point (0,$n)
    // Stop when reach it (but don't count it)
    for ($y = 0, $x = $n; $x > 0; $y ++) {
        // While outside the circle, go left;
        for (; $n * $n < $x * $x + $y * $y; $x --) {
            // Nothing here
        }
        // ($x,$y) is the rightmost lattice point on row $y that is inside the circle
        // There are exactly $x lattice points on the row $y that have x > 0
        $count += $x;
    }
    // Four quarters plus the center
    return 4 * $count + 1;
}

การดำเนินการตรวจสอบที่ไร้เดียงสาว่า$n*($n+1)จุด (และวิ่ง 1,000 ช้าลง แต่ยังคงคำนวณf(1001)ในเวลาน้อยกว่า 0.5 วินาที) และชุดทดสอบ (โดยใช้ข้อมูลตัวอย่างที่ให้ไว้ในคำถาม) สามารถพบได้บน GitHub


0

Clojure / ClojureScript, 85 ตัวอักษร

#(apply + 1(for[m[(inc %)]x(range 1 m)y(range m):when(<=(+(* x x)(* y y))(* % %))]4))

Brute บังคับให้จตุภาคแรกรวมถึงแกน y แต่ไม่ใช่แกน x สร้าง 4 สำหรับทุกจุดแล้วเพิ่มเข้าด้วยกันด้วย 1 สำหรับจุดเริ่มต้น ทำงานภายใน 2 วินาทีสำหรับการป้อนข้อมูล 1,000

ใช้ผิดวิธีforเพื่อกำหนดตัวแปรและบันทึกอักขระสองสามตัว การทำเช่นเดียวกันเพื่อสร้างนามแฝงสำหรับrangeจะไม่บันทึกอักขระใด ๆ (และทำให้มันทำงานช้าลงอย่างมาก) และดูเหมือนว่าคุณจะไม่ต้องบันทึกอะไรเลยด้วยการสร้างฟังก์ชันแบบจัตุรัส


นี่เป็นคำถามที่ค่อนข้างเก่าคุณแน่ใจหรือไม่ว่าคำตอบนี้จะใช้ได้ในเวลานั้น?
บลู

@muddyfish ฉันไม่ได้สังเกตอายุแค่เห็นมันใกล้ด้านบน Clojure ถือกำเนิดคำถาม แต่ฉันไม่รู้ประวัติของมันมากพอที่จะรู้เกี่ยวกับการเปลี่ยนแปลงภาษา
MattPutnam


0

Mathematica, 35 ตัวอักษร

f[n_]:=Sum[SquaresR[2,k],{k,0,n^2}]

ยกระดับจากhttps://oeis.org/A000328

https://reference.wolfram.com/language/ref/SquaresR.html

SquaresR[2,k]คือจำนวนวิธีในการแทนค่า k เป็นผลรวมของสองกำลังสองซึ่งเหมือนกับจำนวนจุดขัดแตะในวงกลมรัศมี k ^ 2 ผลรวมจาก k = 0 ถึง k = n ^ 2 เพื่อค้นหาจุดทั้งหมดในหรือภายในวงกลมรัศมี n


1
2~SquaresR~k~Sum~{k,0,#^2}&เพื่อทำให้มันสั้นลง
jaeyong sung

0

Tcl, 111 ไบต์

lassign {1001 0 -1} r R x
while {[incr x]<$r} {set R [expr {$R+floor(sqrt($r*$r-$x*$x))}]}
puts [expr {4*$R+1}]

xแยกง่าย ๆเหนือ quadrant I, นับy ที่ใหญ่ที่สุดโดยใช้ทฤษฎีบทพีทาโกรัสในแต่ละขั้นตอน ผลลัพธ์คือ 4 เท่าของผลรวมบวกหนึ่ง (สำหรับจุดศูนย์กลาง)

ขนาดของโปรแกรมจะขึ้นอยู่กับค่าของR แทนที่{1001 0 -1}ด้วย"$argv 0 -1"และคุณสามารถเรียกใช้มันมีค่าอาร์กิวเมนต์บรรทัดคำสั่งใด ๆ สำหรับR

คำนวณ f (1001) → 3147833.0ในประมาณ 1030 microseconds, AMD Sempron 130 2.6GHz 64-bit processor, Windows 7

เห็นได้ชัดว่ารัศมีที่ใหญ่กว่ายิ่งใกล้เคียงกับ PI: f (10000001) มากขึ้นในเวลาประมาณ 30 วินาทีให้ค่า 15 หลักซึ่งเป็นเรื่องของความแม่นยำของ IEEE สองเท่า


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