Tính khoảng cách Hausdorff


21

Giới thiệu

Các khoảng cách Hausdorff đo sự khác biệt giữa hai tập con của một không gian metric. Theo trực giác, một không gian số liệu chỉ là một số được thiết lập với chức năng khoảng cách tích hợp; trong thử thách này, chúng ta sẽ sử dụng các số tự nhiên với khoảng cách thông thường d(a, b) := abs(a - b). Khoảng cách Hausdorff giữa hai tập hữu hạn không rỗng ABđược cho bởi

max(max(min(d(a, b) for b in B) for a in A),
    max(min(d(a, b) for a in A) for b in B))

trong ký hiệu giống như Python. Khoảng cách Hausdorff có thể được tính bằng cách tìm phần tử trong Ađó khoảng cách đến phần tử gần nhất Blà tối đa và phần tử Bmà khoảng cách đến phần tử gần nhất Alà tối đa, sau đó lấy tối đa các khoảng cách này. Nói cách khác, nếu khoảng cách Hausdorff là d, thì mọi phần tử Anằm trong khoảng cách dcủa một số phần tử Bvà ngược lại.

Đầu vào

Đầu vào của bạn là một danh sách các số nguyên. Nó chỉ chứa các yếu tố 0,1,2,3, trong đó biểu thị cho dù chỉ số nhất định của danh sách là một phần tử của không Acũng không B, chỉ có A, chỉ B, hoặc cả hai AB. Ví dụ: đầu vào [0,1,1,0,2,3]có nghĩa là A = {1,2,5}B = {4,5}, nếu chúng ta sử dụng lập chỉ mục dựa trên 0 (điều này không có sự khác biệt, vì các số liệu của chúng tôi là bất biến dịch).

Đầu ra

Đầu ra của bạn là khoảng cách Hausdorff giữa AB; trong ví dụ trên, nó là 3. Nếu một trong hai thiết lập là trống, thì khoảng cách không được xác định và bạn sẽ trả về -1.

Quy tắc

Bạn có thể viết một chương trình đầy đủ hoặc một chức năng. Số byte thấp nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

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

[] -> -1
[0] -> -1
[0,1,0] -> -1
[2,0,0,2] -> -1
[0,1,2,3] -> 1
[0,3,3,0,0,0,0,3] -> 0
[1,0,0,1,0,0,1,3,1] -> 7
[1,0,0,0,0,3,0,0,0,0,2] -> 5
[0,1,1,3,1,3,2,1,1,3,0,3] -> 2
[2,2,2,1,2,0,3,1,3,1,0,3] -> 3
[1,3,0,2,0,2,2,1,0,3,2,1,1,2,2] -> 2
[1,0,1,1,2,0,1,2,3,1,0,0,0,1,2,0] -> 4

Trong phương trình của bạn, tôi tin rằng nó quá dài, max(max(min(d(a, b) for b in B) for a in A))nên là đủ. Điều này là do d(a,b)trả về giá trị tuyệt đối và do đó cả hai hàm max sẽ trả về cùng một số mỗi lần.
Nathan Merrill

6
@NathanMerrill Có thể mọi yếu tố của Anó rất gần với một trong số đó B, nhưng có những yếu tố Brất xa A(ví dụ: nếu Alà tập con của B). Trong trường hợp đó, công thức ngắn là không chính xác.
Zgarb

Câu trả lời:


7

CJam, 53 52 46 38 37 byte

3,q~f{f&:L,{L=},}$~ff{-z}_z+::e<W+:e>

Lấy đầu vào trên STDIN dưới dạng mảng kiểu CJam:

[0 1 2 3]

Dưới đây là một khai thác thử nghiệm chuyển đổi tất cả các trường hợp thử nghiệm sang định dạng này và chạy mã trên chúng. Mặc dù kết quả nằm trong trường đầu vào, nhưng chúng không được sử dụng bởi mã (loại bỏ chúng nếu bạn không tin tưởng tôi :)).

Giải trình

