网格可以弯曲。你多久了?


12

考虑在W宽x H高的文本网格上绘制一条简单的开放的二维曲线,其中X该曲线.表示曲线的一部分,表示空白,不使用其他任何字符。

每个网格空间都有8个相邻的网格空间,即Moore邻域。边界之外的网格空间被认为是空的。

网格包含曲线,如果有且只有一个X OR,如果有一个以上的X地方:

  • 正好2个X只有一个相邻X。这些是曲线的端点。
  • X除端点外,每个端点都恰好相邻2 Xs。这些构成了曲线的主体。

例如,此W = 9而H = 4的网格包含一条曲线:

....X....
.X.X.X.X.
X..X..X.X
.XX.....X

同样,这些网格(W = 4,H = 3)具有曲线:

....  .X..  ....  ....  .X.X
....  X..X  ..X.  XX..  X.X.
..X.  .XX.  .X..  ....  ....

但是,这些网格不包含曲线:

....  .XX.  ...X  XX..  ....  X.X.
....  X..X  ..XX  XX..  .X.X  .X..
....  .XX.  .X..  ....  ...X  X.X.

我们可以通过将Xs的所有相邻对之间的距离求和来找到曲线的长度:

  • 两个正交相邻的Xs 之间的距离为1个单位。

    XX
    X
    X
  • 两个对角相邻的Xs 之间的距离为√2单位。

    X.
    .X
    .X
    X.

例如,网格中曲线的长度

XXX.
...X
..X.

可以可视化为

长度示例

所以我们可以看到它是1 +1 +√2+√2= 4.828427 ...

只有一个的曲线的长度X为零。

当网格不形成曲线时,其长度不能很好地定义。

挑战

给定Xs和.s 的文本网格,输出其包含的曲线的长度,否则输出诸如-1或的值,Null以指示网格没有曲线。

输入时X.如果需要,可以使用其他字符,如果需要,可以使用H和W作为输入。以嵌套列表或填充有1和0而不是字符串的矩阵形式输入也可以。

您可以输出曲线长度的浮点数,也可以输出两个整数A和B,其中length = A + B*√2

以字节为单位的最短代码获胜。

测试用例

XXX.
...X
..X.
2 + 2*√2 = 4.828427...

....X....
.X.X.X.X.
X..X..X.X
.XX.....X
3 + 8*√2 = 14.313708...

....
....
..X.
0 + 0*√2 = 0

.X..
X..X
.XX.
1 + 3*√2 = 5.242640...

....
..X.
.X..
0 + 1*√2 = 1.414213...

....
XX..
....
1 + 0*√2 = 1

.X.X
X.X.
....
0 + 3*√2 = 4.242640...

....
....
....
....
-1

.XX.
X..X
.XX.
-1

...X
..XX
.X..
-1

....
.X.X
...X
-1

X.X.
.X..
X.X.
-1

我建议允许求解器为没有曲线的网格选择输出格式(对于任何m,n≥0,任何格式都不为m + n * sqrt(2)的一致值)。
格雷格·马丁

@Greg听起来不错。完成
加尔文的爱好

[x.x,...,.x.]不是有效的曲线,对吗?
Magic Octopus Urn'Mar

@carusocomputing正确
加尔文的爱好

Answers:


3

MATL52 51字节

t2Y6~Z+*ssGt3Y6Z+*tt1=z2=wssGzqE=*Gz1=+?}_q]ssy-h2/

输入是零和一的矩阵。

输出B,然后A。非曲线为负A

在线尝试!验证所有测试用例

说明

计算曲线的长度使用两个2D卷积1:一个使用Moore蒙版,另一个使用仅包含对角邻域的蒙版。结果是输入大小相同的两个矩阵,分别表示为MD。M给出每个点的邻居总数,而D给出对角邻居的数量。

必须过滤MD中的结果,以丢弃不属于曲线的点。同样,它们必须除以2,因为“与...相邻”是一个对称关系,因此曲线中的每个点都被计数两次。

