Đĩa nguyên nhỏ nhất


23

Thử thách này là về việc tìm đĩa nhỏ nhất có chứa một số điểm nhất định. Điều này được thực hiện có phần phức tạp hơn, tuy nhiên, bởi thực tế là trong thử thách này, cả tọa độ và bán kính của đĩa đều phải là số nguyên.

Đầu vào của bạn sẽ là một danh sách các điểm có tọa độ nguyên xy. Bạn có thể coi đây là danh sách các bộ dữ liệu, danh sách các danh sách hoặc bất kỳ cách nào khác để thể hiện một bộ sưu tập các cặp. xycả hai sẽ là số nguyên (có thể âm). Mỗi điểm được đảm bảo là duy nhất, và sẽ có ít nhất một điểm.

Đầu ra của bạn sẽ là một đĩa theo hình thức ba số, X, Y, và R. X, YRlà tất cả các số nguyên, XYđại diện cho trung tâm của đĩa và Rđại diện cho bán kính của nó. Khoảng cách giữa mọi điểm đã cho và tâm phải nhỏ hơn hoặc bằng Rvà không được tồn tại một đĩa như vậy với một đĩa nhỏ hơn Rcũng thỏa mãn điều kiện này.

Có thể sẽ có nhiều giải pháp khả thi cho một đầu vào nhất định, mã của bạn phải xuất ít nhất một trong số chúng trong trường hợp này.

Bạn có thể sử dụng bất kỳ loại tích hợp hình học nào mà ngôn ngữ của bạn hỗ trợ nếu có, và đầu vào / đầu ra có thể thông qua các đối tượng điểm / đĩa tích hợp thay vì chỉ các số.

Các trường hợp thử nghiệm

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)

Ít byte nhất sẽ thắng.



Tìm thấy một vài lỗi chính tả, nếu bạn không phiền tôi chỉ ra chúng: "Điều này được thực hiện phần nào lừa tôi ..."; "... đại diện cho trung tâm của đĩa và R đại diện cho i t bán kính s ..."; "... và không được tồn tại một đĩa như vậy ..."
J. Sallé

2
Thông thường làm cho mọi thứ số nguyên chỉ làm cho mã golf dễ dàng hơn.
dùng202729

@KevinCruijssen Đó là sự trùng hợp. Đầu vào có thể theo thứ tự bất kỳ.
Pavel

1
@Pavel Đầu vào có thể theo thứ tự nào, hoặc chúng ta có thể lấy đầu vào theo thứ tự nào? Như trong, đầu vào có thể theo thứ tự bất kỳ và chúng ta nên sắp xếp thủ công trước trong giải pháp của mình, hoặc chúng ta đã có thể lấy đầu vào được sắp xếp trước chưa?
Kevin Cruijssen

Câu trả lời:


6

Thạch , 25 24 22 21 20 18 byte

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

Cảm ơn @EriktheOutgolfer đã cho tôi biết ), tiết kiệm 1 byte.

Cảm ơn @Dennis đã lưu 2 byte.

Hãy thử trực tuyến!

Giải trình

«/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 Cảm ơn! Từ khi nào vector hóa của Jelly lặp lại danh sách ngắn hơn, hay tôi hiểu sai về việc loại bỏ ?
PurkkaKoodari

Độ sâu được khớp trước. Nếu bạn là một cặp và một mảng các cặp, cặp đó sẽ được khớp với tất cả các cặp.
Dennis

8

Brachylog v2, 19 byte

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

Hãy thử trực tuyến!

Chương trình này rất dễ viết - Brachylog gần như hoàn hảo cho loại vấn đề này - nhưng khó chơi gôn. Tôi sẽ không ngạc nhiên nếu có một byte tiết kiệm ở đâu đó ở đây, vì một vài điều tôi đã làm dường như có bất kỳ ảnh hưởng nào (và nó chứa các hướng dẫn bản đồ lồng nhau, thông thường là một dấu hiệu cho thấy bạn nên sử dụng thành viên / findall, nhưng tôi không thể xem một cách để làm điều đó).

