Код-Гольф: Решіткові точки всередині кола


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

Найкоротший код виграє. Діють звичайні правила Code-Golf.

Будь ласка, опублікуйте як приклад обчислення та терміни f [1001].



Відповіді:


9

J, 21 19 18

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

Побудовує комплекси від -x-xj до x + xj і приймає величину.

Редагувати: с >:

Редагування 2: З гачком і монадією ~. Біжить з декількох причин кілька разів повільніше, але все-таки на 10-секундні секунди для f (1000).


О, ага, я не знав про це i:, я так краду, що, дякую!
JB

@JB: Так, добре ... я краду >:. дерп
Джессі Мілікан

Я б хотів, щоб я зрозумів шапки досить добре, щоб вкрасти їх теж O :-)
JB

Ця відповідь гнітюче коротка (для того, хто ніколи не намагався навчитися короткому та / або гольфу) >:. Але ей, це класна відповідь! :)
Фонд позову Моніки

5

J, 27 21

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

Дуже жорстоко: обчислює sqrt (x² + y²) в межах [-n, n] і рахує елементи ≤n . Ще дуже прийнятні рази на 1000.

Правка : i:yзовсім трохи коротша, ніж y-i.>:+:y. Спасибі Джессі Мілікан !


Га! Це була ідея, щоб попросити гідну виставу! Просто цікаво: Який термін для 1000?
Доктор Белісарій

1
@belisarius: 0,86с. На 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 Chars

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 символів коротше.
Вентеро

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

Дякую, я не знав про цю нитку!
flawr

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

Python 2, 48 байт

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

Як і рішення fR0DDY , але рекурсивний і повертає поплавок. Повернення int становить 51 байт:

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


1

APL (Dyalog Extended) , 14 байт

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

Спробуйте в Інтернеті!

Незважаючи на відсутність 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)точки (і працює на 1000 повільніше, але все-таки обчислює 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))

Брут примушує перший квадрант, включаючи вісь y, але не вісь x. Створює 4 для кожної точки, потім додає їх разом з 1 для початку. Працює за 2 секунди для введення 1000.

Зловживає пекло, forщоб визначити змінну і зберегти кілька символів. Якщо це зробити для створення псевдоніму range, не зберігається жодних символів (і робить його запуск значно повільніше), і здається, що ви збираєтесь нічого зберегти, зробивши квадратну функцію.


Це досить старе питання, ви впевнені, що ця відповідь спрацювала б у той час?
Блакитний

@muddyfish я не помітив віку, просто побачив це біля вершини. Clojure передує цьому питанню, але я не знаю його історії достатньо, щоб знати про зміни мови.
MattPutnam


0

Математика, 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 співав

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

Простий дискретний х цикл над квадратом I, рахуючи найбільшу y використовуючи теорему Піфагора на кожному кроці. Результат у 4 рази перевищує суму плюс один (для центральної точки).

Розмір програми залежить від значення r . Замініть {1001 0 -1}на, "$argv 0 -1"і ви можете запустити його з будь-яким значенням аргументу командного рядка для r .

Обчислює f (1001) → 3147833.0приблизно за 1030 мікросекунд, 64-бітний процесор AMD Sempron 130 2,6 ГГц, Windows 7.

Очевидно, що чим більший радіус, тим ближче наближення до PI: f (10000001) проходить приблизно за 30 секунд, виробляючи 15-значне значення, що стосується точності подвійного IEEE.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.