您可以将六聚氰胺折叠成立方体吗?


24

我的孩子最喜欢的玩具之一就是这样的玩具。实际上,它是我最喜欢的玩具之一-我一直在玩它,它给了我一些PPCG挑战的想法。这是一个:

编写一个程序或函数,将ASCII线条图作为输入,并确定是否折成立方体。

输入项

输入将仅由一个这样的正方形构成的六边形组成:

+-+
| |
+-+

例如,有效的输入heximino为:

+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
  | |
  +-+

输出量

  • 如果六氨基可以折叠成立方体,则为真实值,或者
  • 否则为假值。

为了节省我们的工作量,维基百科具有以下出色的图形:

  • 所有35种六聚氰胺:

  • 折叠成立方体的所有11种六聚氰胺:

笔记

  • 输入的六胺可能会发生旋转或反射,而不仅仅是上图所示
  • 输入的六氨基酸可能有前导空格,但会相对于它们正确对齐
  • 输入的六边形可能在行的末尾有尾随空格,在输入的末尾有尾随新行

1
您能解释一下为什么这里有一个图像处理标签吗?问题和答案都不必进行任何类型的图像处理来解决挑战。
Optimizer

关于前导/尾随空格的澄清:输入中是否允许每行上不必要的前导/尾随空格和不必要的换行符?我应该能够管理1000个以上的字符输入吗?
edc65

@ edc65是的,您应该期望所描述的不必要的空格。最大输入大小为1000个字符似乎是合理的-我将在
Digital Trauma

嗯 我想知道在打印的页面上可以挤压并置多少个立方体六聚体?
luser droog

Answers:


7

PMA /蜗牛,130

