Validador Pentomino

9

Como alguém que não pode se incomodar em olhar para seus pentominos para ver se ele tem uma forma retangular, decidi fazer você escrever um programa que faça isso.

Sua tarefa

Dada a entrada dividida por novas linhas contendo 12 caracteres únicos, decida se é uma solução válida.

Uma solução válida DEVE

  • Tenha 5 de cada personagem (exceto novas linhas)
  • Cada conjunto de caracteres deve estar totalmente conectado
  • Cada conjunto de caracteres deve ter uma forma única
  • Ter uma forma retangular regular

Se for uma solução válida, emita um valor verdadeiro, caso contrário, emita um valor falso.

Seu programa pode ser uma função ou um programa completo, mas deve levar a entrada de stdin e a saída para stdout.

Casos de teste

Soluções válidas

000111
203331
203431
22 444
2   46
57 666
57769!
58779!
58899!
5889!!

00.@@@ccccF111//=---
0...@@c))FFF1//8===-
00.ttttt)))F1/8888=-

Configurações inválidas

invalid (doesn't contain 12 unique characters)

111112222233333444445555566666
77777888889999900000qqqqqwwwww (Each set has the same shape)

1234567890qw
w1234567890q
qw1234567890
0qw123456789
90qw12345678 (None of the characters are connected)

1234567890qw (Not 5 characters in every set)

1111122222333334444455555666666
77777888889999900000qqqqqwwwwww (More than 5 characters in some sets)

00
0                   
00.@@@ccccF111//=---
 ...@@c))FFF1//8===-
  .ttttt)))F1/8888=- (Doesn't form a rectangular shape)
Azul
fonte
1. O reflexo de um pentomino tem a mesma forma que o original? 2. Podemos assumir que a entrada consistirá em caracteres ASCII imprimíveis e novas linhas?
Dennis
@Dennis Sim e Sim
Azul
@DigitalTrauma Não é remotamente uma duplicata disso. Aliás, essa foi uma pergunta incrível, é uma pena que eu não tenha tido tempo de responder quando ela foi solicitada recentemente.
Level River St
@steveverill você está certo - eu não li essa pergunta corretamente #
Digital Trauma

Respostas:

3

JavaScript (ES6), 237 235 222 bytes

f=p=>(m=[],s=[],d=0,l=p.indexOf`
`+1,[...p].map((c,i)=>(i+1)%l&&!m[i]?g=d-2<s.indexOf((t=a=>m[a]|p[a]!=c?r=0:(m[a]=y.push(a),n=a<n?a:n,t(a+1)+t(a-1)+t(a+l)+t(a-l)+1))(n=i,y=[])!=5?g=0:s[d++]=y.map(a=>r+=a-n)|r):0),d==12&g)

2 bytes salvos graças a @DankMemes !

Uso

f(`000111
203331
203431
22 444
2   46
57 666
57769!
58779!
58899!
5889!!`);
=> true

Explicação

Algumas notas sobre esta solução:

  • É possível que esta resposta não seja válida. Na verdade, ele não verifica se os pentominós rotados têm a mesma forma, no entanto, tentei, mas não consegui encontrar um retângulo pentomino válido que atenda aos requisitos das regras e inclua dois ou mais da mesma forma rotacionada. Mas eu não sou especialista em pentomino, portanto, se você encontrar uma combinação válida com a qual isso falha, entre em contato.
  • As regras também exigem respostas para usar STDINe STDOUTpara entrada e saída, mas prompt()são projetadas apenas para entrada em linha única e o meu computador (Windows) coloca automaticamente \r\ncaracteres em cada nova linha ao colar, então eu fiz uma função que aceita uma string.
f=p=>(
  m=[],                      // m = map of checked characters
  s=[],                      // s = list of shapes found (stored as integer)
  d=0,                       // d = number shapes found
  l=p.indexOf`
`+1,                         // l = length of each line (including newline character)
  [...p].map((c,i)=>         // iterate through each character of the input
    (i+1)%l&&                // skip newline characters
      !m[i]?                 // skip the character if it has already been mapped
        g=                   // g = pentomino is valid
          d-2<s.indexOf(     // check if shape already existed before just now
            (t=a=>           // t() checks if character is part of the shape then maps it
              m[a]|          // skip if character is already mapped
                p[a]!=c      //    or if the current character is part of the shape
              ?r=0:(
                m[a]=        // mark the character as mapped
                  y.push(a), // y = list of shape character indices
                n=a<n?a:n,   // n = minimum index of all characters in the shape
                t(a+1)+      // check and map adjacent characters
                t(a-1)+
                t(a+l)+
                t(a-l)+
                1
              )
          )(n=i,y=[])
            !=5?g=0:         // make sure there are only 5 characters in the shape
            s[d++]=          // add the shape to the list
              y.map(a=>      // sum of (index of each character in the shape - minimum
                r+=a-n)|r    //     index) = unique integer representing the shape
        ):0
  ),
  d==12&g                    // ensure there is 12 shapes and return the 'is valid' result
)
user81655
fonte
11
Você pode abusar dos modelos marcados com l=p.indexOf`<newline here>`para salvar 2 bytes #
DankMemes
@DankMemes Obrigado pela captura! Eu estava realmente cansado quando escrevi isso e ainda não o verifiquei duas vezes. : P
user81655