Số lượng lỗ trong đa giác


11

Vấn đề : Đếm số lượng lỗ trong một đa giác được kết nối. Khả năng kết nối của đa giác được đảm bảo bởi điều kiện là mọi tam giác trong tam giác đầu vào chia sẻ ít nhất 1 cạnh với một tam giác khác và chỉ có một bộ tam giác được kết nối như vậy.

Đầu vào là danh sách Lcác nđiểm trong mặt phẳng và danh sách T3 điểm với các mục từ 0...n-1. Đối với mỗi mục trong Ttuple (t_1,t_2,t_3)đại diện cho ba đỉnh (từ danh sách L) của một tam giác trong tam giác. Lưu ý rằng đây là hình tam giác theo nghĩa 'tam giác đa giác' , vì điều này sẽ không bao giờ có hai hình tam giác trong Tsự chồng chéo đó. Một quy định bổ sung là bạn sẽ không phải vệ sinh đầu vào LTkhông chứa bất kỳ sự lặp lại nào.

Ví dụ 1 : Nếu L = {{0,0},{1,0},{0,1},{1,2}}T = {{0,1,2},{1,2,3}}sau đó đa giác được chỉ định có số lỗ là 0.

Hình 1

Ví dụ 2 : Nếu 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}}sau đó đầu vào đa giác sẽ dẫn đến đầu ra là 2.

Hình 2

Nhiệm vụ là viết chương trình (hoặc hàm) ngắn nhất nhận LTlàm đầu vào và trả về số lượng lỗ. 'Người chiến thắng' sẽ được công nhận là mục có số lượng ký tự ít nhất (ngày kết thúc dự kiến ​​là ngày 1 tháng 6).

Định dạng đầu vào mẫu (lưu ý lập chỉ mục 0):

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

1
"Khả năng kết nối của đa giác được đảm bảo bởi điều kiện là mọi tam giác trong tam giác đầu vào chia sẻ ít nhất 1 cạnh với một tam giác khác." - không Đó không phải là một điều kiện đủ. Lấy ví dụ , T=1,2,3/1,2,4/5,6,7/5,6,8. Mỗi tam giác chia sẻ một cạnh với một tam giác khác, nhưng tam giác bị ngắt kết nối
John Dvorak

Chúng ta có thể giả sử đầu vào đại diện cho một tam giác một phần hợp lệ (không có hai tam giác trùng nhau và không có tam giác nào xuất hiện hai lần) và tam giác được kết nối?
John Dvorak


Chúng ta cũng có thể giả sử đầu vào được kết nối cạnh theo nghĩa không thể loại bỏ một tập hợp các điểm hữu hạn để làm cho hình dạng bị ngắt kết nối? (ví dụ: T=1,2,3/1,4,5được kết nối nhưng không được kết nối cạnh)
John Dvorak

2
Tôi không chắc tại sao doanh nghiệp này về ngày kết thúc đã bắt đầu cắt xén gần đây. Bạn được phép thay đổi câu trả lời được chấp nhận, vì vậy không cần thiết phải đặt ngày kết thúc. Thật hợp lý khi có một ý tưởng tinh thần rằng bạn sẽ đợi một tuần trước khi chọn câu trả lời để không khiến mọi người sợ rằng câu trả lời đầu tiên là không thể đánh bại, nhưng miễn là bạn hoạt động trên trang web, bạn có thể thay đổi câu trả lời đã chọn nếu ai đó đăng một cái tốt hơn Các cuộc thảo luận meta có liên quan bao gồm meta.codegolf.stackexchange.com/q/542/194meta.codegolf.stackexchange.com/q/193/194
Peter Taylor

Câu trả lời:


5

GolfScript (23 ký tự)

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

Giả sử định dạng đầu vào bằng cách sử dụng ký hiệu mảng GolfScript và tọa độ trích dẫn (hoặc tích phân). Ví dụ

$ 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

(Tương đương trực tuyến )

hoặc là

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

( Tương đương trực tuyến )


5

Con trăn, 71

Điều gì sau đây là một chương trình (không phải là một hàm ) tính toán số lượng mong muốn.

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

Ví dụ sử dụng:

>>> 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 để sử dụng splat, sử dụng froundredet thay vì sắp xếp, zip (không thể nói tôi đã từng sử dụng nó trước đây, cần phải tự làm quen.)
Kaya

3

APL, 36

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

Hàm lấy Llàm đối số bên trái của nó vàT bên phải của nó.

Ví dụ:

      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

