จำนวนหลุมในรูปหลายเหลี่ยม


11

ปัญหา : นับจำนวนหลุมในรูปหลายเหลี่ยมที่เชื่อมต่อ การเชื่อมต่อของรูปหลายเหลี่ยมนั้นได้รับการประกันโดยเงื่อนไขว่าสามเหลี่ยมทุกรูปในสามเหลี่ยมป้อนข้อมูลจะใช้ร่วมกันอย่างน้อย 1 ด้านกับรูปสามเหลี่ยมอื่นและมีรูปสามเหลี่ยมที่เชื่อมต่อเพียงชุดเดียว

การป้อนข้อมูลเป็นรายชื่อLของnจุดในเครื่องบินและรายการT3 tuples 0...n-1กับรายการจาก สำหรับแต่ละรายการในTtuple (t_1,t_2,t_3)แสดงถึงจุดยอดสามจุด (จากรายการL) ของสามเหลี่ยมในรูปสามเหลี่ยม โปรดทราบว่านี่เป็นรูปสามเหลี่ยมในความหมายของ'รูปหลายเหลี่ยมสามเหลี่ยม'เนื่องจากสิ่งนี้จะไม่มีรูปสามเหลี่ยมสองรูปTซ้อนทับกัน ข้อกำหนดเพิ่มเติมคือคุณจะไม่ต้องฆ่าเชื้ออินพุตLและTไม่ต้องทำซ้ำ

ตัวอย่างที่ 1 : ถ้าL = {{0,0},{1,0},{0,1},{1,2}}และT = {{0,1,2},{1,2,3}}จากนั้นรูปหลายเหลี่ยมที่ระบุมีจำนวนหลุมเป็น 0

รูปที่ 1

ตัวอย่างที่ 2 : ถ้าL = {{0,0},{1,0},{2,0},{2,1},{2,2},{1,2},{0,2},{0,1},{.5,.5},{1.5,.5},{1.5,1.5},{.5,1.5}}และT = {{5,6,11},{5,10,11},{4,5,10},{3,8,10},{2,3,9},{2,8,9},{1,2,8},{0,1,8},{0,8,11},{0,7,11},{6,7,11},{3,4,10}}จากนั้นอินพุตรูปหลายเหลี่ยมควรเป็นผลลัพธ์ของ 2

รูปที่ 2

ภารกิจคือการเขียนโปรแกรมที่สั้นที่สุด (หรือฟังก์ชั่น) ที่ใช้LและTเป็นอินพุตและส่งกลับจำนวนของหลุม 'ผู้ชนะ' จะได้รับการยอมรับว่าเป็นรายการที่มีจำนวนตัวอักษรน้อยที่สุด (วันสิ้นสุดเบื้องต้นที่ 1 มิถุนายน)

การจัดรูปแบบอินพุตตัวอย่าง (หมายเหตุการทำดัชนี 0):

0,0
1,0
0,1
1,2
0,1,2
1,2,3    

1
"การเชื่อมต่อของรูปหลายเหลี่ยมนั้นรับประกันได้โดยเงื่อนไขว่าสามเหลี่ยมทุกอันในสามเหลี่ยมการป้อนข้อมูลใช้ร่วมกันอย่างน้อย 1 ด้านกับอีกสามเหลี่ยมหนึ่ง" - ไม่ นั่นไม่ใช่เงื่อนไขที่เพียงพอ T=1,2,3/1,2,4/5,6,7/5,6,8ใช้ตัวอย่างเช่น, สามเหลี่ยมทุกอันแบ่งเป็นขอบกับสามเหลี่ยมอีกอันหนึ่ง แต่การเชื่อมต่อสมการถูกตัดออก
John Dvorak

เราอาจสมมติว่าอินพุตเป็นรูปสามเหลี่ยมบางส่วนที่ถูกต้อง (ไม่มีรูปสามเหลี่ยมสองรูปซ้อนทับกันและไม่มีรูปสามเหลี่ยมสองครั้ง) และรูปสามเหลี่ยมนั้นเชื่อมต่อกันหรือไม่
John Dvorak


