多边形中的孔数


11

问题:计算连接的多边形中的孔数。通过以下条件保证多边形的连通性:输入三角剖分中的每个三角形与另一个三角形至少共享一侧,并且只有一组这样连接的三角形。

输入是平面中Ln点的列表T,以及包含来自的三元组的列表0...n-1。对于T元组中的每个项,(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

任务是编写最短的程序(或函数),该程序以LT作为输入并返回孔的数量。“优胜者”将被认为是字符数最少的条目(暂定结束日期为6月1日)。

输入格式样本(请注意0索引):

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

1
“多边形的连通性是通过以下条件保证的:输入三角剖分中的每个三角形与另一个三角形至少共享一侧。” -不 这还不够。例如,T=1,2,3/1,2,4/5,6,7/5,6,8。每个三角形与另一个三角形共享一条边,但是三角剖分是断开的
John Dvorak

我们是否可以假设输入代表有效的局部三角剖分(两个三角形不重叠且两次都不存在三角形)并且三角剖分已连接?
约翰·德沃夏克


我们是否还可以假设输入是边缘连接的,就意味着无法删除一组有限的点以使形状断开连接?(例如:T=1,2,3/1,4,5已连接但未边缘连接)
约翰·德沃夏克

2
我不确定为什么有关终止日期的业务最近才开始兴起。您可以更改接受的答案,因此无需设置结束日期。明智的做法是,在选择答案之前要等一个星期,以免吓到人们认为第一个答案无与伦比,但是只要您在网站上处于活动状态,就可以更改所选答案如果有人发布更好的。相关的元讨论包括meta.codegolf.stackexchange.com/q/542/194meta.codegolf.stackexchange.com/q/193/194
Peter Taylor

Answers:


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

接下来是一个计算所需数字的程序(不是function)。

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(使用splat),frozenset而不是排序,使用zip(不能说我以前用过,需要认识自己)。–
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⍴将向量参数整形为三对。在这种情况下,它将向量的第一和第二,第三和第一,第二和第三项配对在一起。
    • ,/ 将vector参数连接在一起
    • ⍵[⍋⍵] 排序正确的参数
    • ∪/ 过滤掉所有重复项
    • ⍴⊃ 将嵌套标量转换为向量,并返回其长度。
    • 整个函数返回形状(E)中的边数
  • 1 是不言自明的(我希望...)

然后1+E-(V+F),整个函数返回或1-(F+V-E)


我的GolfScript解决方案几乎可以做到。我很惊讶它比GolfScript长得多。
彼得·泰勒

@PeterTaylor我很惊讶您的GolfScript解决方案这么短!(但同样 GolfScript)
波动率

2

93岁的Mathematica(尚未打高尔夫球)

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)吗?
约翰·德沃夏克

@JanDvorak也许我错了,但我认为除非您使用无限精度算术,否则任何解决方案都将起作用,直到达到一定的最小大小为止(您必须确定三个点是否对齐)。只是在这种解决方案中就明确指出了问题。
belisarius博士13年

如果使用拓扑方法,则不必这样做。如果存在共线的三个点,则那里需要一个零面积的三角形-否则您将有一个孔。
约翰·德沃夏克

@belisarius。这是我从Wolfram技术支持部门收到的关于我们的结果之间差异的答案:“您好-感谢您的来信。我确认您的代码在Mac和Windows上给出了不同的结果。我不认为这是预期的行为,因此我已向开发人员提交了有关此问题的报告。我将确保传递从开发人员处获得的有关此问题的任何有用信息。如果您还有其他疑问,请告诉我。...技术支持Wolfram Research ,Inc.”
DavidC

@DavidCarraher “是的,我还有其他问题:您会给我寄去每个错误的支票吗?”
belisarius博士13年

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

请注意,我只考虑拓扑。我没有以任何方式使用顶点位置。

调用者(预期为Mathematica或JSON格式的T):

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

是的,一种欧拉特征方法。这就是我在python中所做的。
卡亚

2
@Kaya。(请参阅Columbus的鸡蛋en.wikipedia.org/wiki/Egg_of_Columbus)一旦某人对您的问题给出了欧拉答案,其他人就会跟随的可能性大大增加。我可以向您保证,独自发现这种方法将更具挑战性和满足感,只有在此之后才能将Euler的工作与多面体联系起来。
DavidC

2

Mathematica 76 73 72 67 62

经过大量的实验,我意识到顶点的精确位置无关紧要,因此我用图形来表示问题。基本不变性,三角形,边和顶点的数量保持不变(避免了交叉线)。

图中有两种内部“三角形”:大概有一张脸,即一个“实心”三角形,而那些没有。内部面的数量与边缘或顶点没有任何关系。这意味着在完全“填充”的图形中戳洞只会减少面的数量。我系统地玩着三角形之间的变化,并跟踪面部,顶点和边缘。最终,我意识到孔的数量始终等于1-#faces-#vertices + #edges。事实证明这是1减去Euler特性(我仅在规则多面体的情况下才知道(尽管边缘的长度显然不重要)。

下面的函数返回输入顶点和三角形时的孔数。与我之前提交的文档不同,它不依赖于图像扫描。您可以将其视为1-欧拉的特征,即1-(F + V -E)其中F= #faces,V=#vertices,E=#edges。1 - (F + V -E)给定实际的面(三角形)和顶点,该函数返回孔的数量。

可以很容易地看出,去除配合物外部的任何三角形都不会影响欧拉特性,无论它与其他三角形共享一侧还是两侧。

注意:v将使用小写字母代替L原始配方;也就是说,它包含顶点本身(而不是V,即顶点数)

f用于T原始配方;也就是说,它包含三角形,表示为顶点索引的有序三元组。

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

(感谢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个孔。


您基本上是将三角剖分栅格化并在该图像上转储图形库吗?如果孔太小,那不会失败吗?
约翰·德沃夏克

1
您的第二个示例在这里返回0(这就是为什么我没有使用过MorphologicalEulerNumber[])。Mma 9.01,Win XP。
belisarius博士13年

我也在使用9.0.1,但在Mac上。您是说Mathematica在Windows上返回了与我不同的答案吗?如果是这样,那听起来像是个错误(在Windows XP版本中)。
DavidC

@DavidCarraher是:i.stack.imgur.com/LKcr1.png
博士13年

@简·德沃夏克 MorphologicalEulerNumber有时需要一张图片;它拒绝接受图形对象。在这些情况下,孔的大小和分辨率至关重要(请参见codegolf.stackexchange.com/questions/8706/…)。但是在这里,它可以直接与Graphics对象一起使用,该对象显式包含所有顶点。我想象(或希望)它将使用一种不依赖于图像的方法。我希望我知道它是如何尝试解决此问题的。也许在函数的源代码中进行一些拼写将使事情变得清晰。
DavidC

1

巨蟒,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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.