Đây là một đệ trình chức năng. Đầu vào là từ đối số bên trái đến chức năng trong định dạng [[x,y],[x,y],…], đầu ra từ đối số bên phải trong biểu mẫu [r,[[x,y]]]. (Nếu bạn muốn thử số âm trong đầu vào, lưu ý rằng Brachylog sử dụng _cho dấu trừ, không phải vậy -. Điều này gây nhầm lẫn bởi vì hàm → trình bao bọc chương trình đầy đủ mà Brachylog gửi kèm, được yêu cầu sử dụng đối số dòng lệnh Z, sẽ hiển thị số âm trong đầu ra với dấu trừ thông thường.)

Giải trình

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

Điều này thú vị ở chỗ chúng tôi yêu cầu Brachylog tìm giá trị của một số thuộc tính nhất định (trong trường hợp này là bán kính của đĩa tập trung tại điểm Aphù hợp với tất cả các điểm đầu vào), nhưng hầu như không đặt bất kỳ yêu cầu nào lên nó (tất cả những gì chúng tôi yêu cầu là bán kính là một số). Tuy nhiên, Brachylog sẽ tính toán bên trong bán kính theo câu hỏi một cách tượng trưng thay vì cố gắng sử dụng các con số cụ thể, vì vậy khi đạt được kết quả cuối cùng , nó sẽ thực hiện hai điều cùng một lúc: đầu tiên, nó đảm bảo rằng chỉ các số nguyên được sử dụng cho tọa độ Avà cho bán kính (buộc bán kính bình phương là một số vuông và giải thích việc sử dụng ≤ᵛđể tìm "tối đa hoặc lớn hơn"); thứ hai, nó tìm thấy bán kính khả thi nhỏ nhất có thể (vì bán kính đứng đầu trong đầu ra).

Một điều không được chỉ định trong chương trình là tất cả các điểm được đo theo cùng một tâm của đĩa; như đã viết, không có ràng buộc nào mà chúng tôi không sử dụng một trung tâm khác nhau cho mỗi điểm. Tuy nhiên, thứ tự tiebreak (trong trường hợp này được đặt bởi thứ ba và là một ràng buộc cấu trúc sẽ được đánh giá trước khi ràng buộc giá trị ngụ ý ) muốn Acàng ngắn càng tốt (nghĩa là một phần tử duy nhất, vì vậy chúng tôi sử dụng cùng một trung tâm mỗi lần, nó thử độ dài bằng 0 Atrước nhưng điều đó rõ ràng không hoạt động, vì vậy nó sẽ thử một danh sách đơn tiếp theo). Kết quả là, cuối cùng chúng tôi nhận được một ràng buộc hữu ích (rằng chúng tôi chỉ có một đĩa) "miễn phí".

Giải pháp này xảy ra để khái quát hóa cho bất kỳ số lượng kích thước nào , không có thay đổi đối với mã nguồn; không có giả định nào ở đây rằng mọi thứ là hai chiều. Vì vậy, nếu bạn tình cờ cần quả cầu nguyên nhỏ nhất, bạn cũng có thể có nó.


3

Perl 6 , 81 byte

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

Hãy thử trực tuyến!

Lấy danh sách các điểm dưới dạng danh sách 2 yếu tố ((X1, Y1), (X2, Y2), ...). Trả về một danh sách (R, (X, Y)). Sử dụng cách tiếp cận tương tự như câu trả lời Jelly của 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.

Các minmaxphương pháp rất hữu ích ở đây là nó trả về một Range. Sản phẩm của Cartesian có phạm vi trực tiếp mang lại tất cả các điểm có tọa độ nguyên.


2

05AB1E , 26 byte

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

Câu trả lời Jelly của cảng @ Pietu1998 .

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

ø                    # 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

Matlab, 73 byte

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

Đơn giản chỉ cần tìm giải pháp nhỏ nhất (điểm nổi) và làm tròn đến điểm gần nhất và trần bán kính (trường hợp xấu nhất cho vấn đề minimax). Tôi không biết chắc chắn liệu điều đó có mang lại giải pháp chính xác cho tất cả các trường hợp có thể xảy ra hay không (trong độ chính xác), nhưng đối với các trường hợp kiểm tra thì nó sẽ hoạt động (nếu tôi không mắc lỗi đánh máy).

