Підрахунок одиничних квадратів коло проходить через


24

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

Ось ілюстрація для r = 5 :

ілюстрації Ілюстрація Ківаля Нгаокраджанга, знайдена в OEIS

Приклади:

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



@Luke Я просто шукав це, але, схоже, використовується дещо інше визначення (принаймні, воно не погоджується N = 50).
Мартін Ендер

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*rгоризонтальні лінії, проходячи кожне в обох напрямках, загалом 8*r.

Але кожне перетинання у вершині вважається двома крайовими перетинами, вводячи лише одну нову клітинку. Отже, ми компенсуємо відняттям кількості перетинів вершин. Це включає в себе точку на осях любить (r,0), а також Піфагор трійки , як (4,3)для r=5.

Підраховуємо за один квадрант точки (x,y)з x>=0і y>0з x*x+y*y==n, а потім множимо на 4. Це робимо, підраховуючи число sqrt(r*r-x*x)цього цілого числа xна проміжку [0,r).


5

Математика, 48 байт

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

Дивиться на перший квадрант і підраховує кількість комірок сітки, для яких вхід падає між нормами нижнього лівого та верхнього правого кутів комірки (звичайно, множивши результат на 4).


Інший метод 8#-SquaresR[2,#^2]Sign@#&заснований на посту xnor
милі

@miles О, уау, у мене не було поняття SquaresR. Сміливо публікуйте це (або дозвольте xnor опублікувати це).
Мартін Ендер


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 байт

->\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, щоб знайти всі поля, які будуть перетинати коло. Симетрія дозволяє помножити на 4. Може піти від -$1 to $1, але це займе більше байтів і буде менш ефективним. Очевидно, що це не найвищий час з алгоритмів, але для запуску корпусу 5525 на моїй машині потрібно лише 16 секунд.


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.


Радий, що я можу дещо надихнути когось :)
Роберт Бенсон,

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ітерацію, і всі спроби виходили однаковими байтами
Джордж Рейт,

@Neil Ах. Я бачу, про що ви говорите, k<n?...але я втрачаю ті байти, які перебувають у порядку, n**2-k++**2тому що пріоритет оператора помиляється, коли йдеш у зворотному напрямку, а віднімання не комутативне, тому ліва сторона завжди повинна мати k-1дужки і потребує дужок. Якщо ви не знайшли спосіб?
Джордж Рейт

Ах, я не помітив віднімання ... можливо, ви можете помножити всю справу на -4, а не на 4, щоб обійти це? (Хоча це все-таки може з'їсти у вашій економії ...)
Ніл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.