เราอาจสมมติว่าอินพุตนั้นเชื่อมต่อกับขอบในแง่ที่ว่ามันเป็นไปไม่ได้ที่จะลบชุดของจุด จำกัด เพื่อทำให้การตัดการเชื่อมต่อรูปร่าง? (เช่นT=1,2,3/1,4,5เชื่อมต่อ แต่ไม่ได้เชื่อมต่อที่ขอบ)
John Dvorak

2
ฉันไม่แน่ใจว่าทำไมธุรกิจเกี่ยวกับวันที่สิ้นสุดจึงเริ่มมีการครอบตัดเมื่อเร็ว ๆ นี้ คุณได้รับอนุญาตให้เปลี่ยนคำตอบที่ยอมรับดังนั้นไม่จำเป็นต้องกำหนดวันที่สิ้นสุด มีเหตุผลที่จะต้องมีความคิดทางจิตว่าคุณจะต้องรอหนึ่งสัปดาห์ก่อนที่จะเลือกคำตอบเพื่อไม่ให้คนคิดว่าคำตอบแรกนั้นถูกที่สุด แต่ตราบใดที่คุณยังทำงานอยู่ในไซต์คุณสามารถเปลี่ยนคำตอบที่เลือกได้ ถ้ามีคนโพสต์ดีกว่า การสนทนาเมตาที่เกี่ยวข้องรวมถึงmeta.codegolf.stackexchange.com/q/542/194และmeta.codegolf.stackexchange.com/q/193/194
Peter Taylor

คำตอบ:


5

GolfScript (23 ตัวอักษร)

~.{2*2/~}%{$}%.&,@@+,-)

สมมติว่ารูปแบบการป้อนข้อมูลโดยใช้สัญลักษณ์อาร์เรย์ GolfScript และพิกัด (หรือหนึ่งส่วน) อ้างอิง เช่น

$ golfscript codegolf11738.gs <<<END
[["0" "0"] ["1" "0"] ["2" "0"] ["2" "1"] ["2" "2"] ["1" "2"] ["0" "2"] ["0" "1"] [".5" ".5"] ["1.5" ".5"] ["1.5" "1.5"] [".5" "1.5"]] [[5 6 11] [5 10 11] [4 5 10] [3 8 10] [2 3 9] [2 8 9] [1 2 8] [0 1 8] [0 8 11] [0 7 11] [6 7 11] [3 4 10]]
END
2

( เทียบเท่าออนไลน์ )

หรือ

$ golfscript codegolf11738.gs <<<END
[[0 0] [1 0] [0 1] [1 2]] [[0 1 2] [1 2 3]]
END
0

( เทียบเท่าออนไลน์ )


5

Python, 71

สิ่งที่ตามมาคือโปรแกรม (ไม่ใช่ฟังก์ชั่น ) ที่คำนวณจำนวนที่ต้องการ

len(set().union(*(map(frozenset,zip(t,t[1:]+t))for t in T)))-len(L+T)+1

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

>>> L = ((0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,1),(.5,.5),(1.5,.5),(1.5,1.5),(.5,1.5))
>>> T = ((5,6,11),(5,10,11),(4,5,10),(3,8,10),(2,3,9),(2,8,9),(1,2,8),(0,1,8),(0,8,11),(0,7,11),(6,7,11),(3,4,10))
>>> len(set().union(*(map(frozenset,zip(t,t[1:]+t))for t in T)))-len(L+T)+1
2

+1 สำหรับการใช้เครื่องหมาย, ใช้ frozenset แทนการเรียงลำดับ, ซิป (ไม่สามารถพูดได้ว่าฉันเคยใช้มาก่อน, ต้องรู้จักตนเอง)
Kaya

3

APL, 36

{1+(⍴⊃∪/{{⍵[⍋⍵]}¨,/3 2⍴⍵,⍵}¨⍵)-⍴⍺,⍵}

ฟังก์ชั่นใช้Lเป็นอาร์กิวเมนต์ซ้ายและTขวา

