Hausdorff Mesafesini Hesapla


21

Giriş

Hausdorff mesafe Bir metrik alan iki alt arasındaki fark ölçülür. Sezgisel olarak, bir metrik boşluk, yerleşik bir mesafe işlevine sahip olan sadece bir kısmıdır; Bu mücadelede, doğal sayıları normal mesafeden kullanacağız d(a, b) := abs(a - b). Haussdorf iki boş olmayan sonlu kümeler arasındaki mesafe Ave Bverilir

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

Python benzeri gösterimde. Hausdorff mesafesi, Aen yakın elemana olan mesafenin Bmaksimum olduğu elementin Bbulunması ve en yakın elemana olan mesafenin Amaksimum olduğu elementin hesaplanması ve daha sonra bu mesafelerin maksimumunun alınması ile hesaplanabilir. Hausdorff mesafe, başka bir deyişle, d, daha sonra her eleman Amesafesinde dbir elemanın B, ve tersi.

Giriş

Girişiniz tek bir tamsayı listesidir. Sadece elementleri içeren 0,1,2,3listenin verilen endeks bir unsuru ne olup olmadığını delalet, Ane de Bsadece Atek Bveya her ikisi Ave B. Örneğin, girdi şu [0,1,1,0,2,3]anlama gelir A = {1,2,5}ve B = {4,5}eğer 0 temelli indeksleme kullanıyorsak (farkımız yoktur, çünkü metriklerimiz çeviri değişmezdir).

Çıktı

Çıktınız arasındaki Hausdorff mesafedir Ave B; Yukarıdaki örnekte, öyle 3. Herhangi bir ayar boşsa, mesafe tanımlanmaz ve geri dönersiniz -1.

kurallar

Tam bir program veya bir fonksiyon yazabilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklar izin verilmez.

Test Kılıfları

[] -> -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

Denkleminizde max(max(min(d(a, b) for b in B) for a in A))yeterli olması gerektiği gibi çok uzun olduğuna inanıyorum . Bunun nedeni d(a,b)mutlak değeri verir ve bu nedenle her iki maksimum fonksiyon her seferinde aynı sayıyı döndürür.
Nathan Merrill

6
@NathanMerrill Her elemanının birine Açok yakın olduğu söylenebilir B, ancak Bçok uzak olan unsurlar vardır A(örneğin, eğer Abir altkümesi varsa B). Bu durumda, kısa formül yanlış.
Zgarb

Yanıtlar:


7

CJam, 53 52 46 38 37 bayt

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

STDIN'de bir CJam stil dizisi olarak girdi alır:

[0 1 2 3]

İşte tüm test senaryolarını bu formata dönüştüren ve üzerlerinde kod çalıştıran bir test donanımı . Sonuçlar giriş alanında olmasına rağmen, kod tarafından kullanılmazlar (bana güvenmiyorsanız bunları kaldırın :)).

açıklama

İlk önce A ve B iki setini almak için girişi ayrıştırırız:

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

Ve şimdi mutlak farkları buluyoruz ve en fazla mayın sayısını seçiyoruz:

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

Unutmayın ki boş diziyi 0her zaman yığının en altından tutarız, ancak boş diziler çıktıya hiçbir şey katkıda bulunmaz.


5

CJam, 57 56 52 bayt

Bunun biraz daha golf oynayabileceğini düşünüyorum ama işte:

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

Giriş, bir CJam tarz listesi gibi girilir, örn.

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

5

Nasıl çalışır :

Kod iki bölüme ayrılmıştır:

Girişi listelerde ayrıştırma Ave B:

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

İki çift üzerinde gerekli işlemleri gerçekleştirme Ave B:

{~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";

Burada çevrimiçi deneyin


5

Lua, 235 bayt

Kesinlikle bir kazanan değil, en azından eğlenceli bir mücadele.

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

Giriş şöyle çalışır:

lua hausdorff.lua <space-separated-sequence>

... ve işte bir test komut dosyası:

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)

... üretir ...

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 bayt

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

Algoritmam doğrudan girdi dizgisinde çalışır ve bu sayıyı asla dönüştürmez. Sadece bir defa maksimum ve asla minimum hesaplamaz.

Bir bayt kaydettiğiniz için @ isaacg 'a teşekkür ederiz.

Çevrimiçi deneyin: Pyth Compiler / Executor

açıklamalar:

İlk önce girişin önüne çok sayıda sıfır ekleyeceğim.

          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

