Validador Pentomino

9

Como alguien que no puede molestarse en mirar sus pentominos para ver si tiene una forma rectangular, he decidido hacerte escribir un programa que lo haga.

Tu tarea

Dada alguna entrada dividida por nuevas líneas que contienen 12 caracteres únicos, decida si es una solución válida.

Una solución válida DEBE

  • Tener 5 de cada personaje (excepto las nuevas líneas)
  • Cada conjunto de caracteres debe estar completamente conectado
  • Cada conjunto de personajes debe tener una forma única
  • Estar en una forma rectangular regular

Si es una solución válida, generar un valor verdadero, de lo contrario generar un valor falso.

Su programa puede ser una función o un programa completo, pero debe tomar la entrada de stdin y la salida a stdout.

Casos de prueba

Soluciones 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=-

Configuraciones 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
fuente
1. ¿El reflejo de un pentomino tiene la misma forma que el original? 2. ¿Podemos suponer que la entrada consistirá en caracteres ASCII imprimibles y líneas nuevas?
Dennis
@Dennis Sí y Sí
Azul
@DigitalTrauma No es remotamente un duplicado de eso. Por cierto, esa fue una pregunta increíble, es una pena que no haya tenido tiempo de responderla cuando se me hizo una nueva pregunta.
Level River St
@steveverill tienes razón - No leí esta pregunta correctamente
Digital Trauma

Respuestas:

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 guardados gracias a @DankMemes !

Uso

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

Explicación

Un par de notas sobre esta solución:

  • Es posible que esta respuesta no sea válida. En realidad, no verifica si los pentominoes rotados tienen la misma forma, sin embargo, intenté pero no pude encontrar un rectángulo de pentomino válido que cumpla con los requisitos de las reglas e incluye dos o más de la misma forma rotada. Pero no soy un experto en pentomino, así que si encuentras una combinación válida con la que esto falla, avísame.
  • Las reglas también requieren respuestas para su uso STDINy STDOUTpara la entrada y salida, pero prompt()solo están diseñadas para la entrada de una sola línea y mi computadora (Windows) coloca automáticamente \r\ncaracteres en cada nueva línea al pegar, por lo que lo convertí en una función que acepta una cadena.
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
)
usuario81655
fuente
1
Puede abusar de las plantillas etiquetadas l=p.indexOf`<newline here>`para guardar 2 bytes
DankMemes
@DankMemes ¡Gracias por la captura! Estaba realmente cansado cuando escribí esto y aún no lo he verificado dos veces. : P
user81655