ตัวอย่างเช่น:

      L←(0 0)(1 0)(0 1)(1 2)
      T←(0 1 2)(1 2 3)
      L{1+(⍴⊃∪/{{⍵[⍋⍵]}¨,/3 2⍴⍵,⍵}¨⍵)-⍴⍺,⍵}T
0
      L←(0 0)(1 0)(2 0)(2 1)(2 2)(1 2)(0 2)(0 1)(.5 .5)(1.5 .5)(1.5 1.5)(.5 1.5)
      T←(5 6 11)(5 10 11)(4 5 10)(3 8 10)(2 3 9)(2 8 9)(1 2 8)(0 1 8)(0 8 11)(0 7 11)(6 7 11)(3 4 10)
      L{1+(⍴⊃∪/{{⍵[⍋⍵]}¨,/3 2⍴⍵,⍵}¨⍵)-⍴⍺,⍵}T
2

คำอธิบายไปจากขวาไปซ้าย:

  • ⍴⍺,⍵ต่อเวกเตอร์อินพุตสองตัวเข้าด้วยกันแล้วคืนค่าความยาว ( V + F)
  • ก้าวเข้าไปในบล็อกถัดไป:
    • ¨⍵ ใช้ฟังก์ชั่นด้านซ้ายกับทุกองค์ประกอบของการโต้แย้งที่ถูกต้องและส่งกลับผลลัพธ์
    • ⍵,⍵ ส่งคืนอาร์กิวเมนต์ที่ถูกตัดแบ่งด้วยตัวของมันเอง
    • 3 2⍴กำหนดอาร์กิวเมนต์ของเวกเตอร์เป็นสามคู่ ในกรณีนี้มันจับคู่รายการที่หนึ่งและสองที่สามและที่หนึ่งและที่สองและสามของเวกเตอร์
    • ,/ รวมอาร์กิวเมนต์เวกเตอร์เข้าด้วยกัน
    • ⍵[⍋⍵] เรียงลำดับอาร์กิวเมนต์ที่ถูกต้อง
    • ∪/ กรองรายการที่ซ้ำกันออก
    • ⍴⊃ เปลี่ยนสเกลาที่ซ้อนกันเป็นเวกเตอร์และคืนความยาวของมัน
    • ฟังก์ชั่นทั้งหมดคืนค่าจำนวนขอบในรูปร่าง ( E)
  • 1 อธิบายตนเอง (ฉันหวังว่า ... )

ฟังก์ชั่นทั้งหมดแล้วส่งกลับหรือ1+E-(V+F)1-(F+V-E)


ค่อนข้างมากในสิ่งที่โซลูชัน GolfScript ของฉันทำ ฉันประหลาดใจว่ามันนานกว่า GolfScript มาก
Peter Taylor

@PeterTaylor ฉันประหลาดใจที่โซลูชัน GolfScript ของคุณสั้นลงมาก! (แต่แล้วอีกครั้งมันเป็น GolfScript)
ความผันผวน

2

Mathematica, 93 (ยังไม่ค่อยได้เล่นกอล์ฟมาก)

f[l_, t_] :=  Max@MorphologicalComponents[Erosion[Graphics[
                                                        GraphicsComplex[l, Polygon[t + 1]]], 1]] - 1

(เพิ่มช่องว่างเพื่อความชัดเจน)

การทดสอบ:

f[{{0, 0}, {1, 0}, {0, 1}, {1, 2}}, {{0, 1, 2}, {1, 2, 3}}]
(*
 -> 0
*)

{l, t} = {{{0, 0}, {1,   0}, {2,    0}, {2,     1}, {2,    2}, {1, 2}, {0, 2}, 
           {0, 1}, {.5, .5}, {1.5, .5}, {1.5, 1.5}, {.5, 1.5}}, 

           {{5, 6, 11}, {5, 10, 11}, {4, 5, 10}, {3, 8, 10}, {2, 3,  9}, 
            {2, 8,  9}, {1,  2,  8}, {0, 1,  8}, {0, 8, 11}, {0, 7, 11}, {6, 7, 11}, {3, 4, 10}}};
