คำนวณระยะทาง Hausdorff


21

บทนำ

ระยะดอร์ฟมีขนาดแตกต่างระหว่างสองส่วนย่อยของพื้นที่เมตริก โดยสังเขปพื้นที่เมตริกเป็นเพียงบางชุดที่มีฟังก์ชั่นระยะทางในตัว d(a, b) := abs(a - b)ในความท้าทายนี้เราจะใช้หมายเลขธรรมชาติกับระยะทางสามัญ ระยะห่างของ Hausdorff ระหว่างสองเซตที่ไม่ว่างเปล่าAและBได้รับจาก

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 ระยะทางของ Hausdorff สามารถคำนวณได้โดยการหาองค์ประกอบAที่ระยะทางไปยังองค์ประกอบที่ใกล้ที่สุดBคือสูงสุดและองค์ประกอบของBระยะทางไปยังองค์ประกอบที่ใกล้ที่สุดของAสูงสุดและจากนั้นใช้ระยะทางสูงสุดเหล่านี้ กล่าวอีกนัยหนึ่งถ้าระยะห่าง Hausdorff dทุกองค์ประกอบของAอยู่ในระยะห่างdจากองค์ประกอบบางส่วนของBและในทางกลับกัน

อินพุต

ข้อมูลที่คุณป้อนเป็นรายการจำนวนเต็มเดียว มันมีองค์ประกอบ0,1,2,3ซึ่งมีความหมายว่าดัชนีที่กำหนดของรายการเป็นองค์ประกอบของค่าAมิได้BเพียงAเท่านั้นBหรือทั้งสองอย่างและA Bตัวอย่างเช่นการป้อนข้อมูล[0,1,1,0,2,3]หมายความว่าA = {1,2,5}และB = {4,5}ถ้าเราใช้การจัดทำดัชนีแบบ 0 (ซึ่งไม่สร้างความแตกต่างเนื่องจากตัวชี้วัดของเราเป็นค่าคงที่การแปล)

เอาท์พุต

ผลลัพธ์ของคุณคือระยะห่างระหว่าง Hausdorff AและB; 3ในตัวอย่างข้างต้นก็คือ -1หากตั้งอย่างใดอย่างหนึ่งเป็นที่ว่างเปล่าแล้วระยะทางที่ไม่ได้กำหนดไว้และคุณจะกลับมา

กฎระเบียบ

คุณสามารถเขียนโปรแกรมเต็มรูปแบบหรือฟังก์ชั่น จำนวนไบต์ต่ำสุดที่ชนะและช่องโหว่มาตรฐานไม่ได้รับอนุญาต

กรณีทดสอบ

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

ในสมการของคุณฉันเชื่อว่ามันนานเกินไปที่max(max(min(d(a, b) for b in B) for a in A))ควรจะเพียงพอ เพราะนี่คือd(a,b)คืนค่าสัมบูรณ์ดังนั้นทั้งสองฟังก์ชั่นสูงสุดจะส่งกลับจำนวนเดียวกันทุกครั้ง
Nathan Merrill

6
@NathanMerrill อาจเป็นได้ว่าองค์ประกอบทุกAอย่างอยู่ใกล้กับองค์ประกอบหนึ่งBแต่มีองค์ประกอบBที่อยู่ไกลมากA(ตัวอย่างเช่นหากAเป็นส่วนย่อยของB) ในกรณีนั้นสูตรสั้นไม่ถูกต้อง
Zgarb

คำตอบ:


7

CJam, 53 52 46 38 37 ไบต์

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

รับอินพุตบน STDIN เป็นอาร์เรย์สไตล์ CJam:

[0 1 2 3]

นี่คือชุดควบคุมการทดสอบที่แปลงทุกกรณีการทดสอบเป็นรูปแบบนี้และเรียกใช้รหัสจากพวกเขา แม้ว่าผลลัพธ์จะอยู่ในช่องป้อนข้อมูล แต่ก็ไม่ได้ใช้รหัส (ลบออกหากคุณไม่เชื่อใจฉัน :))

คำอธิบาย

