突出显示边界框,第二部分:六边形网格


24

您会得到一个由.和组成的六角形网格#,如下所示:

 . . . . . . . .
. . . . # . . . 
 . # . . . # . .
. . . # . . . . 
 . . . . . # . .
. . . . . . . . 

你的任务是填补的整个轴线对齐边框#进一步#

 . . . . . . . .
. . # # # # . . 
 . # # # # # . .
. . # # # # # . 
 . . # # # # . .
. . . . . . . . 

与轴对齐的边界框是最小的凸六边形形状,其中包含所有#。请注意,在六角形网格的情况下,需要考虑三个轴(W / E,SW / NE,NW / SE):

在此处输入图片说明

这是另一个示例,显示在某些情况下,一个或多个边仅包含一个边#

. . . . . . . .         . . . . . . . . 
 . # . . . . . .         . # # # # . . .
. . . . . # . .         . . # # # # . . 
 . . # . . . . .         . . # # # . . .
. . . . . . . .         . . . . . . . . 

您可以将它们视为具有退化边的六边形,也可以像上面我所做的那样在它们周围绘制边界框,在这种情况下,它们仍然是六边形:

在此处输入图片说明

太难?尝试第一部分!

规则

您可以使用任何两个不同的非空格可打印ASCII字符(0x21至0x7E,包括0x21至0x7E)来代替#.。我会继续提到他们作为#.对规范虽然剩下的时间。

输入和输出可以是单个换行符分隔的字符串,也可以是字符串列表(每行一个),但是格式必须一致。

您可以假定输入至少包含一行,#并且所有行的长度均相同。请注意,有两种不同的“种类”的行(以空格或非空格开头)-您可能无法假设输入始终以相同的类型开头。您可以假设边界框始终适合您所获得的网格。

您可以编写程序或函数,并使用我们的任何标准方法来接收输入和提供输出。

您可以使用任何编程语言,但是请注意,默认情况下,这些漏洞是禁止的。

这是,因此以字节为单位的最短有效答案为准。

测试用例

每个测试用例具有彼此相邻的输入和输出。

#    #

 . .      . . 
# . #    # # #
 . .      . . 

 . #      . # 
. . .    . # .
 # .      # . 

 # .      # . 
. . .    . # .
 . #      . # 

 # .      # . 
# . .    # # .
 . #      # # 

 . #      # # 
# . .    # # #
 . #      # # 

. . #    . # #
 . .      # # 
# . .    # # .

# . .    # # .
 . .      # # 
. . #    . # #

. . . . . . . .         . . . . . . . . 
 . . # . # . . .         . . # # # . . .
. . . . . . . .         . . . # # . . . 
 . . . # . . . .         . . . # . . . .

. . . . . . . .         . . . . . . . . 
 . . # . . . # .         . . # # # # # .
. . . . . . . .         . . . # # # # . 
 . . . # . . . .         . . . # # # . .

. . . . . . . .         . . . . . . . . 
 . # . . . . . .         . # # # # . . .
. . . . . # . .         . . # # # # . . 
 . . . . . . . .         . . . . . . . .

. . . . . . . .         . . . . . . . . 
 . # . . . . . .         . # # # # . . .
. . . . . # . .         . . # # # # . . 
 . . # . . . . .         . . # # # . . .

. . . . # . . .         . . # # # # . . 
 . # . . . # . .         . # # # # # . .
. . . # . . . .         . . # # # # # . 
 . . . . . # . .         . . # # # # . .

1
我的头在旋转,试图找到任何明显的模式。您说的是“六边形”,但是在测试用例中只有两个输入形成六边形。我迷路了。
Anastasiya-Romanova秀

1
@ Anastasiya-Romanova秀如果您将形状描绘为通过外部字符的中心,那么可以肯定的是,某些六边形将具有退化的边(例如在矩形网格中,您可以看到矩形缩小为一条线的情况)。但是,如果您在字符周围绘制矩形(就像我在图中所做的那样),则所有示例都是六边形(其中一些边非常短)。
马丁·恩德