f[l, t]
 (*
  -> 2
 *)

สิ่งนี้ไม่ได้ขึ้นอยู่กับรูปสามเหลี่ยมหรือรูที่มีขนาดเล็กที่สุด (อาร์กิวเมนต์Erosion)
John Dvorak

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

ถ้าคุณใช้วิธีทอพอโลยีคุณไม่จำเป็นต้องทำ หากมี collinear สามจุดคุณจำเป็นต้องใช้สามเหลี่ยมที่มีพื้นที่เป็นศูนย์หรือไม่เช่นนั้นคุณจะมีรู
John Dvorak

@belisarius นี่คือคำตอบที่ฉันได้รับจาก Wolfram Technical Support เกี่ยวกับความคลาดเคลื่อนระหว่างผลลัพธ์ของเรา: "สวัสดี - ขอบคุณสำหรับอีเมลของคุณฉันยืนยันว่ารหัสของคุณให้ผลลัพธ์ที่แตกต่างกันใน Mac และ Windows ฉันไม่คิดว่านี่เป็นพฤติกรรมที่ตั้งใจ ฉันได้ส่งรายงานกับนักพัฒนาของเราเกี่ยวกับปัญหานี้ฉันจะแน่ใจว่าได้ส่งผ่านข้อมูลที่เป็นประโยชน์ใด ๆ ที่ฉันได้รับจากนักพัฒนาของเราในเรื่องนี้โปรดแจ้งให้เราทราบหากคุณมีคำถามเพิ่มเติม ... ฝ่ายสนับสนุนด้านเทคนิค Wolfram Research , Inc. "
DavidC

@DavidCarraher "ใช่ฉันมีคำถามเพิ่มเติม: คุณจะส่งเช็คให้ฉันสำหรับแต่ละข้อผิดพลาดหรือไม่"
ดร. เบลิซาเรีย

2

Ruby, 239 ตัวอักษร (ร่างกาย 227)

def f t
e=t.flat_map{|x|x.permutation(2).to_a}.group_by{|x|x}.select{|_,x|x.one?}.keys
n=Hash[e]
(u,n=n,n.dup;e.map{|x|a,b=*x;n[a]=n[n[a]]=n[b]})until n==u
n.values.uniq.size+e.group_by(&:last).map{|_,x|x.size}.reduce(-1){|x,y|x+y/2-1}
end

โปรดทราบว่าฉันกำลังพิจารณาโทโพโลยีเท่านั้น ฉันไม่ได้ใช้ตำแหน่งจุดสุดยอด แต่อย่างใด

ตัวเรียก (คาดว่า T ในรูปแบบ Mathematica หรือ JSON):

input = gets.chomp
input.gsub! "{", "["
input.gsub! "}", "]"
f eval(input)

ทดสอบ:

f [[0,1,2],[1,2,3]]
#=> 0
f [[5, 6, 11], [5, 10, 11], [4, 5, 10], [3, 8, 10], [2, 3, 9], [2, 8, 9], [1, 2, 8], [0, 1, 8], [0, 8, 11], [0, 7, 11], [6, 7, 11], [3, 4, 10]]
#=> 2
f [[1,2,3],[3,4,5],[5,6,1],[2,3,4],[4,5,6],[6,1,2]]
#=> 1

Yay แนวทางลักษณะออยเลอร์ นั่นเป็นวิธีที่ฉันทำในหลาม
Kaya

2
@Kaya (ดู Egg of Columbus en.wikipedia.org/wiki/Egg_of_Columbus ) เมื่อมีคนให้คำตอบกับคำถามของคุณ Eulerian โอกาสที่คนอื่นจะทำตามจะเพิ่มขึ้นอย่างมาก ฉันรับรองได้ว่าคุณจะท้าทายและพอใจมากกว่าที่จะค้นพบแนวทางด้วยตัวเองหลังจากนั้นจึงเชื่อมต่อกับงานของออยเลอร์กับโพลีเฮดรา
DavidC

