2013-01-28 21 views
16

In primo luogo, non sono necessariamente alla ricerca di un algoritmo completo che posso semplicemente copiare e incollare, quindi chiamarlo un giorno. Qualsiasi soluzione di "approccio generale" andrebbe bene per me!Genera un puzzle Zebra/Einstein generando algoritmo

Questo post è stato stimolato da una giornata di lavoro lento, e inciampato su this site e non essere in grado di capire come hanno implementato il loro generatore.

Il problema

Per quelli di voi che non conoscono, la "Zebra Puzzle" o "Puzzle di Einstein" è un famoso puzzle logico che probabilmente avete eseguito in prima.

L'intero articolo wiki è here, ma inserirò i bit pertinenti.

There are five houses. 
The Englishman lives in the red house. 
The Spaniard owns the dog. 
Coffee is drunk in the green house. 
The Ukrainian drinks tea. 
The green house is immediately to the right of the ivory house. 
The Old Gold smoker owns snails. 
Kools are smoked in the yellow house. 
Milk is drunk in the middle house. 
The Norwegian lives in the first house. 
The man who smokes Chesterfields lives in the house next to the man with the fox. 
Kools are smoked in the house next to the house where the horse is kept. 
The Lucky Strike smoker drinks orange juice. 
The Japanese smokes Parliaments. 
The Norwegian lives next to the blue house. 

Now, who drinks water? Who owns the zebra? In the interest of clarity, it must be 
added that each of the five houses is painted a different color, and their inhabitants 
are of different national extractions, own different pets, drink different beverages 
and smoke different brands of American cigarets [sic]. One other thing: in statement 
6, right means your right. 

Questo va tutto bene. Ho trovato diversi modi concisi e accurati online per risolvere questo problema, specialmente usando la programmazione dei vincoli. Tuttavia, ciò che mi interessa è rendere più di questi tipi di puzzle.

Fare più

Ovviamente, una rappresentazione matriciale è un modo logico pensare a questo. Con ogni colonna contenente una persona, casa, cosa bevono, che tipo di auto guidano, ecc.

Il mio pensiero iniziale era di iniziare con una griglia generata a caso che è completa (cioè risolta) quindi (in qualche modo) creare suggerimenti dalla versione risolta che lo identificano in modo univoco. Ogni volta che qualcosa può essere determinato, viene rimosso dalla griglia.

strappando il sito che ho elencato all'inizio, i seguenti "suggerimenti" che possono essere utilizzati per risolvere la griglia possono essere del seguente tipo:

  • La persona/animale/vegetale vive/cresce in una data casa

  • La persona/animale/pianta non vive/cresce in una data casa.

  • La persona/animale/pianta vive nella stessa casa degli altri persona/animale/pianta.

  • La persona/animale/pianta è un vicino diretto dell'altro persona/animale/pianta.

  • La persona/animale/pianta è il vicino di sinistra o destra di altri persona/animale/pianta.

  • C'è una casa tra la persona/animale/pianta e l'altra persona/animale/pianta.

  • C'è una casa tra la persona/animale/piano e l'altra persona/animale/pianta a sinistra oa destra.

  • Ci sono due case tra la persona/animale/pianta e l'altra persona/animale/pianta.

  • Ci sono due case tra la persona/animale/piano e l'altra persona/animale/pianta a sinistra oa destra.

  • La persona/animale/pianta vive a destra oa sinistra dell'altro persona/animale/pianta.

Si può vedere come questi potrebbero essere generalizzati, esteso, ecc;

La difficoltà è che, usando il mio approccio (partendo da una griglia completa e generando questi suggerimenti), non sono sicuro di come assicurarsi che il set di suggerimenti che creo sia assolutamente determinante nella griglia di destinazione.

Ad esempio, se si dice "L'inglese non possiede un albero di pino" non è possibile abbinare in modo decisivo due cose in un dato momento nel puzzle. Tuttavia, se ci fossero solo due alberi rimanenti da risolvere, questo potrebbe di fatto essere una prova decisiva.

Sto pensando a questo nel modo completamente sbagliato? Un approccio migliore sarebbe quello di creare una griglia con alcuni elementi noti, predefiniti e randomizzati (cioè, la casa rossa è nel mezzo) e quindi costruire la griglia usando questi suggerimenti come regole per la costruzione?

Qualsiasi consiglio, articoli da leggere, tecniche di programmazione per conoscere, ecc. Sarebbe molto apprezzato!

+0

Post correlati: http://gamedev.stackexchange.com/questions/5909/data-structures-for-logic-games -deduction-rules-sufficienti-set-of-clues – greenoldman

risposta

8

