Você pode dobrar um hexomino em um cubo?


24

Um dos brinquedos favoritos do meu filho é um conjunto como este . Na verdade, é um dos meus brinquedos favoritos - eu brinquei com ele e me deu algumas idéias de desafio para o PPCG. Aqui está um:

Escreva um programa ou função que use um desenho de linha ASCII como entrada e decida se ele deve ou não ser dobrado em um cubo.

Entrada

A entrada consistirá em exatamente um hexomino construído a partir de quadrados como este:

+-+
| |
+-+

Por exemplo, um heximino de entrada válido é:

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

Saída

  • Um valor verdadeiro se o hexomino puder ser dobrado em um cubo ou
  • Um valor falsey caso contrário.

Para economizar um pouco de trabalho, a wikipedia possui ótimos gráficos de:

  • Todos os 35 hexominoes:

  • Todos os 11 hexominoes que se dobram em cubos:

Notas

  • Os hexominoes de entrada podem ter rotação ou reflexão, não apenas os mostrados nas imagens acima
  • Os hexominoes de entrada podem ter espaços à esquerda, mas serão alinhados corretamente em relação a si mesmos
  • Os hexominoes de entrada podem ter espaço à direita no final das linhas e novas linhas à direita no final da entrada

11
Você pode explicar por que há uma tag de processamento de imagem aqui? Nem a pergunta nem a resposta precisarão fazer nenhum tipo de processamento de imagem para resolver o desafio.
Optimizer

Esclarecimentos sobre o espaço inicial / final: são necessários espaços iniciais / finais desnecessários em cada linha e novas linhas desnecessárias permitidas na entrada? Devo ser capaz de gerenciar uma entrada de mais de 1000 caracteres?
edc65 10/05

@ edc65 sim, você deve esperar o espaço em branco desnecessário que você descreve. Tamanho da entrada 1000 caracteres no máximo parece razoável - Vou editar isso em
Digital Trauma

Hmm. Gostaria de saber quantos hexominoes de cubo podem ser espremidos, justapostos, em uma página impressa?
Luser droog

Respostas:


7

PMA / Caracóis , 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

ou mais "legível",

?
.!(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

De maneira incomum, surgiu um problema que pode ser tratado pela quantidade limitada de recursos implementados até o momento. O !(z\ )padrão determina que a posição atual está no espaço no meio de um quadrado usando uma afirmação negativa de que existe um espaço em alguma direção "octilinear". A idéia geral é verificar um padrão que coloque um quadrado em cada um dos 5 locais necessários em relação ao quadrado em que a partida começa. Além disso, ele precisa verificar se não está em um bloco de quadrados 2x2. Antes que o programa funcionasse, tive que corrigir um erro com a análise de parênteses.

Se o hexomino não mapear um cubo, 0será impresso. Caso isso aconteça, algum número inteiro positivo é impresso (número de correspondências).

Eu adaptei este gerador polyomino para criar todos os casos de teste possíveis:

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)]

hahahahahahahah mais "legível"
Optimizer

5

Ruby, 173 148144 143 bytes

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]}

Última alteração: /2no lado direito ou <substituído por *2no lado esquerdo. Permite a eliminação de um conjunto de()

Explicação

O código está dividido em duas partes: uma função principal sem nome que faz a análise e uma função auxiliar sem nome atribuída à variável hque faz a verificação.

A função principal varre o bytewise pela string, adicionando as coordenadas xey i,jde todos os +símbolos encontrados em x[]e y[]. Em seguida, chama hduas vezes. A primeira vez que assume que o hexomino é horizontal ( x[]contém os comprimentos e y[]as larguras) e a segunda vez que assume que é vertical.

A função hpega as coordenadas longitudinais na matriz be as coordenadas longitudinais na matriz c. Calcula o comprimento (em quadrados) da expressão (b.max.b.min)/2. Se for menor ou igual a 3, o hexomino deve ser avaliado na outra direção para hretornar false.

A inspeção dos hexominos mostrará que, se o comprimento for 4, os hexominos que se dobrarão em um cubo não terão mais que 2 quadrados (3 +símbolos) na primeira e na última linha . A maioria dos quadrados está concentrada na linha do meio, que se tornará o equador do cubo. Essa condição acaba sendo necessária e suficiente para um hexomino de comprimento 4 que se dobra em um cubo.

Existe apenas um hexomino de comprimento 5 que se dobrará em um cubo. Possui 3 quadrados (4 +símbolos) na primeira e na última linha. Todos os outros hexominos de comprimento 5 têm 5 ou mais +símbolos na primeira ou na última linha.

Existe apenas um hexomino de comprimento 6. Ele possui 7 +símbolos em cada linha.

Juntando tudo isso, é suficiente verificar se o comprimento do hexomino é maior que 3 e o número de +símbolos na primeira e na última linha (o que for maior) é menor que o comprimento.

Ungolfed in program program

#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 no seu texto?
Paŭlo Ebermann 17/11/2015

3

JavaScript (ES6), 443 431

Editar correção de bug, problema durante a análise de entrada, removendo colunas em branco

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)))

Isso é muito longo e ainda mais, pois a análise de entrada é uma grande parte da tarefa.

O que faço é verificar se a entrada fornecida é um dos 11 hexominos dobráveis.

Cada hexomino dobrável pode ser mapeado para algum bitmap 5x5 (até 8 diferentes, com simetria e rotações). Tomando os bitmaps como número de 25 bits, eu encontrei os valores mínimos para os 11 hexominos anotados, usando o código a seguir (com formato de entrada muito simples)

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))
))

Isso dá [1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056]

Portanto, dada a string de entrada, tenho que fazer o mesmo para encontrar o bitmap mínimo e retornar true se esse número estiver presente na minha lista de pré-cálculos.

// 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
)

Execute o snippet para testar no Firefox


Perdoe-me se estiver faltando alguma coisa, mas você não conseguiu ,\nt=tdesde o final da segunda linha / o início da terceira linha?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ revendo seis meses depois, o código de análise poderia ser 10 ... 15 bytes mais curto. Como é, preciso da atribuição de t na linha 2 e novamente na linha 3 porque na linha 3 é usado para encontrar o número de caracteres em branco a serem cortados no lado esquerdo.
edc65
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.