2

Mathematica 76 73 72 67 62

หลังจากการทดลองมากฉันก็ตระหนักว่าตำแหน่งที่แม่นยำของจุดยอดนั้นไม่เกี่ยวข้องดังนั้นฉันจึงแสดงปัญหาด้วยกราฟ ค่าคงที่ที่จำเป็นจำนวนสามเหลี่ยมขอบและจุดยอดคงที่ไม่เปลี่ยนแปลง (หลีกเลี่ยงการข้ามเส้น)

มี "สามเหลี่ยม" ภายในสองชนิดในกราฟ: มันมีใบหน้าสมมุติเช่นสามเหลี่ยม "เต็ม" และที่ไม่มี จำนวนใบหน้าภายในไม่มีความสัมพันธ์กับขอบหรือจุดยอด นั่นหมายความว่าการเจาะรูในกราฟ "เต็ม" เต็มลดจำนวนใบหน้าเท่านั้น ฉันเล่นอย่างเป็นระบบด้วยรูปแบบต่าง ๆ ระหว่างสามเหลี่ยมติดตามใบหน้าจุดยอดและขอบ ในที่สุดฉันก็รู้ว่าจำนวนของรูเสมอเท่ากับ 1 - #faces - # vertices + #edges สิ่งนี้กลายเป็น 1 ลบด้วยคุณสมบัติของออยเลอร์ (ซึ่งฉันเพิ่งรู้จักในบริบทของรูปทรงหลายเหลี่ยมปกติ (แม้ว่าความยาวของขอบนั้นไม่มีความสำคัญอย่างชัดเจน

ฟังก์ชั่นด้านล่างนี้จะคืนค่าจำนวนหลุมเมื่อป้อนจุดยอดและสามเหลี่ยม ซึ่งแตกต่างจากการส่งก่อนหน้าของฉันมันไม่ได้อาศัยการสแกนภาพ คุณสามารถคิดว่ามันเป็น 1 - คุณลักษณะของออยเลอร์เช่น 1 - (F + V -E) โดยที่F= #faces, V= # จุดยอด, E= # ขอบ ฟังก์ชั่นจะคืนค่าจำนวนรู1 - (F + V -E)รับจากใบหน้าจริง (สามเหลี่ยม) และจุดยอด

มันสามารถแสดงให้เห็นได้อย่างง่ายดายว่าการลบสามเหลี่ยมใด ๆ ที่อยู่ด้านนอกคอมเพล็กซ์นั้นไม่มีผลกระทบต่อคุณลักษณะของออยเลอร์

หมายเหตุ: ตัวพิมพ์เล็กvจะใช้แทนLสูตรดั้งเดิม นั่นคือมันมีจุดยอดเอง (ไม่ใช่ V, จำนวนจุดยอด)

fใช้สำหรับTสูตรดั้งเดิม นั่นคือมันมีรูปสามเหลี่ยมแสดงเป็นดัชนีสามจุดยอดสั่ง

รหัส

z=Length;1-z@#2-z@#+z[Union@@(Sort/@{#|#2,#2|#3,#3|#}&@@@#2)]&

(ขอบคุณ Mr. Wizard สำหรับการโกน 5 ตัวโดยกำจัดกฎการเปลี่ยนใหม่)


ตัวอย่างที่ 1

v = {{0, 0}, {1, 0}, {0, 1}, {1, 2}}; f = {{0, 1, 2}, {1, 2, 3}};

z=Length;1-z@#2-z@#+z[Union@@(Sort/@{#|#2,#2|#3,#3|#}&@@@#2)]&[v, f]

0

ศูนย์รู


ตัวอย่างที่ 2

v = {{0, 0}, {1, 0}, {2, 0}, {2, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1} , {.5, .5}, {1.5, .5}, {1.5, 1.5}, {.5, 1.5}}; f = {{5, 6, 11}, {5, 10, 11}, {4, 5, 10}, {3, 8, 10}, {2, 3, 9}, {2, 8, 9} , {1, 2, 8}, {0, 1, 8}, {0, 8, 11}, {0, 7, 11}, {6, 7, 11}, {3, 4, 10}};

