离外部有多远?


15

取一个2D空间区域,该区域划分为以轴对齐的单位正方形元素,其中心以整数间隔对齐。如果一条边由两个元素共享,则称该边为内部,否则为外部边。

您的目标是找到从每个元素的中心开始(即traversal distancedistance简称为)到达外部边缘必须经过的最小数量的相邻元素。您只能穿过一条边缘(即没有切角/对角运动)。注意,“外部元素”(具有至少一个外部边缘的元素)被认为需要遍历0相邻元素才能到达外部边缘。

输入值

输入是一个非负整数对坐标的列表,表示所有元素中心的(x,y)。假定不存在重叠元素(即x / y对唯一标识一个元素)。您可能假定有关元素输入顺序的任何信息。

欢迎您将输入的原点转换到任何位置(例如0,0或1,1,等等)。

您可以假定所有输入元素都已连接,或者换句话说,可以使用上述规则从任何一个元素移动到任何其他元素。注意,这并不意味着2D区域只是简单连接。里面可能有孔。

示例:以下为无效输入。

0,0
2,0

在此处输入图片说明

不需要错误检查。

输入可以来自任何来源(文件,stdio,函数参数等)

输出量

输出应该是标识每个元素的坐标列表,并遍历相应的整数距离以到达边缘。输出可以按所需的任何元素顺序进行(例如,您不必按与输入相同的顺序输出元素)。

输出可以是任何源(文件,stdio,函数返回值等)

任何与元素的坐标与其外部距离匹配的输出都可以,例如,所有这些都可以:

x,y: distance
...

[((x,y), distance), ...]

[(x,y,distance), ...]

例子

文本示例输入的格式为x,y,每行一个元素;欢迎您将其重塑为方便的输入格式(请参阅输入格式规则)。

文本示例输出的格式为x,y: distance,每行一个元素;同样,欢迎您将其重塑为方便的输出格式(请参见输出格式规则)。

图形数字的左下边界为(0,0),内部数字表示到达外部边缘的预期最小距离。请注意,这些数字仅用于演示目的;您的程序不需要输出这些。

例子1

输入:

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

输出:

1,0: 0
3,0: 0
0,1: 0
1,2: 0
1,1: 1
2,1: 0
4,3: 0
3,1: 0
2,2: 1
2,3: 0
3,2: 0
3,3: 0

图示:

在此处输入图片说明

例子2

输入:

4,0
1,1
3,1
4,1
5,1
6,1
0,2
1,2
2,2
3,2
4,2
5,2
6,2
7,2
1,3
2,3
3,3
4,3
5,3
6,3
7,3
8,3
2,4
3,4
4,4
5,4
6,4
3,5
4,5
5,5

输出:

4,0: 0
1,1: 0
3,1: 0
4,1: 1
5,1: 0
6,1: 0
0,2: 0
1,2: 1
2,2: 0
3,2: 1
4,2: 2
5,2: 1
6,2: 1
7,2: 0
1,3: 0
2,3: 1
3,3: 2
4,3: 2
5,3: 2
6,3: 1
7,3: 0
8,3: 0
2,4: 0
3,4: 1
4,4: 1
5,4: 1
6,4: 0
3,5: 0
4,5: 0
5,5: 0

图示:

在此处输入图片说明

例子3

输入:

4,0
4,1
1,2
3,2
4,2
5,2
6,2
8,2
0,3
1,3
2,3
3,3
4,3
5,3
6,3
7,3
8,3
9,3
1,4
2,4
3,4
4,4
5,4
6,4
7,4
8,4
9,4
2,5
3,5
4,5
5,5
6,5
9,5
10,5
11,5
3,6
4,6
5,6
9,6
10,6
11,6
6,7
7,7
8,7
9,7
10,7
11,7

输出:

4,0: 0
4,1: 0
1,2: 0
3,2: 0
4,2: 1
5,2: 0
6,2: 0
8,2: 0
0,3: 0
1,3: 1
2,3: 0
3,3: 1
4,3: 2
5,3: 1
6,3: 1
7,3: 0
8,3: 1
9,3: 0
1,4: 0
2,4: 1
3,4: 2
4,4: 2
5,4: 2
6,4: 1
7,4: 0
8,4: 0
9,4: 0
2,5: 0
3,5: 1
4,5: 1
5,5: 1
6,5: 0
9,5: 0
10,5: 0
11,5: 0
3,6: 0
4,6: 0
5,6: 0
9,6: 0
10,6: 1
11,6: 0
6,7: 0
7,7: 0
8,7: 0
9,7: 0
10,7: 0
11,7: 0