Gọi nó với

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)

Bạn đã đúng, nhưng đầu ra của fminimax là [0,500000211699422 0.499999788525202], vì vậy nó làm tròn chính xác. Vì vậy, tôi may mắn ở đây. Tôi hiện đang suy nghĩ làm thế nào để vượt qua vấn đề này (vì nó chỉ hoạt động bằng may mắn thuần túy).
Jonas

2

Pyth , 34 33 byte

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

Đầu ra ở dạng [R,x,y]

Dùng thử trực tuyến tại đây hoặc xác minh tất cả các trường hợp thử nghiệm cùng một lúc tại đâ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

Chỉnh sửa: Đã lưu một byte bằng cách sắp xếp lại định dạng đầu ra, phiên bản trước:

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


2

Ngôn ngữ Wolfram (Mathicala) , 66 byte

Đây là một cách tiếp cận vũ phu. Tôi đã xem xét BoundingRegion[#,"MinDisk"]&hàm ngắn hơn nhiều nhưng không có cách nào để buộc tọa độ và bán kính nguyên.

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

Hãy thử trực tuyến!


Tốt đẹp. Nhưng, làm thế nào về {Round@#[[1]], Ceiling@#[[2]]} &@BoundingRegion[#, "MinDisk"]&?
DavidC

@DavidC, làm tròn trung tâm có thể di chuyển nó lên tới Sqrt [2] /2=.707 nhưng lấy trần sẽ không nhất thiết phải thêm đủ chiều dài vào bán kính để chống lại điều đó. Tôi nghĩ một ví dụ về sự thất bại đó sẽ chỉ là hai điểm {{0,0}, {11,11}}
Kelly Lowder

Tôi hiểu ý bạn là gì!
DavidC

2

Java 10, 283 279 277 257 byte

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 byte nhờ vào mẹo sử dụng của @nwellnhofMath.hypot .

Mảng kết quả theo thứ tự [R,X,Y] .

Hãy thử trực tuyến.

Giải trình:

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
Bạn có thể lưu ít nhất 8 byte với Math.hypot.
nwellnhof

@nwellnhof Ah, hoàn toàn quên mất Math.hypot, đó là hoàn hảo cho thử thách này! -20 byte ngay tại đó. Cảm ơn. :)
Kevin Cruijssen

1

Javascript, 245 byte

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

(Một chút) phiên bản dễ đọc hơn:

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

Chỉ cần tìm hộp giới hạn và kiểm tra từng tọa độ trong hộp đó xem nó có tốt nhất không.

Tôi có thể lưu 8 byte bằng một câu trả lời gần đúng, bằng cách thay thế:

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


Chắc chắn có nhiều thứ hơn để chơi gôn, nhưng JS không phải là bộ mạnh mẽ của tôi. Tuy nhiên, bạn có thể chơi golf 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);. Và tôi khá chắc chắn rằng bạn có thể loại bỏ không gian tại return[.
Kevin Cruijssen

1
Bạn có thể có thể lưu một vài byte bằng cách sử dụng Math.hypot.
nwellnhof


1

Than , 65 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Giải trình:

≔Eθ§ι¹ζ

Lấy tọa độ y vào z.

≔Eθ§ι⁰η

Lấy tọa độ x vào h.

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

Lặp lại các phạm vi bao gồm từ mức tối thiểu đến mức tối đa hztạo danh sách tất cả các trung tâm đĩa tiềm năng.

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

Lặp lại tất cả các tâm đĩa, sau đó lặp qua tất cả các điểm ban đầu, sau đó lặp qua cả hai tọa độ, trừ, bình phương, tổng, lấy tối đa và lưu danh sách kết quả.

I§υ⌕η⌊η

Tìm vị trí của đường kính tối đa tối thiểu và in tâm đĩa tương ứng.

I⌈X⌊η·⁵

In đường kính tối đa tối thiểu, nhưng làm tròn nó đến số nguyên tiếp theo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.