z=Length;1-z@#2-z@#+z[Union@@(Sort/@{#|#2,#2|#3,#3|#}&@@@#2)]&[v, f]

2

ดังนั้น 2 หลุมเป็นตัวอย่างที่ 2


คุณกำลังสร้างการวิเคราะห์สามเหลี่ยมและทิ้งไลบรารีกราฟิกบนรูปภาพนั้นหรือไม่ นั่นไม่ได้ล้มเหลวหรือเปล่าหากรูเล็กเกินไป?
John Dvorak

1
ตัวอย่างที่สองของคุณส่งคืน 0 ที่นี่ (นั่นคือเหตุผลที่ฉันไม่ได้ใช้MorphologicalEulerNumber[]) Mma 9.01, Win XP
ดร. เบลิซาเรียส

ฉันใช้ 9.0.1 ด้วย แต่ใช้กับ Mac คุณกำลังบอกว่า Mathematica ให้คำตอบที่แตกต่างจากของฉันบน Windows หรือไม่? ถ้าเป็นเช่นนั้นดูเหมือนว่าบั๊ก (ในรุ่น Windows XP)
DavidC


@Jan Dvorak MorphologicalEulerNumberบางครั้งต้องใช้รูปภาพ มันปฏิเสธที่จะยอมรับวัตถุกราฟิก ในกรณีเหล่านี้ขนาดของรูและความละเอียดมีความสำคัญ (ดูcodegolf.stackexchange.com/questions/8706/… ) แต่ที่นี่มันทำงานได้โดยตรงกับวัตถุกราฟิกซึ่งมีจุดยอดทั้งหมดอย่างชัดเจน ฉันจินตนาการ (หรือหวัง) ว่าจะใช้วิธีการที่ไม่ได้ขึ้นอยู่กับภาพ ฉันหวังว่าฉันรู้ว่ามันพยายามแก้ไขปัญหาอย่างไร บางทีการสะกดคำบางอย่างในซอร์สโค้ดสำหรับฟังก์ชั่นจะชี้แจงสิ่งต่าง ๆ
DavidC

1

Python, 107

ฉันตระหนักว่าการคู่โดยตรงสั้นกว่าและการพิมพ์from itertools import* combinations()แต่ฉันก็สังเกตเห็นว่าวิธีการแก้ปัญหาของฉันอาศัยใบหน้ารูปสามเหลี่ยมอินพุตที่มีจุดยอดของพวกเขาอยู่ในลำดับที่สอดคล้องกัน ดังนั้นการเพิ่มจำนวนตัวอักษรจึงไม่มาก

f=lambda l,t:1-len(l+t)+len(set([tuple(sorted(m))for n in[[i[:2],i[1:],[i[0],i[2]]]for i in t]for m in n]))

Python, 115

แนวทางลักษณะออยเลอร์ความฟุ้งซ่านของ itertools ดูเหมือนจะเป็นไปไม่ได้ที่จะหลีกเลี่ยง ฉันสงสัยว่ามันจะถูกกว่าหรือไม่ถ้าใช้เทคนิคที่ตรงกว่านี้เพื่อสร้างจุดยอดคู่

from itertools import*
f=lambda l,t:1-len(l+t)+len(set([m for n in[list(combinations(i,2)) for i in t]for m in n]))

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

> f([[0,0],[1,0],[0,1],[1,2]],[[0,1,2],[1,2,3]])
> 0
> f([[0,0],[1,0],[2,0],[2,1],[2,2],[1,2],[0,2],[0,1],[.5,.5],[1.5,.5],[1.5,1.5],[.5,1.5]],[[5,6,11],[5,10,11],[4,5,10],[3,8,10],[2,3,9],[2,8,9],[1,2,8],[0,1,8],[0,8,11],[0,7,11],[6,7,11],[3,4,10]])
> 2
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.