Giải thích, đi từ phải sang trái:

  • ⍴⍺,⍵ nối hai vectơ đầu vào và trả về độ dài của chúng (V + F )
  • Bước vào bên trong khối tiếp theo:
    • ¨⍵ áp dụng hàm bên trái cho mọi phần tử của đối số bên phải và trả về kết quả
    • ⍵,⍵ trả về đúng đối số được nối với chính nó
    • 3 2⍴định hình đối số vector thành ba cặp. Trong trường hợp này, nó ghép các mục thứ nhất và thứ hai, thứ ba và thứ nhất và thứ hai và thứ ba của vectơ.
    • ,/ tham gia đối số vector với nhau
    • ⍵[⍋⍵] sắp xếp các đối số đúng
    • ∪/ lọc ra bất kỳ bản sao
    • ⍴⊃ biến một vô hướng lồng nhau thành một vectơ và nó trả về chiều dài của nó.
    • Toàn bộ hàm trả về số cạnh trong hình ( E)
  • 1 là tự giải thích (tôi hy vọng ...)

Toàn bộ hàm sau đó trả về 1+E-(V+F), hoặc 1-(F+V-E).


Khá nhiều chính xác những gì giải pháp GolfScript của tôi làm. Tôi ngạc nhiên khi nó dài hơn GolfScript rất nhiều.
Peter Taylor

@PeterTaylor Tôi rất ngạc nhiên khi giải pháp GolfScript của bạn ngắn hơn nhiều! (Nhưng sau đó, một lần nữa, đó GolfScript)
Biến động

2

Mathematica, 93 (chưa chơi gôn nhiều)

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

(Không gian được thêm vào cho rõ ràng)

Kiểm tra:

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

Điều này không dựa vào các hình tam giác hoặc lỗ có kích thước tối thiểu nhất định (đối số Erosion)?
John Dvorak

@JanDvorak Có lẽ tôi đã sai, nhưng tôi nghĩ rằng trừ khi bạn sử dụng số học chính xác vô hạn, mọi giải pháp sẽ hoạt động cho đến khi bạn đạt được kích thước tối thiểu nhất định (bạn sẽ phải quyết định xem ba điểm có thẳng hàng hay không). Chỉ là trong loại giải pháp này, vấn đề được nêu rõ ràng.
Tiến sĩ belisarius

nếu bạn sử dụng phương pháp tô pô, bạn không cần phải làm vậy. Nếu có ba điểm cộng tuyến thì bạn cần một tam giác có diện tích bằng 0 ở đó - nếu không bạn có một lỗ.
John Dvorak

@ Belisarius. Đây là câu trả lời tôi nhận được từ Hỗ trợ kỹ thuật của Wolfram về sự khác biệt giữa các kết quả của chúng tôi: "Xin chào - Cảm ơn email của bạn. Tôi đã xác nhận rằng mã của bạn cho kết quả khác nhau trên Mac và Windows. Tôi không nghĩ rằng đây là hành vi có chủ đích, vì vậy tôi không nghĩ rằng đây là hành vi có chủ đích, vì vậy Tôi đã nộp báo cáo với các nhà phát triển của chúng tôi về vấn đề này. Tôi chắc chắn sẽ chuyển bất kỳ thông tin hữu ích nào tôi nhận được từ các nhà phát triển của chúng tôi về vấn đề này. Vui lòng cho tôi biết nếu bạn có bất kỳ câu hỏi nào khác. ... Hỗ trợ kỹ thuật Nghiên cứu Wolfram , Inc. "
DavidC

@DavidCarraher "Vâng, tôi có thêm câu hỏi: Bạn sẽ gửi cho tôi kiểm tra từng lỗi chứ?"
Tiến sĩ belisarius

2