确定曲线是否有效比我预期的要麻烦。为此,代码将测试三个条件:

  1. M中的个数等于2吗?(也就是说,只有一个邻居有两个点吗?)
  2. M的总和等于输入曲线中的点数乘以22吗?(与条件1一起,这将测试M中除两个以外的所有非零值是否相等2
  3. 输入曲线是否包含单个点?

如果条件1和2为真,或者条件3为真,则曲线有效。

t       % Implicit input matrix of zeros and ones. Duplicate
2Y6~    % Push [1 0 1; 0 0 0; 1 0 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix D
ss      % Sum of matrix D
Gt      % Push input again wtice
3Y6     % Push [1 1 1; 1 0 1; 1 1 1]
Z+      % 2D convolution, keeping size
*       % Multiply to zero out results for non-curve points. Gives matrix M
tt      % Duplicate twice
1=z     % Number of ones
2=      % Does it equal 2? This is condition 1
wss     % Swap. Sum of matrix
G       % Push input again
zqE     % Number of nonzeros values minus 1, and then multiplied by 2
=       % Are they equal? This is condition 2
*       % Multiply. This is a logical AND of conditions 1 and 2
G       % Push input again
z1=     % Does it contain exactly one nonzero value? This is condition 3
+       % Add. This is a logical OR with condition 3
?}      % If result was false
  _q    %   Negate and subtract 1. This makes sure we get a negative value
]       % End
ss      % Sum of matrix M
y       % Duplicate sum of matrix D from below
-       % Subtract
h       % Concatenate horizontally
2/      % Divide by 2. Implicitly display

1 卷积是成功的关键


1

Python 3中316个 315 311字节

我认为这涵盖了所有情况;至少测试用例有效。

同样,肯定还有很多事情要进行,可能是在处理边缘盒的开始阶段。

def f(d,R,C):
 s=sum;d=[0]*(C+2),*[[0,*r,0]for r in d],[0]*(C+2);o=-1,0,1;k=[[[(1,0),(0,1)][i*j]for i in o for j in o if d[r+i][c+j]and i|j]for c in range(1,-~C)for r in range(1,-~R)if d[r][c]];w=[x/2for x in map(s,zip(*s(k,[])))]or[0,0];print([w,-1][s(w)!=s([s(z)for z in d])-1or[len(t)for t in k].count(1)>2])

在线尝试!

怎么运行的:

  1. d,R,C 是1.列表列表,其中1作为曲线,0作为背景,2.行和列数
  2. 在前后插入0的行,在前后插入0的行,d因此我们不必担心2d数组的边缘
  3. 对于2d数组中的每个1,扫描邻域中的1,如果关系是对角线,则将(1,0)添加到列表中,否则添加(0,1)
  4. 对所有元组求和,因此(n,m)分别代表对角和非对角邻点的数量
  5. 检查关系数是否正好是1的数量减去1的数量;如果不是,则不是曲线。

感谢@Helka Homba指出丢失的案件。感谢@TuukkaX和@Trelzevir提供了高尔夫技巧。


看起来d=[[1,0,1],[0,1,0],[1,0,1]]这里会失败(添加了测试用例)。
加尔文的爱好

@HelkaHomba是的,我监督了。谢谢!已修复(不幸的是现在有更多字节)。
尼罗河

1
s=sum保存4个字节。
Trelzevir

0

Mathematica,153150字节

Switch[Sort[Join@@BlockMap[If[#[[2,2]]<1,Nothing,Tr[Tr/@#]]&,#~ArrayPad~1,{3,3},1]],{1},0,{2,2,3...},1/.#~ComponentMeasurements~"PolygonalLength",_,]&

采用2D数组,其中0s代表.s,1s代表Xs。Null非曲线的输出。

1/.#~ComponentMeasurements~"PolygonalLength"&

Mathematica为此内置了45字节,但它为非曲线输出一些数字,为input输入1 / sqrt(2){{1}}。纠正这些花费105个字节(可以打高尔夫球吗?)。

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.