Ecco un semplice algoritmo facendo uso del risolutore:

  1. generare un'istanza di puzzle casuale.

  2. Creare un set C di tutti gli indizi possibili relativi a questa istanza di puzzle. (Ci sono un numero limitato e in effetti un numero abbastanza piccolo di possibili indizi: per esempio se ci sono 5 case, ci sono 5 possibili indizi della forma "La persona A vive in casa B", 8 possibili indizi della forma "La persona A vive accanto a casa B", e così via.)

  3. Scegli una permutazione casuale c , c ..., cn degli indizi C.

  4. Set i = 1.

  5. Se i>n, abbiamo finito. Il set C di indizi è minimo.

  6. Let D = C - {ci}. Esegui il tuo risolutore sul set D di indizi e conta il numero di soluzioni possibili.

  7. Se c'è esattamente una soluzione, impostare C =D.

  8. Set i = i + 1 e tornare al punto 5.

(È possibile accelerare l'operazione rimuovendo gli indizi in lotti piuttosto che uno alla volta, ma rende l'algoritmo più complicato da descrivere)

+0

Grazie, Gareth! Questa è una soluzione eccezionale! – Weaver

+0

+1: questo mi sembra giusto. Anche se il passo 2 non è cosa da poco. Inoltre lascia la possibilità di indizi ridondanti e/o ovvi nel Set. Ad esempio "A vive a destra di B" e "B vive vicino ad A". O meno apparenti come "A lives next to B", "B vive vicino a C" "C non vive vicino ad A". – RBarryYoung

+2

Questo algoritmo inizia con * C * contenente * tutti i possibili * indizi, compresi molti sottoinsiemi ridondanti. Quindi rimuove gli indizi da questo set fino a quando non sarà più possibile rimuovere senza rendere ambiguo il puzzle. A questo punto non possono essere rimasti sottosistemi ridondanti. –

3

non sono del tutto sicuro in questa soluzione, ma questo è come vorrei affrontarlo:

Partendo da una soluzione casuale (ad esempio verde casa detiene polacco che fuma LM, casa rossa tiene irlandese che fuma chiodi di garofano, ecc) . puoi considerare quella soluzione come un grafico delle relazioni tra le affermazioni. dove ogni elemento (lucido, casa rossa, ecc.) è collegato a tutti gli altri elementi con un "sì" o un "no edge" (nel nostro caso lo smalto è collegato alla casa verde con un "sì" e al chiodi di garofano con un "no edge" (tra molti altri bordi, questo grafico iniziale è un grafico completo, direzionale)).

Ora, se si eliminano a caso i bordi, finché non si rimane con un grafico connesso minimo, si dovrebbe avere un grafico che rappresenta un puzzle risolvibile. traduce ogni margine yes in "foo is/does bar" e ogni no edge a "foo is not/does bar".

intuitivamente questo suona proprio per me. ma ancora, questo non è in alcun modo un modo formale o riconosciuto per farlo, e potrebbe essere completamente sbagliato.

+0

Questo è un approccio intelligente !, grazie per il suggerimento! Questa volta giocherò con alcuni algoritmi :) Segnalo come risposta se posso confermare che funziona! – Weaver

+0

grazie, se questo approccio fallisce puoi sempre usare l'approccio iterativo di Gareths. ma mi piacerebbe sapere se il mio modo funziona o no :) – Oren

+0

Che cos'è un "grafico connesso minimo" in questo approccio? E stai tenendo conto del fatto che ci sono quattro volte più connessioni NO delle connessioni YES? (cioè, le connessioni YES sono uniche in uno dei due gradi di libertà, ma NO non lo sono). – RBarryYoung

2

si può anche fare il contrario (che vi porterà un risolutore pure):.

  1. Genera S, un elenco di tutte le possibili soluzioni (ad es. tabelle).
  2. Generare un fatto casuale f (ad esempio: il norvegese ha un gatto).
  3. Set T = S
  4. filtro dal T tutte le soluzioni che violano f.
  5. Se | T | = 0 quindi vai a (il fatto è in contraddizione con uno precedente)
  6. Se | T | < | S | quindi impostare S = T e F.append (f) (il fatto non è già incarnata da fatti precedenti)
  7. IF | S | > 1 allora goto 2

Una volta fatto - F sarà l'elenco dei fatti che portano alla unico tavolo a sinistra in S.

Certo, si tratta di una forza bruta e probabilmente non funzionerà correttamente con una tabella 5X5 o superiore.

1

interessante notare che il "Einstein" Puzzle (citazioni destinati, tutto "intelligente" tende ad essere assegnato ad Einstein forse per avere più glamour), è legato alla algoritmo di generazione Sudoku (da una corretta traduzione di termini) e anche a Rubik (3x3x3) Risoluzione Algoritmo

Nel caso di Sudoku, gli indizi corrispondono ai già assegnati numeri sulla griglia e l'informazione mancante per svuotare slot

Nel caso di Rubik cubo (che trovo più interessante), gli indizi corrispondono alle simmetrie del cubo (ad esempio, il colore verde è accanto al colore rosso, come quello). I dati mancanti sono und da ri-allineamento (solving) il cubo

Si tratta di un abbozzo, grazie