2010-12-27 4 views
9

Recentemente ho scritto un programma di Ruby per determinare soluzioni a un puzzle "Scramble Squares" tegola:Come posso utilizzare TDD per risolvere un puzzle con una risposta sconosciuta?

ho usato TDD per implementare la maggior parte di esso, portando a test che si presentava così:

it "has top, bottom, left, right" do 
    c = Cards.new 
    card = c.cards[0] 
    card.top.should == :CT 
    card.bottom.should == :WB 
    card.left.should == :MT 
    card.right.should == :BT 
end 

Questo ha funzionato bene per i metodi "helper" di livello inferiore: identificare i "lati" di una tessera, determinare se una tessera può essere posizionata correttamente nella griglia, ecc.

Ma io ha incontrato un problema durante la codifica dell'algoritmo vero e proprio per risolvere il puzzle. Dal momento che non conoscevo le possibili soluzioni valide al problema, non sapevo come scrivere un test prima.

ho finito per scrivere una bella brutta, non testato, algoritmo per risolverlo:

def play_game 
    working_states = [] 
    after_1 = step_1 
    i = 0 
    after_1.each do |state_1| 
     step_2(state_1).each do |state_2| 
     step_3(state_2).each do |state_3| 
      step_4(state_3).each do |state_4| 
      step_5(state_4).each do |state_5| 
       step_6(state_5).each do |state_6| 
       step_7(state_6).each do |state_7| 
        step_8(state_7).each do |state_8| 
        step_9(state_8).each do |state_9| 
         working_states << state_9[0] 
        end 
        end 
       end 
       end 
      end 
      end 
     end 
     end 
    end 

Quindi la mia domanda è: come si usa TDD scrivere un metodo quando non si conosce già la uscite valide?

Se siete interessati, il codice è su GitHub:

risposta

8

Questa non è una risposta diretta, ma questo mi ricorda the comparison tra i risolutori di Sudoku scritti da Peter Norvig e Ron Jeffries. L'approccio di Ron Jeffries usava il classico TDD, ma non ha mai avuto davvero una buona soluzione. Norvig, d'altra parte, era in grado di risolverlo in modo molto elegante senza TDD.

La domanda fondamentale è: può un algoritmo emergere utilizzando TDD?

+0

penserei sarebbe necessario conoscere il un lgoritmo (o almeno parti di esso) prima di poter scrivere test per questo. +1 per il collegamento, molto interessante. –

+1

http://pindancing.blogspot.com/2009/09/sudoku-in-coders-at-work.html collegato dal tuo collegamento sembra discutere di una sorta di "risposta" al punto e.p. –

+0

Grazie per i link a tutti. Sembra che in questo ** particolare ** spazio problema (che genera un algoritmo per risolvere un enigma), l'approccio di "utilizzare i test per capire il progetto mentre si va" tende a portare a soluzioni maldestre o inefficienti. Mi ricorda [queste critiche al TDD] (http://www.dalkescientific.com/writings/diary/archive/2009/12/29/problems_with_tdd.html). Non sono sicuro che tu possa fare un giudizio più ampio sul processo stesso. Per lo meno, ero * molto * felice di aver messo a punto (e testato) i metodi di livello inferiore disponibili prima di immergermi nel risolvere il problema reale. – matthewsteele

1

Dal puzzle website:

L'oggetto di Scramble Squares® pu Il gioco dell'ugello consiste nell'ordinare i nove quadrati quadrati colorati in un quadrato da 12 "x 12" in modo che la grafica realistica dei pezzi sui lati corrisponda perfettamente per formare un progetto completato in ogni direzione.

Quindi una delle prime cose che cercherò è una verifica del fatto che due tessere, in una particolare disposizione, si combinino l'una con l'altra. Questo è per quanto riguarda la tua domanda di validità. Senza quel metodo che funziona correttamente, non puoi valutare se il puzzle è stato risolto. Sembra un buon punto di partenza, un bel pezzo da mordere verso la soluzione completa. Non è ancora un algoritmo, ovviamente.

Una volta che match() funziona, dove andiamo da qui? Bene, una soluzione ovvia è la forza bruta: dall'insieme di tutte le possibili disposizioni delle tessere all'interno della griglia, respingete quelle in cui due tessere adiacenti non corrispondono. È un algoritmo, di questo genere, ed è abbastanza sicuro che funzioni (sebbene in molti enigmi la morte termica dell'universo avvenga prima di una soluzione).

Che ne dici di raccogliere il set di tutte le coppie di tessere che corrispondono ad un dato bordo (LTRB)? Potresti arrivare da lì a una soluzione, più veloce? Certamente puoi testarlo (e testarlo) abbastanza facilmente.

Le prove improbabili per danno a un algoritmo, ma possono aiutare a pensare agli algoritmi e, naturalmente, possono rendere più facile la convalida del proprio approccio.

0

so se questo "risponde" la questione sia

analisi del "puzzle"

9 piastrelle
ognuno ha 4 lati
ogni tessera ha una mezza modello/immagine

BRUTE FORCE APPROACH

per risolvere questo problema è necessario generare 9! combinazioni (9 piastrelle X 8 tessere X 7 piastrelle ...)

limitato dal numero di lati corrispondenti alla piastrella corrente (s) già in atto

CONSIDERATO APPROCCIO

Q Quanti lati sono diverso? IE quante partite ci sono?

quindi 9 X 4 = 36 lati/2 (in quanto ogni lato "must" match almeno 1 lato)
altrimenti è un puzzle uncompleteable
NOTA: almeno 12 deve corrispondere "correttamente" per un 3 X 3 Puzzle

etichetta ogni lato corrispondenza di una piastrella utilizzando una lettera unica

poi costruire una tabella che tiene ogni tessera
dovrai 4 voci nella tabella per ogni tessera
4 lati (angoli) quindi 4 combinazioni
se si ordina la tabella a fianco e indice nella tabella

lato, tile_number
ABCD tile_1
BCDA tile_1
CDAB tile_1
DABC tile_1

utilizzando la tabella dovrebbe accelerare le cose
poiché è necessario solo abbinare 1 o 2 lati al massimo
questo limita la quantità di piastrella NON PRODUCTIVA che deve fare

a seconda del design del modello/immagine
ci sono 3 combinazioni (orientamenti) dal momento che ogni piastrella può essere posizionato con 3 orientamenti
- gli stessi (più copie della stessa piastrella)
- riflessione
- rotazione

Dio ci aiuti se decidono di rendere la vita molto difficile
mettendo simili modelli/immagini sul lato opposto che ha anche bisogno di abbinare
o anche fare le piastrelle a dadini e la congruenza 6 lati !!!

Utilizzando TDD,
si può scrivere test e poi codice per risolvere ogni piccola parte del problema,
come descritto sopra e scrivere più test e codice per risolvere l'intero problema

NO non è facile, avete bisogno di sedersi e scrivere i test e il codice di praticare

NOTA: si tratta di una variante del problema mappa colorazione