Đầu tiên, chúng tôi phân tích cú pháp đầu vào để có được hai bộ A và B:

3,q~f{f&:L,{L=},}$~
3,                  "Push [0 1 2]. 1 is for A, 2 is for B, and 0 we can luckily ignore
                     as we'll see later.";
  q~                "Read and evaluate the input.";
    f{          }   "Map this block onto the [0 1 2] array, copying in the input for
                     each iteration.";
      f&:L          "Take the bitwise AND with each element of the input and store the
                     result in L.";
          ,{  },    "Get the length N, and filter the range [0 .. N-1] by evaluating
                     the block for each element.";
            L=      "Check if the bitwise AND at that index yielded something non-zero.
                     This gives an empty array for 0, A for 1 and B for 2.";
                 $  "Sort the three arrays. This has two important effects: a) it moves
                     the empty array resulting from 0 to the front, and b) if only one
                     of A and B is empty, it moves the non-empty one to the end.";
                  ~ "Unwrap the array, dumping all three sets on the stack.";

Và bây giờ chúng tôi tìm thấy sự khác biệt tuyệt đối và chọn tối đa của phút:

ff{-z}_z+::e<W+:e>
ff{-z}             "Turn A and B into a matrix of absolute differences.";
      _z           "Duplicate and transpose.";
        +          "Add the two together, so I've got one row of distances for
                    each element in either A or B.";
         ::e<      "Find the minimum of each row.";
             W+    "Add a -1 in case one set was empty.";
               :e> "Get the overall maximum.";

Lưu ý rằng chúng tôi đã giữ mảng trống kết quả từ ban đầu 0ở dưới cùng của ngăn xếp mọi lúc, nhưng các mảng trống không đóng góp gì cho đầu ra.


5

CJam, 57 56 52 byte

Tôi nghĩ rằng điều này có thể được chơi golf một chút, nhưng ở đây đi:

q~ee_{W=2%},\{W=1>},]0ff=_W%]{~ff-{:z$1<~}%W+$W=}/e>

Đầu vào đi vào như một danh sách theo kiểu của CJam, vd.

[1 0 0 0 0 3 0 0 0 0 2]

5

Cách thức hoạt động :

Mã được chia thành hai phần:

Phân tích cú pháp đầu vào vào danh sách AB:

q~ee_{W=2%},\{W=1>},]0ff=_W%]
q~                               "Eval the input array";
  ee                             "Enumerate and prepend index with each element. For ex:
                                  [5 3 6]ee gives [[0 5] [1 3] [2 6]]";
    _{W=2%},                     "Make a copy and filter out elements with value 1 or 3";
            \{W=1>},             "On the original, filter elements with value 2 or 3";
                    ]            "Wrap stack in an array. Stack right now contains
                                  enumerated A and B in an array";
                     0ff=        "Get the index of the enumerated arrays. Stack is [A B]";
                         _W%     "Make a copy and swap order. Stack is now [A B] [B A]";
                            ]    "Wrap this in an array";

Thực hiện các hành động cần thiết trên hai cặp AB:

{~ff-{:z$1<~}%W+$W=}/e>
{                  }/            "Run this loop for both the pairs, [A B] and [B A]"
 ~ff-                            "Unwrap [A B] and take difference of every pair";
     {      }%                   "For each row in the matrix difference";
      :z$                        "abs each term and then sort";
         1<~                     "Take only the first element of the array";
              W+                 "Add -1 to compensate for an empty array";
                $W=              "Take max";
                     e>          "Take max of the two maximums";

Dùng thử trực tuyến tại đây


5

Lua, 235 byte

Chắc chắn không phải là một người chiến thắng, nhưng ít nhất là một thử thách thú vị.