1
@ Anastasiya-Romanova秀新图表有帮助吗?
马丁·恩德

3
一世!看起来像二,如果我有..错了眼镜
尼尔

1
@Neil或者,你知道,酒精过多;)
ThreeFx

Answers:


7

Pyth82 71字节

L,hbebMqH @ S + GH1KhMyJs.e,Lkfq \#@ bTUb.zA,ySm-FdJySsMJj.es.eXW && gKkgG-kYgH + kYZ \。\#bz
MqH @ S [hGHeG)1j.es.eXW && ghMJs.e,Lkfq \#@ bTUb.zkgSm-FdJ-kYgSsMJ + kYZ \。\#bz

在线尝试!

说明

  • 设A为y坐标最低的点,B为y坐标最高的点。

  • 令C为最低点(x值减去y值),D为最高点。

  • 设E为最低点(x值加y值),F为最高点。

然后,这等效于找到y坐标在A和B之间,x值减去y值在C和D之间,x值加y值在E和F之间的坐标。


我第一次可以提早发布解决方案,如果只有SE Android应用程序可以正确处理制表符(由于某种原因,它们在粘贴时会消失):/
Sarge Borsch,2016年

@SargeBorsch对不起:(
Leaky Nun

哈哈,为什么,是SE Android应用让我失败了:D
Sarge Borsch

6

Haskell,256 254 243字节

import Data.List
f=z(\l->(,).(,))[0..]l)[0..]
q l=m(m(\e->min(snd e).(".#"!!).fromEnum.and.z($)(m(\x y->y>=minimum x&&y<=maximum x).transpose.m b.filter((==)'#'.snd).concat$l)$b e))l
b=(m uncurry[const,(-),(+)]<*>).pure.fst
z=zipWith
m=map
q.f

感谢@Damien打高尔夫球f

输入作为字符列表,输出以相同的方式提供。

太可惜了,这真是个野兽。它基于LeakyNun的思想,即根据项目的坐标使用最大值和最小值进行过滤。

m=map实际上节省字节的事实让我感到非常惊讶,因为它看起来是如此昂贵。


说明:

这是一个稍微减少的版本(强调):

import Data.List
f=zipWith(\y l->zipWith(\x e->((y,x),e))[0..]l)[0..]
p=map(\x y->y>=minimum x&&y<=maximum x).transpose.map b.filter((==)'#'.snd).concat
q l=map(map(\e->min(snd e).(".#"!!).fromEnum.and.zipWith($)(p$l)$b e))l
b=(map uncurry[const,(-),(+)]<*>).pure.fst
  • f是一个函数,它(y-index, x-index)在保留列表的原始结构的同时为每个字符分配一个索引。

  • b:给定索引列表中的一项,则b计算[y-index, y - x, y + x]

  • p:给定索引字段,返回3个函数Int -> Bool,第一个函数是y-index的校验,第二个是差值,第三是和。min(snd e)照顾空间(一个空间小于两个)。此功能内嵌在高尔夫球代码中。

  • q给出的索引字段,更改所有必要.#通过检查特定领域回归True到每一个测试功能。

最终的解决方案是q和的组成f


1
f=z(\y->z((,).(,)y)[0..])[0..]
达米安

h x=z x[0..] f=h$h.curry(,)
Damien's

5

Python 3中,380个 378 348 346字节

请注意,缩进使用制表符,而不是空格。

高尔夫球版:

def s(i):
    L=i.splitlines();E=enumerate;A=lambda x,y:(y,x+y,x-y);N=(2**64,)*3;X=(-2**64,)*3
    for y,l in E(L):
        for x,c in E(l):
            if c=='#':p=A(x,y);X=tuple(map(max,X,p));N=tuple(map(min,N,p))
    R=''
    for y,l in E(L):
        for x,c in E(l):
            if c!='.':R+=c
            else:p=A(x,y);f=all(N[j]<=p[j]<=X[j]for j in range(0,3));R+='.#'[f]
        R+='\n'
    return R