อันดับแรกเราแยกวิเคราะห์อินพุตเพื่อรับสองชุด A และ 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.";

และตอนนี้เราพบความแตกต่างที่แน่นอนและเลือกจำนวนนาทีสูงสุด:

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

โปรดทราบว่าเราได้เก็บอาร์เรย์ว่างไว้ซึ่งเป็นผลมาจากการเริ่มต้น0ที่ด้านล่างของสแต็คตลอดเวลา แต่อาร์เรย์ที่ว่างเปล่าไม่ได้มีส่วนร่วมอะไรกับเอาต์พุต


5

CJam, 57 56 52 ไบต์

ฉันคิดว่านี่สามารถเล่นกอล์ฟได้ แต่ที่นี่จะไป:

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

การป้อนข้อมูลจะเป็นเหมือนรายการสไตล์ CJam เช่น

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

5

มันทำงานอย่างไร :

รหัสจะแบ่งออกเป็นสองส่วน:

แยกการป้อนข้อมูลลงในรายการAและ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";

ดำเนินการตามที่ต้องการในสองคู่Aและ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";

ลองออนไลน์ได้ที่นี่


5

Lua, 235 ไบต์

ไม่ใช่ผู้ชนะแน่นอน แต่อย่างน้อยก็เป็นความท้าทายที่สนุก

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

อินพุตทำงานได้เช่น:

lua hausdorff.lua <space-separated-sequence>

... และนี่คือสคริปต์ทดสอบ:

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)

... ผลิต ...

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 ไบต์

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

อัลกอริทึมของฉันทำงานกับสตริงอินพุตโดยตรงและไม่แปลงตัวเลขเหล่านี้ มันคำนวณเพียงครั้งเดียวสูงสุดและไม่เคยต่ำสุด

ขอบคุณ @isaacg สำหรับการบันทึกหนึ่งไบต์

ลองออนไลน์: Pyth Compiler / Executor

คำอธิบาย:

ก่อนอื่นฉันจะแทรกศูนย์จำนวนมากที่ด้านหน้าของอินพุต

          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

จากนั้นฉันจะกำหนดฟังก์ชั่นตัวช่วยyซึ่งจะบอกว่าดัชนีของรายการ (เช่นอินพุตหนึ่ง) ปรากฏในทั้งชุด A และ BEg y([0, 1, 0, 0, 1, 1]) = Falseหรือ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

หลังจากนั้นฉันตรวจสอบก่อนว่าผลลัพธ์เป็น-1อย่างไร

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

ตอนนี้กับสิ่งที่น่าสนใจ:

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

โปรดสังเกตว่าฉันจะหาตัวเลขเสมอTเพราะฉันรู้อยู่แล้วว่าดัชนีปรากฏในทั้งสองชุดในรายการ J ตัวเลขนั้นlength(Q)มากที่สุด นี่คือเหตุผลที่ใส่เลขศูนย์ด้วย หากมีlength(Q)ค่าศูนย์เป็นอย่างน้อยแทรกk-Tอยู่เสมอ>= 0ซึ่งจำเป็นสำหรับการแบ่งส่วนรายการ แล้วทำไมฉันถึงต้องใส่2^length(Q)ค่าศูนย์แทนlength(Q)ค่าศูนย์? ในกรณีทดสอบ[]ฉันต้องการอย่างน้อย 1 ศูนย์มิฉะนั้นyJจะส่งคืนข้อผิดพลาด


><Cab:Cbaเป็นเช่นเดียวกับ
isaacg

มันเป็นสิ่งที่ดีกรณีทดสอบไม่รวมถึงการป้อนข้อมูลที่มีขนาดใหญ่ ...
TLW

3

Mathematica, 88 ไบต์

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