A={}B={}c={}d={}m=math p=m.min q=m.max u=unpack for k=1,#arg do for h=0,1 do if
arg[k]/2^h%2>=1 then A[#A+1]=k for i=1,#B do l=m.abs(B[i]-k)d[i]=p(d[i]or
l,l)c[#A]=p(c[#A]or l,l)end end A,B=B,A c,d=d,c end end
print(q(q(-1,u(c)),u(d)))

Đầu vào hoạt động như vậy:

lua hausdorff.lua <space-separated-sequence>

... và đây là một kịch bản thử nghiệm:

local testcase = arg[1] or 'hausdorff.lua'
print('testing '..testcase)
local function run(args) 
    return function(expected)
        local result = tonumber(
            io.popen('lua.exe '..testcase..' '..args):read'*a':match'%S+')
        print(args..' -> '..expected..' :: '..result)
        assert(result == expected,
            ("for input %q expected %s but got %s"):format(
                args, expected, result))
    end
end
run''(-1)
run'0'(-1)
run'0 1 0'(-1)
run'2 0 0 2'(-1)
run'0 1 2 3'(1)
run'0 3 3 0 0 0 0 3'(0)
run'1 0 0 1 0 0 1 3 1'(7)
run'1 0 0 0 0 3 0 0 0 0 2'(5)
run'0 1 1 3 1 3 2 1 1 3 0 3'(2)
run'2 2 2 1 2 0 3 1 3 1 0 3'(3)
run'1 3 0 2 0 2 2 1 0 3 2 1 1 2 2'(2)
run'1 0 1 1 2 0 1 2 3 1 0 0 0 1 2 0'(4)

... sản xuất ...

testing hausdorff.lua
 -> -1 :: -1
0 -> -1 :: -1
0 1 0 -> -1 :: -1
2 0 0 2 -> -1 :: -1
0 1 2 3 -> 1 :: 1
0 3 3 0 0 0 0 3 -> 0 :: 0
1 0 0 1 0 0 1 3 1 -> 7 :: 7
1 0 0 0 0 3 0 0 0 0 2 -> 5 :: 5
0 1 1 3 1 3 2 1 1 3 0 3 -> 2 :: 2
2 2 2 1 2 0 3 1 3 1 0 3 -> 3 :: 3
1 3 0 2 0 2 2 1 0 3 2 1 1 2 2 -> 2 :: 2
1 0 1 1 2 0 1 2 3 1 0 0 0 1 2 0 -> 4 :: 4

4

Pyth, 43 40 39 38 byte

J+m0yQQLq3.|Fb?eS.e&Yfy:J-kT+hkT0JyJ_1

Thuật toán của tôi hoạt động trực tiếp trên chuỗi đầu vào và không bao giờ chuyển đổi các số này. Nó chỉ tính một lần tối đa và không bao giờ tối thiểu.

Cảm ơn @isaacg đã lưu một byte.

Dùng thử trực tuyến: Trình biên dịch / thực thi Pyth

Giải thích:

Đầu tiên tôi sẽ chèn rất nhiều số không vào trước đầu vào.

          implicit: Q = input()
    yQ    powerset(Q)
  m0yQ    map each element of the powerset to 0 (creates 2^Q zeros, I said lots)
 +    Q   zeros + Q
J         assign to J

Sau đó, tôi xác định một hàm trợ giúp y, cho biết nếu các chỉ mục của danh sách (như đầu vào) xuất hiện trong cả hai bộ A và BEg y([0, 1, 0, 0, 1, 1]) = False, nhưng y([0, 1, 0, 2]) = y([3]) = True.

Lq3.|Fb
L          define a function y(b), which returns _
   .|Fb       fold b by bitwise or
 q3            == 3

Sau đó tôi kiểm tra trước nếu kết quả là -1.

?...yJ_1   print ... if numbers appear in both sets (`yJ`) else -1   

Bây giờ đến những thứ thú vị:

  .e              J    map each pair k,Y in enumerate(J) to:
    &Y                   Y and ... (acts as 0 if Y == 0 else ...)
      f          0       find the first number T >= 0, where:
       y                    indices appear in both sets in the substring
        :J-kT+hkT           J[k-T:k+T+1]
eS                     sort and take last element (maximum)

Lưu ý rằng tôi sẽ luôn tìm thấy một số T, vì tôi đã biết rằng các chỉ số xuất hiện trong cả hai bộ trong danh sách J. Số này là tối đa length(Q). Đây cũng là lý do để chèn các số không. Nếu có ít nhất các length(Q)số 0 được chèn, k-Tluôn luôn >= 0, điều này là cần thiết cho việc cắt danh sách. Vậy tại sao tôi chèn 2^length(Q)số không thay vì length(Q)số không? Trong trường hợp thử nghiệm []tôi cần ít nhất 1 0, nếu không yJsẽ trả về lỗi.


><Cab giống như :Cba .
isaacg

Thật tốt khi các trường hợp thử nghiệm không bao gồm đầu vào lớn ...
TLW

3

Toán học, 88 byte

Max[Min/@#,Min/@Thread@#,-1]/.∞->-1&@Outer[Abs[#-#2]&,p=Position;p[#,1|3],p[#,2|3],1]&

1
Câu trả lời rất hay. Để tìm hiểu tổng quát hơn về khoảng cách Hausdorff, người ta có thể sử dụng m=MaxValue;Max[m[RegionDistance[#[[1]],s],s\[Element]#[[2]]]/.m[__]->-1&/@{#,Reverse@c}]& mà sau đó có thể được áp dụng cho các đối tượng đa chiều như vậy%@{Sphere[],Line[{{1,1,0},{3,3,3}}]}
Kelly Lowder

3

Haskell, 145 126 124 byte

s t x=[e|(e,i)<-zip[0..]x,t i]
d#e=maximum[minimum[abs$i-j|j<-e]|i<-d]
[]%_= -1
_%[]= -1
d%e=max(d#e)$e#d
f x=s(>1)x%s odd x

Chạy thử nghiệm:

*Main> map f [[], [0], [0,1,0], [2,0,0,2], [0,1,2,3],
              [0,3,3,0,0,0,0,3], [1,0,0,1,0,0,1,3,1],
              [1,0,0,0,0,3,0,0,0,0,2], [0,1,1,3,1,3,2,1,1,3,0,3],
              [2,2,2,1,2,0,3,1,3,1,0,3],
              [1,3,0,2,0,2,2,1,0,3,2,1,1,2,2],
              [1,0,1,1,2,0,1,2,3,1,0,0,0,1,2,0]]

[-1,-1,-1,-1,1,0,7,5,2,3,2,4]

slọc các số tự nhiên theo một vị ngữ tvà danh sách đầu vào x. #tính toán khoảng cách tối đa của các tham số de.%bắt các bộ trống A hoặc B hoặc lấy tối đa cuối cùng của d#ee#d. flà hàm chính gọi %với tập A và B.

Chỉnh sửa: @Zgarb tìm thấy rất nhiều byte để lưu; @ ali0sha khác 2. Cảm ơn!


mod 2vẻ như không cần thiết. Bạn cũng có thể được hưởng lợi từ việc không xác định abrõ ràng.
Zgarb

bạn có thể tiết kiệm 2 byte với []%_= -1- nhưng bạn đã đánh bại nỗ lực của tôi về điều này :)
alexander-brett

3

Perl, 56 55

Đã thêm +2 cho -lp.

Danh sách đầu vào phải được đưa ra trên stdin không có khoảng trắng, ví dụ:

echo 1011201231000120 | perl -lp hausdorf.pl

hausdorf.pl:

s%%$z=$_&=$p|=$'|P.$p;$q+=!!y/12/3/%eg;$_=$z=~3?$q:-1

Để hỗ trợ khoảng trắng giữa các thành phần của danh sách đầu vào, chỉ cần chia số cuối cùng $qcho 2 với chi phí là 2 nét


2

Con trăn 2, 124

Điều này chắc chắn cảm thấy tối ưu. Ồ tốt

lambda a,E=enumerate:-min([1]+[~l*(n<3)for i,n in E(a)for l,_ in E(a)if{0}|set(n*a+n/3*[5])>{0,n}>=set(a[max(i-l,0):i-~l])])

1

APL (49)

{(⊂⍬)∊∆←(↓2 2⊤⍵)/¨⊂⍳⍴⍵:¯1⋄⌈/{⌈/⌊/⍵}¨(+,⍉¨)|∘.-/∆}

Testcase:

      ({(⊂⍬)∊∆←(↓2 2⊤⍵)/¨⊂⍳⍴⍵:¯1⋄⌈/{⌈/⌊/⍵}¨(+,⍉¨)|∘.-/∆} ¨ testcases) ,⍨ '→',⍨ ↑ ⍕¨testcases
                               → ¯1
0                              → ¯1
0 1 0                          → ¯1
2 0 0 2                        → ¯1
0 1 2 3                        →  1
0 3 3 0 0 0 0 3                →  0
1 0 0 1 0 0 1 3 1              →  7
1 0 0 0 0 3 0 0 0 0 2          →  5
0 1 1 3 1 3 2 1 1 3 0 3        →  2
2 2 2 1 2 0 3 1 3 1 0 3        →  3
1 3 0 2 0 2 2 1 0 3 2 1 1 2 2  →  2
1 0 1 1 2 0 1 2 3 1 0 0 0 1 2 0→  4

Giải trình:

  • ⍳⍴⍵: lấy danh sách các số từ 1 đến độ dài của danh sách đầu vào
  • ↓2 2⊤⍵: cho mỗi giá trị trong danh sách đầu vào, hãy lấy byte đầu tiên và byte thứ hai
  • ∆←(... )/⊂⍳⍴⍵: cho cả hai danh sách byte, chọn các giá trị tương ứng từ ⍳⍴⍵. Lưu trữ chúng trong .
  • (⊂⍬)∊∆... :¯1: Nếu danh sách này chứa danh sách trống, hãy trả về -1. Nếu không thì:

  • |∘.-/∆: nhận được sự khác biệt tuyệt đối giữa mọi cặp giá trị, đưa ra một ma trận

  • (+,⍉¨): lấy một bản sao xoay và không xoay của ma trận đó
  • {⌈/⌊/⍵}: cho cả hai ma trận, lấy tối đa các mức tối thiểu của các hàng
  • ⌈/: sau đó lấy tối đa

@Optimizer: Bằng cách nào đó tôi đã quản lý để sao chép đầu ra thử nghiệm từ phiên bản trước đó có lỗi. Các mã đã chính xác và vẫn còn. Nếu bạn không tin tôi, hãy thử ở đây . (Lưu ý rằng bạn phải nhập danh sách một thành phần dưới dạng ,X, để phân biệt với vô hướng X.)
marinus

Ah tôi thấy. lười biếng với tôi để không đi đến một trình biên dịch trực tuyến và kiểm tra ..
Trình tối ưu hóa

1

Perl, 189 176 157B

Bây giờ với nhà nước hơn 500%.

use List::Util qw'max min';@I=<>;sub f{$n=($n%2)+1;map{$I[$_]&$n?$_:()}0..$#I}sub i{@t=f;max map{$b=$_;min map{abs$_-$b}@t}f}$r=max i,i;print defined$r?$r:-1

Dễ đọc

use List::Util qw'max min';
@I=<>;
sub f {
    $n = ($n%2) + 1;
    map { $I[$_] & $n ? $_ : () } 0..$#I
}
sub i {
    @t = f;
    max map {
        $b = $_;
        min map { abs $_ - $b } @t
    } f
}
$r = max i,i;
print defined $r ? $r : -1

Ví dụ sử dụng:

đầu vào

0
1
2
3

perl golf.pl < input


0

Clojure, 167 byte

#(let[P apply F(fn[I](filter(fn[i](I(% i)))(range(count %))))A(F #{1 3})B(F #{2 3})d(fn[X Y](P min(for[x X](P max(for[y Y](P -(sort[x y])))))))](-(min(d A B)(d B A))))

Có nên có một cách ngắn hơn ... Có?

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.