.!(z\ |o{c..!(z\ }3){w=(..!(z\ )|b..!(z\ )o{..!(z\ }2|c{..!(z\ }1,2w..!(z\ )|w{..!(z\ }1,2c..!(z\ }4o..!(z\ )(..!(z\ )|n..!(z\ )`2

或更“可读”

?
.!(z\  | o{c..!(z\ }3  )
{w =( ..!(z\ ) | b ..!(z\ ) o {..!(z\ }2  | c {..!(z\ }1,2w..!(z\ ) | w {..!(z\ }1,2c..!(z\  }4
o  ..!(z\ ) ( ..!(z\ ) | n ..!(z\ ) `2

异常地,出现了一个问题,可以通过到目前为止实现的有限功能来解决。该!(z\ )模式使用否定断言确定在某个“八边形”方向上存在空间,从而确定当前位置在正方形中间的空间。总体思路是检查一种模式,该模式在相对于匹配开始的正方形的5个必需位置的每个位置放置一个正方形。另外,它需要检查它是否不在2x2的正方形块中。在程序运行之前,我不得不通过括号修复一个错误。

如果hexomino没有映射立方体,0则打印。如果是这样,则会打印一些正整数(匹配数)。

我修改了此多米诺发生器,以创建所有可能的测试用例:

n=input()
r=range
T=lambda P:set(p-min(p.real for p in P)-min(p.imag for p in P)*1j for p in P)
A=[]
for i in r(1<<18):
 P=[k%3+k/3*1j for k in r(18)if i>>k&1]
 C=set(P[:1])
 for x in P:[any(p+1j**k in C for k in r(4))and C.add(p)for p in P]
 P=T(P)
 if not(C^P or P in A or len(P)-n):
  #for y in r(4):print''.join(' *'[y+x*1j in P] for x in r(6))
  o = [ [' ']*13 for _ in r(9)]
  for y in r(4):
   for x in r(6):
    if y+x*1j in P: X=2*x;Y=2*y; o[Y][X]=o[Y+2][X]=o[Y][X+2]=o[Y+2][X+2]='+'; o[Y][X+1]=o[Y+2][X+1]='-';o[Y+1][X+2]=o[Y+1][X]='|'
  print '\n'.join(map(''.join,o))
  A+=[T([p*1j**k for p in P])for k in r(4)]

hahahahahahahahah更“可读”
Optimizer

5

Ruby,173148145143字节

h=->b,c{[c.count(c.max),c.count(c.min),3].max*2<b.max-b.min}
->s{x=[];y=[];i=j=0
s.bytes{|e|e==43&&x<<i|y<<j;i=e<32?0*j+=1:i+1}
h[x,y]||h[y,x]}

最新更改:/2在右侧<被替换为*2左侧。允许消除一组()

说明

该代码分为两部分:执行解析的主要未命名函数和分配给h执行检查的变量的辅助未命名函数。

主函数按字节顺序扫描字符串,并将找到i,j的所有+符号的x和y坐标相加到x[]y[]。然后它调用h两次。第一次假定六边形是水平的(x[]包含长度和y[]宽度),第二次假定它是垂直的。

该函数h采用array中的纵向坐标,b然后采用array中的横向坐标c它通过表达式计算长度(以平方为单位) (b.max.b.min)/2。如果该值小于或等于3,则应在另一个方向上评估hexomino,以便h返回false

检查六边形将发现,如果长度为4,则将折叠成一个立方体的那些六边形+在第一行和最后一行中不得超过2个正方形(3个符号)。大部分正方形都集中在中间行,它将变成立方体的赤道。事实证明,此条件对于将折叠成立方体的长度为4的六氨基是必要的和充分的。

只有一个长度为5的六氨基会折叠成立方体。它+的第一行和最后一行有3个正方形(4个符号)。长度为5的所有其他六氨基+在第一行或最后一行具有5个或更多符号。

长度为6的hexomino只有1个+。每行有7个符号。

将所有这些放在一起,足以检查hexomino的长度是否大于3,并且+第一行和最后一行(以较高者为准)上的符号数小于该长度。

取消测试程序

#checking function as explained in text
h=->b,c{[c.count(c.max),c.count(c.min),3].max<(b.max-b.min)/2}

#main function for parsing
f=->s{
  x=[]                 #separate assignments required, 
  y=[]                 #otherwise we get 2 pointers to the same array
  i=j=0                #start coordinates 0,0
  s.bytes{|e|          #scan string bytewise
    e==43&&x<<i|y<<j     #if byte is a + symbol (ascii 43) add the coordinates to arrays x and y
    i=e<32?0*j+=1:i+1    #if byte is before ascii 32 assume newline, increment j and zero i. Otherwise increment i
  }
  h[x,y]||h[y,x]       #call h twice, with x and y in each possible order
}



#VALID INPUTS
puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
| |
+-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
  | |
  +-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
+-+
| |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
      | |
      +-+"]

puts f["
    +-+
    | |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
    +-+
    | |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]


puts f["
  +-+
  | |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
  +-+
  | |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]  
puts f["
+-+-+
| | |
+-+-+-+
  | | |
  +-+-+-+
    | | |
    +-+-+"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+-+
      | | | |
      +-+-+-+
"]


#INVALID INPUTS

puts f["
  +-+-+-+
  | | | |
  +-+-+-+
  | | | |
  +-+-+-+
"]


puts f["
  +-+-+-+-+-+-+
  | | | | | | |
  +-+-+-+-+-+-+

"]


puts f["
  +-+-+
  | | |
  +-+-+
  | |
  +-+
  | |
  +-+
  | |
  +-+
  | |
  +-+
"]

puts f["
  +-+-+-+-+-+
  | | | | | |
  +-+-+-+-+-+
    | |
    +-+
"]

puts f["
      +-+
      | |
  +-+-+-+-+-+
  | | | | | |
  +-+-+-+-+-+
"]

puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+-+
        | | |
        +-+-+"]

puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
      | | |
      +-+-+
"] 


puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
  | | | |
  +-+ +-+
"]

puts f["
 +-+   +-+
 | |   | |
 +-+-+-+-+
 | | | | |
 +-+-+-+-+
"]

puts f["
   +-+-+
   | | |
 +-+-+-+-+
 | | | | |
 +-+-+-+-+
"]

puts f["
  +-+
  | |
  +-+
  | |
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
"]

puts f["
  +-+
  | |
  +-+-+-+
  | | | |
  +-+-+-+
  | |
  +-+
  | |
  +-+
"]

puts f["
  +-+
  | |
+-+-+-+
| | | |
+-+-+-+
| |
+-+
| |
+-+"]

puts f["
  +-+-+
  | | |
  +-+-+
  | |
  +-+-+
  | | |
  +-+-+
    | |
    +-+
"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+
    | | | |
    +-+-+-+
"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+
      | |
      +-+-+
      | | |
      +-+-+
"]


puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+
      | | |
      +-+-+
        | |
        +-+
"]

pentonimo→您的文本中的hexonimo?
圣保罗Ebermann

3

JavaScript(ES6),443431

编辑错误修复,输入解析期间出现问题,删除空白列

F=t=>(a=b=c=d=e=f=g=h=0,M=Math.min,
t=t.split('\n').filter(r=>r.trim()>''),
t=t.map(r=>r.slice(M(...t.map(r=>r.search(/\S/))))),
t.map((r,i)=>i&1&&[...r].map((_,j)=>j&1&&r[j-1]==r[j+1]&t[i-1][j]==t[i+1][j]&r[j-1]=='|'
&&(y=i>>1,x=j>>1,z=y*5,w=x*5,a|=1<<(z+x),e|=1<<(w+y),b|=1<<(4+z-x),f|=1<<(4+w-y),c|=1<<(20-z+x),g|=1<<(20-w+y),d|=1<<(24-z-x),h|=1<<(24-w-y)
))),~[1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056].indexOf(M(a,b,c,d,e,f,g,h)))

这很长,甚至更长,因为解析输入是任务的很大一部分。

我要做的是验证给定的输入是否为11种可折叠六边形之一。

每个可折叠的六边形都可以映射到一些5x5位图(最多8个不同的位图,包括模拟和旋转)。将位图作为25位数字,我使用以下代码(具有非常简单的输入格式)找到了11个指定六边形的最小值。

h=[ // Foldable hexominoes
'o\noooo\no', ' o\noooo\n o', // pink
'o\noooo\n   o', ' o\noooo\n  o', 'ooo\n  ooo', 'oo\n oo\n  oo', //blue
'o\noooo\n o', 'o\noooo\n  o', 'oo\n ooo\n o', 'oo\n ooo\n  o', 'o\nooo\n  oo' // gray
]
n=[]
h.forEach(t=>(
  a=[],
  t.split('\n')
    .map((r,y)=>[...r]
      .map((s,x)=>s>' '&&(
         a[0]|=1<<(y*5+x),a[1]|=1<<(x*5+y),  
         a[2]|=1<<(y*5+4-x),a[3]|=1<<(x*5+4-y),  
         a[4]|=1<<(20-y*5+x),a[5]|=1<<(20-x*5+y),  
         a[6]|=1<<(24-y*5-x),a[7]|=1<<(24-x*5-y))
     )
  ),
n.push(Math.min(...a))
))

那给 [1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056]

因此,给定输入字符串,我必须做同样的事情才能找到最小位图,然后如果此数字出现在我的预计算列表中,则返回true。

// Not so golfed 

F=t=>(  
  a=b=c=d=e=f=g=h=0,M=Math.min,
  t=t.split('\n').filter(r=>r.trim()>''), // remove blank lines
  t=t.map(r=>r.slice(M(...t.map(r=>r.search(/\S/))))), // remove blank colums to the left
  t.map((r,i)=>i&1&&[...r] // only odd rows
   .map((_,j)=>j&1&& // only odd columns
      r[j-1]==r[j+1]&t[i-1][j]==t[i+1][j]&r[j-1]=='|' // found a cell
         &&(y=i>>1,x=j>>1,z=y*5,w=x*5, // find bitmaps for 8 rotations/simmetries
            a|=1<<(z+x),e|=1<<(w+y),  
            b|=1<<(4+z-x),f|=1<<(4+w-y),  
            c|=1<<(20-z+x),g|=1<<(20-w+y),  
            d|=1<<(24-z-x),h|=1<<(24-w-y)  
    ))),
   ~[1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056].indexOf(Math.min(a,b,c,d,e,f,g,h)) // look for min
)

运行片段以在Firefox中进行测试


如果我错过了什么,请原谅我,但是您不能,\nt=t从第二行的结尾/第三行的开头吗?
Conor O'Brien 2015年

@CᴏɴᴏʀO'Bʀɪᴇɴ经过六个月的审核,解析代码可以缩短10 ... 15个字节。照原样,我需要在第2行中给t赋值,在第3行中又赋值,因为在第3行中它用于查找要在左侧剪切的空白字符的数量。
edc65
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.