1
คำตอบที่ดีมาก สำหรับการค้นหาระยะห่างของ Hausdorff โดยทั่วไปเราสามารถใช้m=MaxValue;Max[m[RegionDistance[#[[1]],s],s\[Element]#[[2]]]/.m[__]->-1&/@{#,Reverse@c}]& ซึ่งสามารถนำไปใช้กับวัตถุหลายมิติได้%@{Sphere[],Line[{{1,1,0},{3,3,3}}]}
Kelly Lowder

3

Haskell, 145 126 124 bytes

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

ทดสอบการทำงาน:

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

sกรองหมายเลขธรรมชาติตามภาคและรายชื่อการป้อนข้อมูลt คำนวณระยะทางสูงสุดของพารามิเตอร์ของมันและ จับเซตว่าง A หรือ B หรือใช้เวลาสูงสุดสุดท้ายของและ เป็นฟังก์ชั่นหลักที่เรียกใช้กับชุด A และ Bx#de%d#ee#df%

แก้ไข: @Zgarb พบจำนวนไบต์ที่จะบันทึก; @ ali0sha อีก 2 ขอบคุณ!


mod 2ดูเหมือนว่าไม่จำเป็น คุณอาจได้รับประโยชน์จากการไม่กำหนดaและbชัดเจน
Zgarb

คุณสามารถบันทึก 2 ไบต์มี[]%_= -1- แต่คุณชนะมือพยายามของฉันลงบนนี้ :)
อเล็กซานเด-Brett

3

Perl, 56 55

ที่เพิ่มเข้ามา 2 -lpสำหรับ

รายการอินพุตควรถูกกำหนดบน stdin โดยไม่มีช่องว่างเช่น:

echo 1011201231000120 | perl -lp hausdorf.pl

hausdorf.pl:

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

เพื่อรองรับช่องว่างระหว่างองค์ประกอบของรายการอินพุตเพียงแค่หารสุดท้าย$qด้วย 2 ด้วยค่าใช้จ่าย 2 ครั้ง


2

Python 2, 124

สิ่งนี้ให้ความรู้สึกที่ไม่ดีอย่างแน่นอน โอ้ดี

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

คำอธิบาย:

  • ⍳⍴⍵: รับรายการตัวเลขตั้งแต่ 1 ถึงความยาวของรายการอินพุต
  • ↓2 2⊤⍵: สำหรับแต่ละค่าในรายการอินพุตให้รับไบต์แรกและไบต์ที่สอง
  • ∆←(... เพราะทั้งสองรายการของไบต์เลือกค่าที่สอดคล้องกันจาก)/⊂⍳⍴⍵ ร้านค้าเหล่านี้ใน⍳⍴⍵
  • (⊂⍬)∊∆... :¯1: -1ถ้ารายการนี้มีรายการที่ว่างเปล่ากลับ มิฉะนั้น:

  • |∘.-/∆: ได้รับความแตกต่างที่แน่นอนระหว่างค่าทุกคู่ให้เมทริกซ์

  • (+,⍉¨): รับสำเนาที่หมุนและไม่หมุนของเมทริกซ์นั้น
  • {⌈/⌊/⍵}: สำหรับเมทริกซ์ทั้งคู่ให้ได้ค่าต่ำสุดสูงสุดของแถว
  • ⌈/: จากนั้นรับค่าสูงสุด

@Optimizer: ฉันพยายามที่จะคัดลอกผลการทดสอบจากรุ่นก่อนหน้าซึ่งมีข้อผิดพลาด รหัสนั้นถูกต้องและยังคงเป็น ถ้าคุณไม่เชื่อฉันพยายามที่นี่ (หมายเหตุที่คุณจะต้องป้อนรายการหนึ่งในองค์ประกอบที่เป็น,Xความแตกต่างจากสเกลาX.)
marinus

ฉันเข้าใจแล้ว ขี้เกียจฉันไม่ไปคอมไพเลอร์ออนไลน์และทดสอบ ..
เครื่องมือเพิ่มประสิทธิภาพ

1

Perl, 189 176 157B

ขณะนี้มีสถานะมากกว่า 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

ชัดเจน:

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

ตัวอย่างการใช้งาน:

อินพุต

0
1
2
3

perl golf.pl < input


0

Clojure 167 ไบต์

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

ควรมีวิธีที่สั้นกว่านี้ ... มีไหม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.