在Ideone上测试

说明(以下非高尔夫版本):

所有处理无需任何转换即可完成,只需跳过空格字符。
函数axes_pos计算虚构的“ 3D”坐标的三元组bmin,它们bmax对于所有#字符被累加为(元素方式)最小和最大的三元组(,)。

坐标在中计算def axes_pos(x, y): return y, x + y, lc - y + x
其中X从0到右侧计数,Y从0到底部计数(从第一行到最后一行)。
第一个虚坐标基本上是Y,因为这很明显。它的斧头与绿色边界正交(在OP的图片中),
第二个轴与红色边界正交,第三个与蓝色边界正交。

在第二遍中,替换所有.“ 3D”坐标落入bmin.. bmax范围的元素(按元素计)-在此表达式中对此进行检查all(bmin[j] <= p[j] <= bmax[j] for j in range(0, 3))

带有测试的非高尔夫版本,同样在Ideone上

def solve(i):
    ls = i.splitlines()
    lc = len(ls)

    def axes_pos(x, y):
        return y, x + y, lc - y + x

    I = 2 ** 64
    bmin = (I, I, I)
    bmax = (0, 0, 0)

    for y, line in enumerate(ls):
        for x, char in enumerate(line):
            if char != '#': continue
            p = axes_pos(x, y)
            bmax = tuple(map(max, bmax, p))
            bmin = tuple(map(min, bmin, p))

    result = ''
    for y, line in enumerate(ls):
        for x, char in enumerate(line):
            if char != '.':
                result += char
            else:
                p = axes_pos(x, y)
                f = all(bmin[j] <= p[j] <= bmax[j] for j in range(0, 3))
                result += '#' if f else char
        result += '\n'

    return result


def run_test(a, b):
    result = solve(a)
    if result != b:
        raise AssertionError('\n' + result + '\n\nshould be equal to\n\n' + b)


def run_tests():
    run_test(
        "#\n",

        "#\n")

    run_test(
        " . . \n"
        "# . #\n"
        " . . \n",

        " . . \n"
        "# # #\n"
        " . . \n")

    run_test(
        " . # \n"
        ". . .\n"
        " # . \n",

        " . # \n"
        ". # .\n"
        " # . \n")

    run_test(
        " # . \n"
        ". . .\n"
        " . # \n",

        " # . \n"
        ". # .\n"
        " . # \n")

    run_test(
        " # . \n"
        "# . .\n"
        " . # \n",

        " # . \n"
        "# # .\n"
        " # # \n")

    run_test(
        " . # \n"
        "# . .\n"
        " . # \n",

        " # # \n"
        "# # #\n"
        " # # \n")

    run_test(
        ". . . . . . . . \n"
        " . . # . # . . .\n"
        ". . . . . . . . \n"
        " . . . # . . . .\n",

        ". . . . . . . . \n"
        " . . # # # . . .\n"
        ". . . # # . . . \n"
        " . . . # . . . .\n")

    run_test(
        ". . . . . . . . \n"
        " . . # . . . # .\n"
        ". . . . . . . . \n"
        " . . . # . . . .\n",

        ". . . . . . . . \n"
        " . . # # # # # .\n"
        ". . . # # # # . \n"
        " . . . # # # . .\n")

    run_test(
        ". . . . . . . . \n"
        " . # . . . . . .\n"
        ". . . . . # . . \n"
        " . . . . . . . .\n",

        ". . . . . . . . \n"
        " . # # # # . . .\n"
        ". . # # # # . . \n"
        " . . . . . . . .\n")

    run_test(
        ". . . . . . . . \n"
        " . # . . . . . .\n"
        ". . . . . # . . \n"
        " . . # . . . . .\n",

        ". . . . . . . . \n"
        " . # # # # . . .\n"
        ". . # # # # . . \n"
        " . . # # # . . .\n")

    run_test(
        ". . . . # . . . \n"
        " . # . . . # . .\n"
        ". . . # . . . . \n"
        " . . . . . # . .\n",

        ". . # # # # . . \n"
        " . # # # # # . .\n"
        ". . # # # # # . \n"
        " . . # # # # . .\n")


