Найменший цілий диск


23

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

Вашим входом буде список точок з цілими координатами xта y. Ви можете взяти це як список кортежів, список списків або будь-який інший спосіб представити колекцію пар. xі yобидва будуть (можливо негативними) цілими числами. Кожен пункт гарантовано буде унікальним, і буде хоча б один бал.

Ваш вихід буде диск у вигляді трьох чисел, X, Y, і R. X, YІ Rвсе цілі числа, Xі Yпредставляють центр диска і Rпредставляють його радіус. Відстань між кожною заданою точкою та центром має бути меншою або дорівнює R, і не повинно існувати такий диск з меншим розміром, Rякий також задовольняє цій умові.

Можливо, що для даного входу буде кілька можливих рішень, ваш код повинен вивести принаймні одне з них у цьому випадку.

Ви можете використовувати будь-які види вбудованої геометрії, яку підтримує ваша мова, якщо такі є, а введення / вихід може здійснюватися через вбудовані об'єкти точки / диска, а не просто числа.

Випробування

Input   (Possible) Output(s)
(x,y)   (X,Y,R)
-------------------------
(0,0)   (0,0,0)
-------------------------
(0,1)   (0,0,1)
(1,0)   (1,1,1)
-------------------------
(1,4)   (4,4,3)
(3,2)
(4,1)
(4,5)
(5,2)
(7,4)
-------------------------
(-1,0)  (0,0,2)
(2,0)   (1,0,2)
-------------------------
(-1,0)  (1,0,2)
(2,1)   (0,1,2)
-------------------------
(0,0)   (1,0,1)
(1,1)   (0,1,1)

Виграє найменше байт.



Знайшов пару помилок, якщо ви не заперечуєте проти того, щоб я вказав на них: "Це зроблено дещо хитрістю, я ..."; "... представляє центр диска, а R являє радіус i t s ..."; "... і такого диска не повинно існувати ..."
Дж. Салле

2
Зазвичай створення цілих значень просто полегшує код-гольф.
користувач202729

@KevinCruijssen Це за збігом обставин. Введення даних може бути в будь-якому порядку.
Павло

1
@Pavel Вхід може бути в будь-якому порядку, або ми можемо взяти вхід у будь-якому порядку? Як і в, введення може бути в будь-якому порядку, і ми повинні вручну сортувати спочатку в нашому рішенні, чи ми можемо вже взяти вхід заздалегідь відсортований?
Кевін Кройсейсен

Відповіді:


6

Желе , 25 24 22 21 20 18 байт

«/r»/Œpµ³_²§½ṀĊ,)Ṃ

Завдяки @EriktheOutgolfer за те, що повідомив мені про це ), заощадивши 1 байт.

Дякуємо @Dennis за збереження 2 байт.

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

Пояснення

«/r»/Œpµ³_²§½ṀĊ,)Ṃ      Main link. Arg: points
                        e.g. [[1,4],[3,2],[3,1]]
«/                      Find minimums by coordinate
                        e.g. [1,1]
   »/                   Find maximums by coordinate
                        e.g. [3,4]
  r                     Inclusive ranges by coordinate
                        e.g. [[1,2,3],[1,2,3,4]]
     Œp                 Cartesian product of the x and y ranges
                        e.g. [[1,1],[1,2],[1,3],[1,4],...,[3,4]]
       µ                    Chain, arg: center
                            e.g. [1,3]
        ³                   Get the original points
                            e.g. [[1,4],[3,2],[3,1]]
         _                  Subtract the center from each
                            e.g. [[0,1],[2,-1],[2,-2]]
          ²                 Square each number
                            e.g. [[0,1],[4,1],[4,4]]
           §                Sum each sublist
                            e.g. [1,5,8]
            ½               Square root of each number
                            e.g. [1,2.24,2.83]
             Ṁ              Find the maximum
                            e.g. 2.83
              Ċ             Round up
                            e.g. 3
               ,            Pair with the center point
                            e.g. [3,[1,3]]
                )       Do the above for all points
                        e.g. [[3,[1,1]],[3,[1,2]],[3,[1,3]],...,[3,[3,4]]]
                 Ṃ      Find the lexicographically smallest pair
                        e.g. [3,[1,1]]