Sonra, bir yardım edicinin y(giriş gibi) bir listesini endeksleri iki seti A ve Baş görünür belirtir, y([0, 1, 0, 0, 1, 1]) = Falsefakat 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

Daha sonra sonuç olup olmadığını kontrol ediyorum -1.

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

Şimdi ilginç şeylere:

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

Dikkat edin, her zaman bir sayı bulacağım T, çünkü indislerin J listesindeki her iki kümede de göründüğünü zaten biliyorum. Sayı maksimumdur length(Q). Bu aynı zamanda sıfırları yerleştirme nedenidir. length(Q)Takılan en az sıfır varsa k-T, her zaman >= 0dilimleme için gerekli olan listedir. Peki neden 2^length(Q)sıfır yerine length(Q)sıfır ekliyorum? Test durumunda []en az 1 sıfıra ihtiyacım var, aksi halde yJhata döndürür.


><Cabaynıdır :Cba.
isaacg


3

Mathematica, 88 bayt

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

1
Çok güzel cevap. Hausdorff mesafesinin daha genel bulunması için, m=MaxValue;Max[m[RegionDistance[#[[1]],s],s\[Element]#[[2]]]/.m[__]->-1&/@{#,Reverse@c}]& bunun gibi çok boyutlu nesnelere uygulanabilecek bir kişi kullanılabilir%@{Sphere[],Line[{{1,1,0},{3,3,3}}]}
Kelly Lowder

3

Haskell, 145 126 124 bayt

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

Test sürüşü:

*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]

sdoğal sayıları bir yüklemeye tve giriş listesine göre filtreler x. #parametrelerinin maksimum mesafesini hesaplar dve e. %boş kümeler A veya B'yi yakalar veya son ve d#eve sonunu alır e#d. A ve B ile fçağıran ana işlevdir %.

Düzenleme: @Zgarb kaydetmek için çok sayıda bayt buldu; @ ali0sha başka bir 2. Teşekkürler!


mod 2Gereksiz görünüyor. Ayrıca tanımlamamaktan ave baçıkça belirtmekten de yararlanabilirsiniz .
Zgarb

2 bayt ile tasarruf edebilirsiniz []%_= -1- ama bu girişimimi ellerimden
mahrum bırakıyorsunuz

3

Perl, 56 55

İçin +2 eklendi -lp .

Giriş listesi boşluksuz stdin'de verilmelidir, örneğin:

echo 1011201231000120 | perl -lp hausdorf.pl

hausdorf.pl:

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

Giriş listesinin elemanları arasındaki boşlukları desteklemek için finali $q2 vuruş maliyeti ile 2'ye bölün


2

Python 2, 124

Bu kesinlikle yetersiz kalıyor. Oh iyi.

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⋄⌈/{⌈/⌊/⍵}¨(+,⍉¨)|∘.-/∆}

testcases:

      ({(⊂⍬)∊∆←(↓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

Açıklama:

  • ⍳⍴⍵: 1 ile giriş listesinin uzunluğu arasındaki sayıları listeler.
  • ↓2 2⊤⍵: Giriş listesindeki her değer için ilk baytı ve ikinci baytı al
  • ∆←(... )/⊂⍳⍴⍵: Her iki bayt listesi için ilgili değerleri seçin ⍳⍴⍵. Bunları içeride saklayın .
  • (⊂⍬)∊∆... :¯1: bu liste boş listeyi içeriyorsa, geri dönün -1. Aksi takdirde:

  • |∘.-/∆: her bir değer çifti arasındaki mutlak farkı elde ederek bir matris elde etmek

  • (+,⍉¨): o matrisin döndürülmüş ve döndürülmemiş bir kopyasını al
  • {⌈/⌊/⍵}: Her iki matris için de satırın minimum değerinden maksimum olanı alın
  • ⌈/: o zaman en fazla elde etmek

@Optimizer: Test çıktısını, bir hata olan önceki bir versiyondan kopyalamayı başardım. Kodun kendisi doğruydu ve hala geçerli. Bana inanmıyorsan, burada dene . ( ,XX
Skalerden

Ah, anlıyorum. tembel bir online derleyiciye gitmeme ve
Doktor 15

1

Perl, 189 176 157B

Şimdi% 500 daha fazla devlet ile.

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

Okunabilen:

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

Örnek kullanım:

giriş

0
1
2
3

perl golf.pl < input


0

Clojure, 167 bayt

#(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))))

Daha kısa bir yol olmalı ... Var mı?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.