if __name__ == '__main__':
    run_tests()
更新1:

删除-1了第三虚构坐标的不必要部分,因为它不会改变任何内容

更新2,3:

Leaky Nun我自己也提出了部分实施的改进建议。


我们基本上使用相同的算法吗?你能附上解释吗?
Leaky Nun

1
def A(x,y):return y,x+y,len(L)-1-y+x->A=lambda x,y:(y,x+y,len(L)-1-y+x)
Leaky Nun

同样,列表理解可以帮助您减少一些负担。
Leaky Nun

1
我认为您可以len(L)-y+x成为x-y
Leaky Nun

1
您可以参加专线清单
Leaky Nun

5

果冻45 35 13 42 41 字节

Ṁ€»\
ṚÇṚ«Çṁ"
ŒDṙZL$ÇṙL’$ŒḌ«Ç
ṚÇṚ«Ç
n⁶aÇo⁶

这是链接列表;最后一个必须在输入上调用才能产生输出。

I / O是字符串数组的形式,其中.表示空,@表示填充。

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

背景

让我们考虑以下示例。

. . . . . . . . 
 . @ . . . . . .
. . . . . @ . . 
 . . @ . . . . .

通过在三个方向中的每一个上绘制一对或平行线(最接近的一对,包围所有填充位置),我们可以确定六角形边界框。

在实现中,我们用替换这两行之间的所有字符,用替换@这些行之外的所有字符.,可能只包含对角线的对角线除外)。

对于水平轴,这给出了

................
@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@

对于下降的对角轴,它给出

..@@@@@@@......
...@@@@@@@......
....@@@@@@@.....
 ....@@@@@@@....

对于上升对角线轴,它给出了

....@@@@@@@@@...
...@@@@@@@@@....
..@@@@@@@@@....
.@@@@@@@@@.... .

通过取所有三个字符的最小值,由于.< @,我们得到

...............
...@@@@@@@......
....@@@@@@@....
 ....@@@@@.... .

剩下要做的就是恢复空间。

怎么运行的

n⁶aÇo⁶           Main link. Argument: A (array of strings)

n⁶               Not-equal space; yield 0 for spaces, 1 otherwise.
  aÇ             Take the logical AND with the result the 4th helper link.
                 This will replace 1's (corresponding to non-space characters) with
                 the corresponding character that result from calling the link.
    o⁶           Logical OR with space; replaces the 0's with spaces.
ṚÇṚ«Ç            4th helper link. Argument: A

Ṛ                Reverse the order of the strings in A.
 Ç               Call the 3rd helper link.
  Ṛ              Reverse the order of the strings in the resulting array.
    Ç            Call the 3rd helper link with argument A (unmodified).
   «             Take the character-wise minimum of both results.
ŒDṙZL$ÇṙL’$ŒḌ«Ç  3rd helper link. Argument: L (array of strings)

ŒD               Yield all falling diagonals of L. This is a reversible operation,
                 so it begins with the main diagonal.
   ZL$           Yield the length of the transpose (number of columns).
  ṙ              Shift the array of diagonals that many units to the left.
                 This puts the diagonals in their natural order.
      Ç          Call the helper link on the result.
        L’$      Yield the decremented length (number of columns) of L.
       ṙ         Shift the result that many units to the left.
                 This puts the changed diagonals in their original order.
           ŒḌ    Undiagonal; reconstruct the string array.
              Ç  Call the 2nd helper link with argument L (unmodified).
             «   Take the character-wise minimum of both results.
