Code-Golf: Bir Daire İçindeki Kafes Noktalar


15

Aşağıdaki resim sorunu göstermektedir:

resim açıklamasını buraya girin

Daire yarıçapı olarak bir tamsayı verilen, ortadaki dairenin içindeki kafes noktalarının sayısını (sınır dahil) hesaplayan bir işlev yazın .

Resimde şunlar gösterilir:

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

kontrol / hata ayıklama için diğer değerler:

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

Makul bir performansa sahip olmalıdır. Diyelim ki f [1000] için bir dakikadan az.

En kısa kod kazanır. Her zamanki Code-Golf kuralları geçerlidir.

Lütfen f [1001] hesaplamasını ve zamanlamasını örnek olarak gönderin.



Yanıtlar:


9

J, 21 19 18

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

-X-xj'den x + xj'ye kadar kompleksler oluşturur ve büyüklüğü alır.

Düzenle: İle >:

Edit 2: Kanca ve monadik ile ~. Herhangi bir nedenle birkaç kez daha yavaş çalışır, ancak f (1000) için hala 10-ish saniye.


Oh hey, bilmiyordum i:, çok çalıyorum, teşekkürler!
JB

@JB: Evet, iyi ... çalıyorum >:. derp
Jesse Millikan

Keşke bunları da çalmak için kapakları iyi anladım O :-)
JB

Bu cevap iç karartıcı bir şekilde kısadır (kısa ve / veya golf dilini öğrenmek için hiç uğraşmamış birine) >:. Ama hey, bu harika bir cevap! :)
Monica'nın Davası

5

J, 27 21

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

Çok acımasız: hesaplar sqrt (x² + y²) üzerinde [-n, n] aralığı ve sayımlar ürün ≤n . 1000 için hala çok kabul edilebilir zamanlar.

Düzenleme : i:ybiraz daha kısadır y-i.>:+:y. Teşekkürler Jesse Millikan !


Ha! İyi bir performans istemenin arkasındaki fikir buydu! Sadece merak ediyorum: 1000 için zamanlama nedir?
Dr. belisarius

1
@belisarius: 0.86s. 10 yıllık donanımda. 2000 için 3.26s.
JB

4

Yakut 1.9, 62 58 54 karakter

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

Misal:

f[1001]
=> 3147833

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

4

Python 55 Karakter

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 karakter daha kısadır.
Ventero

3

Haskell, 41 bayt

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

Kadrandaki noktaları sayar x>=0, y>0, 4 ile çarpar, merkez nokta için 1 ekler.


2

Haskell, 44 bayt

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

Haskell'de yeniyim: w<-[-n..n]Boole değeri olan (genellikle) nerede yazabilirsiniz ?
Kusur

1
@flawr Bunlar, bir desen eşleşirse başarılı olan, ancak daha kısa bir izin olarak golfte kullanılabilen desen korumalarıdır . Bu ipucuna bakın .
xnor

Teşekkürler, bu konunun farkında değildim!
Kusur

1

JavaScript (ES6), 80 bayt (ES6 çok yeni olduğu için rakip değil)

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

Alternatif sürüm, ayrıca 80 bayt:

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 sürümü, ayrıca 80 bayt:

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

1

Python 2, 48 bayt

f=lambda n,i=0:i>n or(n*n-i*i)**.5//1*4+f(n,i+1)

Gibi fR0DDY çözümüyle , ama özyinelemeli ve iadeler bir şamandıra. İnt döndürmek 51 bayttır:

f=lambda n,i=0:i>n or 4*int((n*n-i*i)**.5)+f(n,i+1)

1

C (gcc) , 60 bayt

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

Çevrimiçi deneyin!

İlk çeyreğin üzerindeki döngüler, sonucu 4 ile çarpar ve bir ekler. Biraz daha az golf

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

1

APL (Genişletilmiş Dyalog) , 14 bayt

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

Çevrimiçi deneyin!

i:J yapısındaki (-n'den n'ye kadar dahil) eksikliğine rağmen , APL Extended diğer alanlarda daha kısa sözdizimine sahiptir.

{≢⍸⍵≥|⌾⍀⍨⍵…-⍵}            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

Japt -x , 12 bayt

òUn)ï Ëx²§U²

Çevrimiçi deneyin!

Açıklama:

òUn)            #Get the range [-input ... input]
    ï           #Get each pair of numbers in that range
      Ë         #For each pair:
       x        # Get the sum...
        ²       # Of the squares
         §      # Check if that sum is less than or equal to...
          U²    # The input squared
                #Output the number of pairs that passed the check


1

PHP, 85 83 bayt

Kod:

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

Sonuçları ( birden çok PHP sürümü için https://3v4l.org/bC0cY adresini kontrol edin ):

f(1001)=3147833
time=0.000236 seconds.

Çözülmemiş kod:

/**
 * 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)Noktaları kontrol eden (ve 1000 f(1001)saniyeden daha yavaş çalışan ancak 0,5 saniyeden daha kısa sürede hesaplayan ) saf bir uygulama ve test takımı (soruda verilen örnek verileri kullanarak) github'da bulunabilir .


0

Clojure / ClojureScript, 85 karakter

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

Brute, x ekseni değil, y ekseni dahil olmak üzere ilk çeyreği zorlar. Her nokta için 4 üretir, ardından başlangıç ​​noktası için 1 ile birlikte ekler. 1000 girişi için 2 saniyenin altında çalışır.

forBir değişken tanımlamak ve birkaç karakter kaydetmek için cehennemi kötüye kullanır . Bunu yapmak için bir takma ad oluşturmak, rangeherhangi bir karakteri kaydetmez (ve çok daha yavaş çalışmasını sağlar) ve kare bir işlev yaparak herhangi bir şeyi kaydetmeniz pek olası görünmez.


Bu oldukça eski bir soru, bu cevabın o zaman işe yarayacağından emin misiniz?
Mavi

@muddyfish Yaşı fark etmedim, sadece tepenin yakınında gördüm. Clojure sorudan önce gelir, ancak tarihini dil değişiklikleri hakkında bilecek kadar bilmiyorum.
MattPutnam


0

Mathematica, 35 karakter

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

Https://oeis.org/A000328 adresinden kaldırıldı

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

SquaresR[2,k]k, iki kare toplamı olarak k temsil etme yollarının sayısıdır, bu da k ^ 2 yarıçapındaki bir daire üzerindeki kafes noktalarının sayısıyla aynıdır. N yarıçapı dairesi içindeki veya içindeki tüm noktaları bulmak için k = 0 ile k = n ^ 2 arasındaki toplam.


1
2~SquaresR~k~Sum~{k,0,#^2}&kısaltmak için
buttercrab

0

Tcl, 111 bayt

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

Basit ayrık xKadran I üzerinde döngüsü, en büyük saymaHer adımda Pisagor Teoremi kullanılarak en y . Sonuç toplamın 4 katı artıdır (merkez noktası için).

Programın boyutu r değerine bağlıdır . Değiştir {1001 0 -1}ile"$argv 0 -1" ve herhangi bir komut satırı argümanı değeri ile çalıştırabilirsiniz r .

Hesaplar f (1001) → 3147833.0 yaklaşık 1030 mikrosaniye içinde hesaplanır, AMD Sempron 130 2.6GHz 64-bit işlemci, Windows 7.

Açıkçası, yarıçap ne kadar büyükse, PI'ye yaklaştıkça: f (10000001) yaklaşık 30 saniye içinde çalışır ve 15 basamaklı bir değer üretir, bu da bir IEEE çiftinin hassasiyeti ile ilgilidir.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.