Ruby, 239 ký tự (cơ thể 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

lưu ý rằng tôi chỉ xem xét cấu trúc liên kết. Tôi không sử dụng các vị trí đỉnh theo bất kỳ cách nào.

người gọi (mong đợi T ở định dạng Mathicala hoặc JSON):

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

Kiểm tra:

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, một cách tiếp cận đặc trưng euler. Đó là cách tôi đã làm nó trong python.
Kaya

2
@Kaya. (Xem Egg of Columbus en.wikipedia.org/wiki/Egg_of_Columbus ) Một khi ai đó đã đưa ra câu trả lời Euler cho câu hỏi của bạn, khả năng những người khác sẽ làm theo tăng lên rất nhiều. Tôi có thể đảm bảo với bạn rằng sẽ khó khăn hơn rất nhiều và hài lòng khi tự mình khám phá phương pháp tiếp cận, chỉ sau đó, kết nối với Euler sẽ hoạt động với khối đa diện.
DavidC

2

Toán học 76 73 72 67 62

Sau nhiều thử nghiệm, tôi nhận ra rằng vị trí chính xác của các đỉnh không có gì đáng lo ngại, vì vậy tôi đã trình bày vấn đề bằng đồ thị. Các bất biến thiết yếu, số lượng hình tam giác, cạnh và đỉnh vẫn bất biến (cung cấp đường chéo được tránh).

Có hai loại "hình tam giác" bên trong biểu đồ: những hình đó có lẽ là một khuôn mặt, tức là hình tam giác "đầy" và những hình không có. Số lượng các mặt bên trong không có bất kỳ liên quan đến các cạnh hoặc đỉnh. Điều đó có nghĩa là việc chọc các lỗ trên đồ thị "đầy" chỉ làm giảm số lượng khuôn mặt. Tôi đã chơi một cách có hệ thống với các biến thể giữa các hình tam giác, theo dõi các mặt, đỉnh và cạnh. Cuối cùng, tôi nhận ra rằng số lượng lỗ luôn bằng 1 - #faces - # vertices + #edges. Điều này hóa ra là 1 trừ đi đặc tính Euler (mà tôi chỉ biết về bối cảnh của khối đa diện thông thường (mặc dù chiều dài của các cạnh rõ ràng là không quan trọng.

Hàm bên dưới trả về số lượng lỗ khi các đỉnh và hình tam giác được nhập vào. Không giống như đệ trình trước đây của tôi, nó không dựa vào việc quét hình ảnh. Bạn có thể coi đó là đặc điểm 1 - Euler, tức là 1 - (F + V -E) trong đó F= #faces, V= # vertices, E= # edge. Hàm trả về số lượng lỗ,1 - (F + V -E) , được cho các mặt thực tế (hình tam giác) và đỉnh.

Có thể dễ dàng thấy rằng việc loại bỏ bất kỳ tam giác nào ở bên ngoài phức tạp không ảnh hưởng đến đặc tính Euler, bất kể nó có chung một hoặc 2 cạnh với các tam giác khác hay không.

Lưu ý: Chữ thường vsẽ được sử dụng thay choL cho công thức ban đầu; nghĩa là, nó chứa chính các đỉnh (không phải V, số lượng đỉnh)

f được sử dụng cho T công thức ban đầu; nghĩa là, nó chứa các hình tam giác, được biểu diễn dưới dạng bộ ba chỉ số đỉnh.

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

(Cảm ơn thầy Wizard đã cạo sạch 5 ký tự bằng cách loại bỏ quy tắc thay thế.)


ví dụ 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

Không lỗ.


Ví dụ 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

Do đó, 2 lỗ trong ví dụ 2.


về cơ bản, bạn đang rastering tam giác và bỏ một thư viện đồ họa trên hình ảnh đó? Điều đó có thất bại không nếu một cái lỗ quá nhỏ?
John Dvorak

1
ví dụ thứ hai của bạn trả về 0 ở đây (đó là lý do tại sao tôi chưa sử dụng MorphologicalEulerNumber[]). Mma 9,01, giành chiến thắng XP.
Tiến sĩ belisarius

Tôi cũng đang sử dụng 9.0.1, nhưng trên máy Mac. Có phải bạn đang nói Mathicala trả lời một câu trả lời khác với tôi trên Windows? Nếu vậy, đó có vẻ là một lỗi (trong phiên bản Windows XP).
DavidC


@Jan Dvorak. MorphologicalEulerNumberđôi khi đòi hỏi một hình ảnh; nó từ chối chấp nhận một đối tượng đồ họa. Trong những trường hợp này, kích thước của lỗ và độ phân giải là rất quan trọng (xem codegolf.stackexchange.com/questions/8706/iêu ). Nhưng ở đây, nó hoạt động trực tiếp với đối tượng Đồ họa, chứa rõ ràng tất cả các đỉnh. Tôi tưởng tượng (hoặc hy vọng) rằng nó sẽ sử dụng một cách tiếp cận không phụ thuộc vào hình ảnh. Tôi ước tôi biết làm thế nào nó cố gắng giải quyết vấn đề. Có lẽ một số trò chơi trong mã nguồn cho chức năng sẽ làm rõ mọi thứ.
DavidC

1

Con trăn, 107

Tôi nhận ra rằng việc lấy các cặp trực tiếp ngắn hơn from itertools import*và gõ combinations(). Tuy nhiên, tôi cũng nhận thấy rằng giải pháp của tôi dựa vào các mặt tam giác đầu vào có các đỉnh được liệt kê theo thứ tự nhất quán. Do đó, mức tăng trong số lượng nhân vật không phải là lớn.

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

Con trăn, 115

Cách tiếp cận đặc trưng của Euler, tính dài dòng của itertools dường như là không thể tránh khỏi. Tôi tự hỏi nếu nó sẽ rẻ hơn nếu sử dụng một kỹ thuật trực tiếp hơn để tạo ra các cặp đỉnh.

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

Ví dụ sử dụng:

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