Algoritmo para asentar Zoombinis en el ferry del Capitán Cajun?

12

He estado jugando la nueva versión de The Logical Journey of the Zoombinis recientemente, y he tratado de implementar algunos algoritmos informáticos que pueden resolver los diversos acertijos. Estoy atrapado en cómo abordar el rompecabezas del ferry del Capitán Cajun.

Para aquellos que no están familiarizados, un Zoombini es una criatura con 4 atributos: cabello, ojos, nariz y pies. Cada uno de esos atributos tiene 5 valores posibles; por ejemplo, los pies de un Zoombini pueden ser ruedas, patines, zapatillas, un resorte o una hélice. Aquí hay un ejemplo de un Zoombini con cabello desordenado, anteojos, nariz verde y zapatillas de deporte:

En el rompecabezas del ferry, la tarea es organizar una colección de 16 Zoombinis en los 16 asientos de un ferry. El acuerdo debe obedecer la regla de que dos asientos ortogonalmente vecinos deben ser ocupados por Zoombinis que compartan al menos una característica. Si dos Zoombinis tienen cabello diferente, ojos diferentes, narices diferentes y pies diferentes entre sí, es posible que no se sienten uno al lado del otro.

La disposición de los asientos cambia por nivel; para concreción, centrémonos en el nivel "Muy difícil", en el que los 16 asientos están dispuestos en una cuadrícula de 4 por 4. Aquí hay un ejemplo donde 15 Zoombinis se han sentado legalmente, pero el Zoombini final parado en el muelle no se puede colocar en el último asiento vacío, porque no compartiría características con el Zoombini a su derecha:

Ejemplo de rompecabezas casi completado

Hay 16! ≈ 21 billones de asignaciones posibles de Zoombinis a asientos. Entonces, simplemente revisar todas las tareas posibles para ver si es legal no será práctico. ¿Cuáles son algunas heurísticas que podría emplear para abordar este problema con sensatez?

thecommexokid
fuente
2
Me recuerda a sudoku, y los solucionadores de sudoku generalmente implementan algún tipo de retroceso.
mattecapu
2
Si está listo y dispuesto a buscar literatura más compleja, puede encontrar información útil buscando Subgraph Isomorphism Problem. El problema es encontrar un gráfico en otro gráfico. En su caso, el subgrafo sería el asiento (los bordes son adyacencias), mientras que el gráfico principal sería el zoombinis, donde las conexiones serían la presencia de un rasgo compartido. Tenga en cuenta que, en general, el problema es NP-completo y generalmente también se realiza retrocediendo, sin embargo, en algunos casos especiales (de los cuales su gráfico puede ser muy bueno), son posibles soluciones polinómicas o incluso lineales.
Ordous
Esta es una gran idea, me encantaron los zoombinis cuando era niño, ¡podría hacer lo mismo!
AlexFoxGill

Respuestas:

8

Gracias a @mattecapu por el útil término de búsqueda de Google de "algoritmo de retroceso". Eso me dio la comida para pensar que necesitaba.

Mi intuición actual es que podría ser mejor llenar los asientos centrales, que tienen 4 vecinos, primero, y guardar los asientos de la esquina, que tienen solo 2 vecinos, para el final. Así que organizo los 16 asientos vacíos en una lista vinculada en este orden:

13   5   6  14

 7   1   2   9

 8   3   4  10

15  11  12  16

Aquí hay un pseudocódigo que describe la función que terminé escribiendo. Lo alimentas con una lista que contiene los 16 Zoombinis y un puntero al primer asiento en la lista vinculada.

function recursively_assign_seat(zoombini_list, seat):

    if zoombini_list is empty:
        return True

    else:
        for each z in zoombini_list:

            for each n in seat.neighbors:
                if not allowed_as_neighbors(z, n):
                    next z

            seat.occupant ← z
            if recursively_assign_seat(zoombini_list.remove(z), seat.next):
                return True
            else:
                seat.occupant ← None

        return False

¡Realmente funciona sorprendentemente rápido! Estaba muy satisfecho con eso.

Todavía no estoy totalmente convencido de haber organizado la lista de asientos en el mejor orden posible. Hay 24 restricciones totales sobre el problema, y ​​el orden ideal de llenado de asientos enfrentaría cada una de esas restricciones lo antes posible en el proceso de llenado de asientos, de modo que las ramas que no son viables se poden al máximo rápidamente.

thecommexokid
fuente
1
cuando llena 8solo está adyacente a 2, pero podría estar llenando el 9que está adyacente a ambos 7y 3. ¡Buen trabajo para resolverlo!
AlexFoxGill
Hizo esa edición; Sin embargo, todavía no estoy seguro de si el esquema de adentro hacia afuera supera simplemente completar fila por fila. Quizás haga algunas pruebas de tiempo.
thecommexokid