图示:

在此处输入图片说明

计分

这是代码高尔夫。以字节为单位的最短代码获胜。有标准漏洞。允许使用除专门设计用来解决此问题的内置程序以外的任何内置程序。


我们可以输出为[[((1,0),0),...]吗?
lirtosiast '16

@lirtosiast是
helloworld922

1
在您的示例中,您没有明确声明输入。
戴尔·约翰逊

@DaleJohnson仅将每个文本输入的前两列用作x,y对。我没有为输入添加单独的报价框,因为它似乎有点长。有没有一种方法可以添加报价框并手动限制其垂直高度?
helloworld922

找到必须遍历才能到达外部边缘的最小数量的相邻元素从哪里开始?您可以在测试caes中添加输出吗?
路易斯·门多

Answers:


2

MATLAB / Octave,143字节

function [v,x,y]=d(x,y)R=S=zeros(max(y+3),max(x+3));i=sub2ind(size(S),y+2,x+2);S(i)=1;while nnz(S=imerode(S,strel('disk',1,0)))R+=S;end;v=R(i);

不打高尔夫球

function [v,x,y]=d(x,y)
  R=S=zeros(max(y+3),max(x+3));
  i=sub2ind(size(S),y+2,x+2);
  S(i)=1;
  while nnz(S=imerode(S,strel('disk',1,0)))
    R+=S;
  end;
  v=R(i);

说明

创建小号乌尔斯河和- [R适当大小的矩阵esult,用零填充。

R=S=zeros(max(y+3),max(x+3));

计算与xy-pairs 对应的线性索引,在边界处填充一个元素。

i=sub2ind(size(S),y+2,x+2);

绘制结构。

S(i)=1;

S示例2所示:

0   0   0   0   0   0   0   0   0   0   0
0   0   0   0   0   1   0   0   0   0   0
0   0   1   0   1   1   1   1   0   0   0
0   1   1   1   1   1   1   1   1   0   0
0   0   1   1   1   1   1   1   1   1   0
0   0   0   1   1   1   1   1   0   0   0
0   0   0   0   1   1   1   0   0   0   0
0   0   0   0   0   0   0   0   0   0   0

通过图像腐蚀去除所有边框元素

S=imerode(S,strel('disk',1,0))

使用半径为1的结构化元素

0   1   0
1   1   1
0   1   0

如果允许对角线移动,我们将改为使用矩形:

1   1   1
1   1   1
1   1   1

然后,为所有非边界元素增加结果

R+=S;

并循环直到图像完全腐蚀为止。

while nnz(S)

返回每个xy-pair 的结果。

v=R(i);

2

Pyth,26个字节

V]MQNf>*4Nl=Nsmfq1.a,dYQN0

例子2

我使用的输出格式是:

[[4, 3]]
2

也就是说,包含点的列表,其后是到外部的距离。

该代码通过使用当前到达的集合来工作,对于每个点,对与该点正好相距1的所有点的输入进行过滤,并检查所得的点数是否为起始数的4倍,并重复进行直到不。当从给定点开始时,它给出了该点与外部的距离。


2

MATL38 37 36 33字节

1Z?t"tX@<~5Bt!Z~2X53$Y+4=+]3#fqhh

这使用语言/编译器的当前版本(15.0.0)

输入格式为:一个具有x值的数组和一个具有y值的数组。输入和输出基于1。因此,测试用例具有以下输入:

[2 4 1 2 2 3 5 4 3 3 4 4]
[1 1 2 3 2 2 4 2 3 4 3 4]

[5 2 4 5 6 7 1 2 3 4 5 6 7 8 2 3 4 5 6 7 8 9 3 4 5 6 7 4 5 6]
[1 2 2 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5 6 6 6]

[5 5 2 4 5 6 7 9 1 2 3 4 5 6 7 8 9 10 2 3 4 5 6 7 8 9 10 3 4 5 6 7 10 11 12 4 5 6 10 11 12 7 8 9 10 11 12]
[1 2 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 7 7 7 7 7 7 8 8 8 8 8 8]

在线尝试!

说明

最初建立一个矩阵,在输入位置为1,否则为0。然后使用“北,东,南,西”遮罩([0 1 0; 1 0 1; 0 1 0])进行卷积,并将每个位置的结果与4进行比较。结果4表示该位置被其他点包围,因此距离为-至少从外部到外部1。将结果(每个点0或1)添加到原始矩阵。这些位置现在包含2(在处理结束时,矩阵将递减1)。

卷积过程被迭代。对于下一次迭代,卷积的输入是以2为阈值的累加矩阵。也就是说,将小于2的值设置为0。卷积的结果表示哪些点的距离至少为2(所有相邻点的距离都为1)。

为方便起见,选择迭代次数作为输入矩阵的列数。这样就足够了(实际上,所需的最大迭代次数是最小矩阵维数的一半)。最后的迭代可能没有用,但是没有害处(它们只是在所有点上加0)。

在该过程的最后,从结果中减去1,因为值k的位置到外部的距离为k -1。提取并显示所有位置的坐标和值。

           % take x and y implicitly
1          % push 1
Z?         % build sparse matrix from that x, y indices with 1 as value
t          % duplicate
"          % for each column of that matrix
  t        %   duplicate
  X@       %   push iteration index
  <~       %   true for matrix entries that are >= iteration index
  5B       %   5 in binary: row vector [1 0 1]
  t!       %   duplicate and transpose into a column vector
  Z~       %   element-wise XOR with broadcast: gives desired mask,
           %   [0 1 0; 1 0 1; 0 1 0]
  2X53$Y+  %   2D convolution. Output has same size as input
  4=       %   compare with 4: are all neighbouring positions occupied?
  +        %   add to accumulated matrix from previous iteration
]          % end for each
3#f        % extract row index, column index and value for nonzero
           % entries. In this case all entries are nonzero