ṚÇṚ«Çṁ"          2nd helper link. Argument: M (array)

Ṛ                Reverse the rows of M.
 Ç               Call the 1st helper link on the result.
  Ṛ              Reverse the rows of the result.
    Ç            Call the 1nd helper link with argument M (unmodified).
   «             Take the minimum of both results.
     ṁ"          Mold zipwith; repeat each character in the result to the left
                 as many times as needed to fill the corresponding row of M.
Ṁ€»\             1st helper link. Argument: N (array)

Ṁ€               Take the maximum of each row of N.
  »\             Take the cumulative maxima of the resulting characters.

2

Python,237230字节

丹尼斯感谢7个字节。

def f(a):i=range(len(a[0]));j=range(len(a));b,c,d=map(sorted,zip(*[[x,x+y,x-y]for y in i for x in j if"?"<a[x][y]]));return[[[a[x][y],"#"][(a[x][y]>" ")*(b[0]<=x<=b[-1])*(c[0]<=x+y<=c[-1])*(d[0]<=x-y<=d[-1])]for y in i]for x in j]

我在Pyth答案

以行数组作为输入,输出二维字符数组。


2

Perl,128 126个字节

包括+6 -0F\n

使用STDIN上的输入运行。使用1用于填充0空。行的末尾不必用空格填充:

perl -M5.010 hexafill.pl
 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 
 0 1 1 1 1 1 0 0
0 0 1 1 1 1 1 0 
 0 0 1 1 1 1 0 0
0 0 0 0 0 0 0 0 
^D

hexafill.pl

#!/usr/bin/perl -0F\n
$-=map{s%$=%$=^!map{/$/;grep{pos=$`;$=?$_|="!"x$`.1:!/\b.*\G./}${--$@}}@F-$-+pos,$-+pos,$-%eeg;--$-;$=||say}@F while$=--

使用立方体坐标。在$= == 1循环期间确定最大值和最小值,并在循环期间填充这些边界之间的坐标$= == 0。前58个循环是没有意义的,仅在那里填充$-行数


1

TSQL,768字节

我写了一个查询来解决这个问题-我发现这很困难。它无法与所有出色的简短答案竞争。但还是想将其发布给有兴趣的人。很抱歉答案的长度-希望codegolf也适用于不同的方法。

打高尔夫球:

DECLARE @ varchar(max)=
'
. . . . # . . . 
 . # . . . # . .
. . . # . . . . 
 . . . . . # . .
. . . . . . . . 
'

;WITH c as(SELECT cast(0as varchar(max))a,x=0,y=1,z=0UNION ALL SELECT SUBSTRING(@,z,1),IIF(SUBSTRING(@,z,1)=CHAR(10),1,x+1),IIF(SUBSTRING(@,z,1)=CHAR(10),y+1,y),z+1FROM c WHERE LEN(@)>z)SELECT @=stuff(@,z-1,1,'#')FROM c b WHERE((exists(SELECT*FROM c WHERE b.y=y and'#'=a)or exists(SELECT*FROM c WHERE b.y<y and'#'=a)and exists(SELECT*FROM c WHERE b.y>y and'#'=a))and a='.')and(exists(SELECT*FROM c WHERE b.x<=x-ABS(y-b.y)and'#'=a)or exists(SELECT*FROM c WHERE b.x<=x+y-b.y and a='#'and b.y<y)and exists(SELECT*FROM c WHERE b.x<=x+b.y-y and a='#'and b.y>y))and(exists(SELECT*FROM c WHERE b.x>=x+ABS(y-b.y)and'#'=a)or exists(SELECT*FROM c WHERE b.x>=x-y+b.y and b.y<y and'#'=a)and exists(SELECT*FROM c WHERE b.x>=x-b.y+y and a='#'and b.y>y))OPTION(MAXRECURSION 0)PRINT @

取消高尔夫:

DECLARE @ varchar(max)=
'
. . . . # . . . 
 . # . . . # . .
. . . # . . . . 
 . . . . . # . .
. . . . . . . . 
'
;WITH c as
(
  SELECT 
    cast(0as varchar(max))a,x=0,y=1,z=0
  UNION ALL
  SELECT
    SUBSTRING(@,z,1),IIF(SUBSTRING(@,z,1)=CHAR(10),1,x+1),
    IIF(SUBSTRING(@,z,1)=CHAR(10),y+1,y),
    z+1
  FROM c
  WHERE LEN(@)>z
)
SELECT @=stuff(@,z-1,1,'#')FROM c b
WHERE((exists(SELECT*FROM c WHERE b.y=y and'#'=a)
or exists(SELECT*FROM c WHERE b.y<y and'#'=a)
and exists(SELECT*FROM c WHERE b.y>y and'#'=a)
)and a='.')
and 
(exists(SELECT*FROM c WHERE b.x<=x-ABS(y-b.y)and'#'=a)
or exists(SELECT*FROM c WHERE b.x<=x+y-b.y and a='#'and b.y<y)
and exists(SELECT*FROM c WHERE b.x<=x+b.y-y and a='#'and b.y>y))
and(exists(SELECT*FROM c WHERE b.x>=x+ABS(y-b.y)and'#'=a)
or exists(SELECT*FROM c WHERE b.x>=x-y+b.y and b.y<y and'#'=a)
and exists(SELECT*FROM c WHERE b.x>=x-b.y+y and a='#'and b.y>y))
OPTION(MAXRECURSION 0) 
PRINT @

小提琴


1

GNU八度,212,196个字节

也许这并不是高尔夫球手最喜欢的选择语言,但这就是挑战所在,不是吗?假设m被作为一个char矩阵:178个字节是独立的,如果填充到函数中则是196 个字节

打高尔夫球:

function k=f(m)[a,b]=size(m);[y,x]=ndgrid(1:a,1:b);t={y,y+x,x-y};k=m;s=x>0;for j=1:3l{j}=unique(sort(vec(t{j}.*(m==['#']))))([2,end]);s&=(l{j}(1)<=t{j})&(l{j}(2)>=t{j});endk(s&mod(x+y,2))=['#']end

松散:

function k=f(m)
[a,b]=size(m);[y,x]=ndgrid(1:a,1:b);t={y,y+x,x-y};k=m;s=x>0;
for j=1:3
  l{j}=unique(sort(vec(t{j}.*(m==['#']))))([2,end]);
  s&=(l{j}(1)<=t{j})&(l{j}(2)>=t{j});
end
k(s&mod(x+y,2))=['#']
end

说明:我们建立一个坐标系统,三个轴-正交于六边形的边,找到每个坐标的最大值和最小值,然后构建一个逻辑遮罩,从任何地方开始以逻辑方式从1开始,并设置每个坐标的最大值和最小值约束,最后重新设置每个剩余的“ true”位置都应为“#”字符。

如果要对其进行测试,则可以像这样创建m矩阵:

m = [' . . . . . . . .. . . . # . . .  . # . . . # . .. . . # . . . .  . . . . . # . .. . . . . . . . ']; m = reshape(m,[numel(m)/6,6])';

然后调用f(m)并通过建立两个矩阵与m进行比较:

['     before           after      ';m,ones(6,1)*'|',f(m)]

1
(迟来)欢迎来到PPCG!倍频程答案非常受欢迎。:)不过有两件事:1)请包括您实际计算的代码(没有不必要的空格),以便人们可以更轻松地检查分数。您可以单独包含可读版本。2)您提交的内容似乎是一个片段,假定输入要存储在中m,输出要存储在中k答案应始终为完整程序或可调用函数。
马丁·恩德

谢谢!是的,您是对的,我现在将k和m嵌入到函数f中,并添加了一个片段以构造第一个测试m进行验证。
mathreadler '16
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.