@Dennis Дякую! З тих пір, коли векторизація Jelly повторила коротший список, чи я неправильно трактую видалення ?
PurkkaKoodari

Глибини узгоджуються спочатку. Якщо у вас є пара і масив пар, пара поєднується з усіма парами.
Денніс

8

Brachylog v2, 19 байт

;Az{\-ᵐ~√ᵐ+}ᵐ≤ᵛ√;A≜

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

Цю програму було легко написати - Брахілог майже ідеальний для подібних проблем - але важко гольфу. Мене не здивувало б, якби десь тут було збереження байтів, так як деякі речі, які я робив, здавались, що справляють будь-який ефект (і він містить вкладені вказівки по карті, як правило, знак того, що ви повинні використовувати член / findall, але я не можу бачити спосіб це зробити).

Це подання функції. Введення - від лівого аргументу до функції у форматі [[x,y],[x,y],…], виведення з правого аргументу у формі [r,[[x,y]]]. (Якщо ви хочете спробувати негативні цифри на вході, зауважте, що Brachylog використовує _для знаку мінус, ні -. Це заплутано, оскільки функція → повна програмна обгортка, до якої надходить Брахілог, запитується за допомогою аргументу командного рядка Z, представлятиме негативні числа у висновку зі знаком регулярний мінус.)

Пояснення

;Az{\-ᵐ~√ᵐ+}ᵐ≤ᵛ√;A≜
;A                   Append something
  z                    to every element of the input
   {       }ᵐ        such that for each resulting element:
     -                 Subtracting
    \ ᵐ                  corresponding elements {of the (input, appended) element}
       ~√              and un-squarerooting
         ᵐ               {the result of} each {subtraction}
          +            and summing {the resulting square numbers}
             ≤       {lets us find} a number at least as large as
              ᵛ        every element {of the list of sums}
               √     which can be square-rooted;
                ;A   append the same list as initially to it.
                  ≜  Find the first integer solution to the above, lexicographically.

Це цікаво тим, що ми просимо Брахілог знайти значення певних властивостей (у цьому випадку радіус диска, центрований у точці, Aщо відповідає всім точкам входу), але навряд чи висуває до нього жодні вимоги (все, що нам потрібно, це що радіус - це число). Однак Брахілог внутрішньо обчислить відповідний радіус символічно, а не намагається використовувати конкретні числа, тож коли буде досягнутий фінал , він виконує одразу дві речі: по-перше, він гарантує, що для координат Aта радіусу використовуються лише цілі числа. (змушуючи радіус квадрата бути квадратним числом і пояснювати використання ≤ᵛзнаходження «максимум чи більше»); по-друге, він знаходить найменший можливий радіус (оскільки радіус поступає першим на виході).

Одне, що зовсім не вказано в програмі, - це те, що всі точки вимірюються в одному центрі диска; як написано, немає обмежень, що ми не використовуємо інший центр для кожної точки. Однак порядок зв'язування (який у цьому випадку встановлюється третім і який як обмеження структури буде оцінено до обмеження значення, яке мається на увазі ) хоче Aбути максимально коротким (тобто одним елементом, тому ми використовуємо той самий централізуйте кожен раз; він спробує Aспершу нульову довжину, але це, очевидно, не працює, тому він намагається переглянути однотонний список далі). В результаті ми отримуємо корисне обмеження (що у нас є лише один диск) "безкоштовно".

Це рішення узагальнюється до будь-якої кількості вимірів , без змін у вихідному коді; тут немає припущень, що речі двовимірні. Тож якщо вам трапиться потрібна найменша ціла сфера, ви можете мати і це.


3

Perl 6 , 81 байт

{min [X]([Z]($^p)>>.minmax).map:{$p.map({(@_ Z-$_)>>².sum**.5}).max.ceiling,$_}}

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

Приймає список точок як двоелементні списки ((X1, Y1), (X2, Y2), ...). Повертає список (R, (X, Y)). Використовується той самий підхід, що і відповідь «Желе» Pietu1998:

[X]([Z]($^p)>>.minmax)  # All possible centers within the bounding box
.map:{ ... }            # mapped to
$p.map({(@_ Z-$_)>>².sum**.5}).max  # maximum distance from any point
.ceiling                # rounded up,
,$_                     # paired with center.
min                     # Find minimum by distance.

minmaxМетод корисний тут , як це повертає Range. Декартовий добуток діапазонів безпосередньо дає всі точки з цілими координатами.


2

05AB1E , 26 байт

øεWsàŸ}`âεUIεX-nOt}àîX‚}{н

Порт @ Pietu1998 Jelly відповіді «s .

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

ø                    # Zip the (implicit) input, swapping the rows and column
                     #  i.e. [[1,4],[3,2],[3,1]] → [[1,3,3],[4,2,1]]
 ε    }              # Map each to:
  W                  #  Push the smallest value (without popping the list)
                     #   i.e. [[1,3,3],[4,2,1]] → [1,1]
   s                 #  Swap so the list is at the top of the stack again
    à                #  Pop the list and push the largest value
                     #   i.e. [[1,3,3],[4,2,1]] → [3,4]
     Ÿ               #  Take the inclusive range of the min and max
                     #   i.e. [[1,2,3],[1,2,3,4]]
`                    # After the map, push both lists separated to the stack
 â                   # And take the cartesian product of the two lists
                     #  i.e. [[1,2,3],[1,2,3,4]]
                     #   → [[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[2,4],[3,1],[3,2],[3,3],[3,4]]
  ε             }    # Map each pair to:
   U                 #  Pop and store the current value in variable `X`
    I                #  Push the input
     ε     }         #  Map each pair in the input to:
      X              #   Push variable `X`
       -             #   Subtract it from the current pair
                     #    i.e. [3,2] - [1,3] → [2,-1]
        n            #   Take the square of each
                     #    i.e. [2,-1] → [4,1]
         O           #   Sum the lists
                     #    i.e. [4,1] → 5
          t          #   Take the square-root of each
                     #    i.e. 5 → 2.23606797749979
            à        #  Pop the converted list, and push its largest value
                     #   i.e. [[3.0,2.23606797749979,2.0],[2.0,2.0,2.23606797749979],...,[2.0,2.0,3.0]]
                     #    → [3.0,2.23606797749979,...,3.0]
             î       #  Round it up
                     #   i.e. [3.0,2.23606797749979,...,3.0] → [3.0,3.0,3.0,4.0,4.0,3.0,3.0,4.0,4.0,3.0,3.0,3.0]
              X     #  Pair it with variable `X`
                     #   i.e. [[3.0,[1,1]],[3.0,[1,2]],...,[3.0,[3,4]]]
                 {   # After the map, sort the list
                  н  # And take the first item (which is output implicitly)
                     #  i.e. [[3.0,[1,1]],[3.0,[1,2]],...,[3.0,[3,4]]] → [3.0,[1,1]]

2

Матлаб, 73 байти

function g(x);[r,~,d]=fminimax(@(a)pdist2(x,a),[0 0]);[round(r) ceil(d)]

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

Телефонуйте за допомогою

g([1 4;3 2;4 1;4 5;5 2;7 4])

(0,0),(1,1)fminimax(0,5,0,5)(1,1)2/21(0,0)

Ви маєте рацію, але вихід fminimax становить [0,500000211699422 0.499999788525202], тож він правильний. Тож мені пощастило тут. Наразі я думаю про те, як обійти цю проблему (адже це працює лише від чистої долі).
Йонас

2

Pyth , 34 33 байт

hSm+.EeSm@s^R2-Vdk2Qd*Fm}FhM_BSdC

Вихід у формі [R,x,y]

Спробуйте в Інтернеті тут або одразу підтвердіть усі тестові випадки тут .