q          % subtract 1 to value to yield distance to exterior
hh         % concatenate vertically twice
           % display implicitly 

1

Python 3中,180个 166 160字节

def f(l,d=0):
 l=set(l);
 if l:i={(a,b)for a,b in l if all([x in l for x in[(a+1,b),(a-1,b),(a,b+1),(a,b-1)]])};return{(c,d)for c in l-i}|f(i,d+1)
 return set()

我们知道,如果一个坐标少于四个邻居,则它必须位于“外部”。因此,在这种情况下,我们可以重复剥离外部单元并为其分配一个等于迭代次数/递归深度的距离。

绝对认为还有改进的余地-检查相邻邻居的最佳方法是什么?

编辑:我应该被允许接受成对的列表作为元组。


0

PHP,316字节

<?preg_match_all("#^(\d+),(\d+)#m",$_GET[i],$t);foreach($t[1]as$k=>$v)$a[$v][$t[2][$k]]=0;function w($x,$y){global$a;return isset($a[$x][$y])?$a[$x][$y]:-1;};for(;$z++<max($t[2]);$o=$s,$s="")foreach($a as$x=>$b)foreach($b as$y=>$c)$s.="\n$x,$y: ".$a[$x][$y]=1+min(w($x+1,$y),w($x-1,$y),w($x,$y-1),w($x,$y+1));echo$o;

在线版本

分解

preg_match_all("#^(\d+),(\d+)#m",$_GET[i],$t); 
foreach($t[1]as$k=>$v) 
$a[$v][$t[2][$k]]=0;  # make a 2 D array
function w($x,$y){global$a;return isset($a[$x][$y])?$a[$x][$y]:-1;};# check the neighbours
for(;$z++<max($t[2]);$o=$s,$s="") # stored the last loop string first run make possible to 1 and so on
foreach($a as$x=>$b) # x values
foreach($b as$y=>$c) # y values
$s.="\n$x,$y: ".$a[$x][$y]=1+min(w($x+1,$y),w($x-1,$y),w($x,$y-1),w($x,$y+1)); # concanate array item x+y+value
echo$o; #Output

可视化为Ascii字符

ksort($a); 
foreach($a as$x=>$b){
for($y=0;$y<=max($t[2]);$y++)
echo isset($a[$x][$y])?$a[$x][$y]:" ";
#The better way would be make a SVG and use the text element and use a factor
#echo '<text x="'.($x*$factor).'" y="'.($y*$factor).'">'.$a[$x][$y].'</text>';
echo"\n";}
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.