Счетная единица квадратов круг проходит через

24

Напишите программу или функцию, которая при заданном целочисленном радиусе r возвращает количество единичных квадратов, через которые проходит круг с радиусом r с центром в начале координат. Если круг проходит точно через точку на сетке, которая не считается проходящей через соседние единичные квадраты.

Вот иллюстрация для r = 5 :

иллюстрация Иллюстрация Киваля Нгаокражанга, найденная в OEIS

Примеры:

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

orlp
источник
@ Лука Я только что искал это, но, похоже, он использует немного другое определение (по крайней мере, с этим не согласен 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).

XNOR
источник
5

Mathematica, 48 байтов

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

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

Мартин Эндер
источник
Другой метод 8#-SquaresR[2,#^2]Sign@#&основан на сообщении xnor
миль
@ Майлз Ого, я понятия не имел, 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.
SMLS
источник
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
LevitatingLion
источник
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?
Нил
@Нейл, я пытался, но не видел пути. Хотелось использовать только одну функцию, но все же нужно было хранить и nрадиус, и kитерацию, и все попытки выходили из одних и тех же байтов
Джордж Райт
@Neil Ах, я понимаю, о чем вы говорите, k<n?...но я теряю эти байты при переупорядочении, n**2-k++**2потому что при обратном ходе оператор неверен, а вычитание некоммутативно, поэтому левой стороне всегда k-1нужны скобки. Если вы не нашли способ?
Джордж Райт
Ах, я пропустил вычитание ... может быть, вы можете умножить все это на -4 вместо 4, чтобы обойти это? (Хотя это все равно может съесть твои сбережения ...)
Нил