hSm+.EeSm@s^R2-Vdk2Qd*Fm}FhM_BSdCQ   Implicit: Q=eval(input())
                                     Trailing Q inferred
                                CQ   Transpose (group x and y coordinates separately)
                       m             Map each in the above, as d, using:
                              Sd       Sort d
                            _B         Pair with its own reverse
                          hM           Take the first element of each, yielding [min, max]
                        }F             Generate inclusive range
                     *F              Cartesian product of the above two lists, yielding all coordinates in range
  m                                  Map each coordinate in the above, as d, using:
        m          Q                   Map each coordinate in input, as k, using:
              -Vdk                       Take the difference between x and y coordinates in d and k
           ^R2                           Square each
          s                              Sum
         @        2                      Take the square root
      eS                               Take the largest of the result
    .E                                 Rounded up
   +                d                  Prepend to d
 S                                   Sort the result, first element as most significant
h                                    Take first element

Редагувати: збережений байт шляхом перестановки вихідного формату, попередня версія:

heDm+d.EeSm@s^R2-Vdk2Q*Fm}FhM_BSdC


2

Мова Вольфрама (Mathematica) , 66 байт

Ось підхід грубої сили. Я вважав набагато коротшу BoundingRegion[#,"MinDisk"]&функцію, але немає можливості примусити цілі координати та радіус.

Minimize[{r,RegionWithin[{x,y}~Disk~r,Point@#]},{x,y,r},Integers]&

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


Приємно. Але, як же {Round@#[[1]], Ceiling@#[[2]]} &@BoundingRegion[#, "MinDisk"]&?
DavidC

@DavidC, округлення центру може перенести його до Sqrt [2] /2=.707, але взяття стелі не обов'язково додасть достатньої довжини до радіусу, щоб протидіяти цьому. Я думаю, що прикладом цього невдачі можуть бути лише два пункти {{0,0}, {11,11}}
Келлі Лоудер

Я бачу, що ти маєш на увазі!
DavidC

2

Java 10, 283 279 277 257 байт

C->{int M=1<<31,m=M,X=M,Y=M,x=M-1,y=x,t,a,b,r[]={x};for(var c:C){x=(t=c[0])<x?t:x;X=t>X?t:X;y=(t=c[1])<y?t:y;Y=t>Y?t:Y;}for(;y<=Y;y++)for(t=x;t<=X;r=m<r[0]?new int[]{m,t,y}:r,m=M,t++)for(var c:C){a=c[0]-t;b=c[1]-y;a*=a;m=(a=(int)Math.ceil(Math.sqrt(a+=b*=b)))>m?a:m;}return r;}

-20 байт завдяки підказці @nwellnhof щодо використання Math.hypot.

Масив результатів у порядку [R,X,Y].

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

Пояснення:

C->{                  // Method with 2D int-array as parameter & int-array as return-type
  int M=1<<31,        //  Minimum `M`, starting at -2,147,483,648
      m=M,            //  Temp integer, starting at -2,147,483,648 as well
      X=M,            //  Largest X coordinate, starting at -2,147,483,648 as well
      Y=M,            //  Largest Y coordinate, starting at -2,147,483,648 as well
      x=M-1,          //  Smallest X coordinate, starting at 2,147,483,647
      y=x,            //  Smallest Y coordinate, starting at 2,147,483,647 as well
      t,a,            //  Temp integers, starting uninitialized
      r[]={x};        //  Result-array, starting at one 2,147,483,647
  for(var c:C){       //  Loop over the input-coordinates
    x=(t=c[0])<x?t:x; //   If the X coordinate is smaller than `x`, change it
    X=t>X?t:X;        //   If the X coordinate is larger than `X`, change it
    y=(t=c[1])<y?t:y; //   If the Y coordinate is smaller than `y`, change it
    Y=t>Y?t:Y;}       //   If the Y coordinate is larger than `Y`, change it
 for(;y<=Y;y++)       //  Loop `y` in the range [`y`,`Y`]:
   for(t=x;t<=X       //   Inner loop `t` in the range [`x`,`X`]:
          ;           //     After every iteration:
           r=m<r[0]?  //      If `m` is smaller than the first value:
              new int[]{m,t,y}
                      //       Replace the result with `m,t,y`
             :        //      Else:
              r,      //       Leave `r` unchanged
           m=M,       //      Reset `m` to -2,147,483,648 for the next iteration
           t++)       //      And increase `t` by 1
     for(var c:C)     //    Inner loop over the input-coordinates
       m=(a=(int)Math.ceil(Math.hypot(c[0]-t,c[1]-y)))
                      //     Subtract `t` from the X coordinate;
                      //     subtract `y` from the Y coordinate;
                      //     take the hypot (<- sqrt(x*x+y*y)) of those
                      //     ceil it
                      //     And set `a` to this value
          >m?         //     If `a` is larger than `m`:
           a          //      Set `m` to `a`
          :           //     Else:
           m;         //      Leave `m` unchanged
  return r;}          //  Return the result `r`

1
Ви можете зберегти принаймні 8 байт за допомогою Math.hypot.
nwellnhof

@nwellnhof Ах, зовсім забув про те Math.hypot, що ідеально підходить для цього виклику! -20 байт прямо там. Спасибі. :)
Кевін Кройсейсен

1

Javascript, 245 байт

a=>{[b,c,d,e]=a.reduce(([j,k,l,m],[h,i])=>[j>h?j:h,k<h?k:h,l>i?l:i,m<i?m:i],[,,,,]);for(f=c;f<b;f++){for(g=e;g<d;g++){s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);n=n?n[2]>s?[f,g,s]:n:[f,g,s]}}return [n[0],n[1],Math.ceil(Math.sqrt(n[2]))]}

(Дещо) більш читаною версією:

a=>{
    [b,c,d,e]=a.reduce(([j,k,l,m],[h,i])=>[j>h?j:h,k<h?k:h,l>i?l:i,m<i?m:i],[,,,,]);
    for(f=c;f<b;f++){
        for(g=e;g<d;g++){
            s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);
            n=n?n[2]>s?[f,g,s]:n:[f,g,s]
        }
    }
    return [n[0],n[1],Math.ceil(Math.sqrt(n[2]))]
}

Просто знаходить обмежувальне поле і перевіряє кожну координату в цьому полі на предмет найкращості.

Я міг би зберегти 8 байт з приблизною відповіддю, замінивши:

Math.ceil(Math.sqrt(n[2])) з ~~(n[2]+1-1e-9)


Напевно є більше речей для гольфу, але JS не мій сильний набір. Тим не менш, можна покататися for(f=c;f<b;f++){for(g=e;g<d;g++){s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);n=n?n[2]>s?[f,g,s]:n:[f,g,s]}}на гольфі for(f=c;f<b;f++)for(g=e;g<d;n=n?n[2]>s?[f,g,s]:n:[f,g,s],g++)s=a.reduce((o,[p,q])=>o>(r=(p-f)**2+(q-g)**2)?o:r);. І я впевнений, що ви можете прибрати простір у return[.
Кевін Кройсейсен

1
Можливо, ви можете зберегти кілька байтів за допомогою Math.hypot.
nwellnhof


1

Вугілля деревне , 65 байт

≔Eθ§ι¹ζ≔Eθ§ι⁰ηF…·⌊η⌈ηF…·⌊ζ⌈ζ⊞υ⟦ικ⟧≔Eυ⌈EθΣEιX⁻§λξν²ηI§υ⌕η⌊ηI⌈X⌊η·⁵

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

≔Eθ§ι¹ζ

Вставте координати у z.

≔Eθ§ι⁰η

Вставте координати x h.

F…·⌊η⌈ηF…·⌊ζ⌈ζ⊞υ⟦ικ⟧

Петля по інклюзивному діапазону від мінімумів до максимумів hі zгенерування списку всіх потенційних центрів дисків.

≔Eυ⌈EθΣEιX⁻§λξν²η

Проведіть петлю над усіма центрами дисків, потім переведіть петлю на всі початкові точки, потім переведіть на обидві координати, відніміть, квадрат, суму, візьміть максимум і збережіть отриманий список.

I§υ⌕η⌊η

Знайдіть положення мінімального максимального діаметра та роздрукуйте відповідний центр диска.

I⌈X⌊η·⁵

Роздрукуйте мінімальний максимальний діаметр, але округляйте його до наступного цілого числа.

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