|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Junior Member
Iscritto dal: Dec 2007
Città: Catania
Messaggi: 15
|
Algoritmo per la risoluzione di un cruciverba
Salve a tutti, mi rivolgo in particolare a coloro i quali si dilettano nel ragionare su algoritmi che possono risolvere determinati problemi.
Vengo subito al mio caso. Ho un insieme di parole tutte note, e devo incastrarle in uno schema già pronto (quadrato o rettangolare che sia), fatto per queste parole, in cui trovo le caselle vuote e le caselle nere, come in un normale cruciverba. L'obiettivo è trovare un metodo di inserimento di queste parole nello schema, rispettando ovviamente gli incastri, in modo da realizzare il minor numero di tentativi e cioè ottimizzando il procedimento per la velocità. Si tratta ovviamente di fare dei tentativi perchè a differenza del normale cruciverba, non ho a disposizione i numeri sulle caselle con le relative definizioni. Ciò significa che almeno al primo inserimento tutte le parole hanno la stessa probabilità di essere collocate. Qualsiasi idea, detta così semplicemente a parole, sarebbe di grande aiuto per me e quindi vi ringrazio in anticipo ![]()
__________________
Einstein è un bravo ragazzo, peccato solo sia convinto che le onde elettromagnetiche siano costituite da particelle". M. Planck Ultima modifica di Enrico Corsaro : 20-10-2008 alle 20:30. |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Aug 2008
Messaggi: 808
|
tanto per iniziare:
risolvere un cruciverba come lo intendiamo noi umani è impossibile ![]() riempire un cruciverba con le parole soluzioni note a priori è un altro discorso il modo più semplice è usare il backtracking provi tutte le diverse combinazioni di inserimento di una parola nei posti di una determinata lunghezza incrociando i risultati con quelli di altre parole se ci sono solo 2 parole che si incrociano allora hai trovato il loro posto e così avanti per tutte |
![]() |
![]() |
![]() |
#3 |
Junior Member
Iscritto dal: Dec 2007
Città: Catania
Messaggi: 15
|
E di fatto mi riferisco proprio al filling di uno schema già pronto. Non cerco necessariamente il sistema più semplice ma a quello più veloce.
Grazie intanto per questa rapida risposta!
__________________
Einstein è un bravo ragazzo, peccato solo sia convinto che le onde elettromagnetiche siano costituite da particelle". M. Planck |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Un algoritmo greedy partendo dalla parola piu' lunga dovrebbe essere fattibile.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#5 |
Junior Member
Iscritto dal: Dec 2007
Città: Catania
Messaggi: 15
|
intendi dire di collocare le parole partendo dalla più lunga (o dalle più lunghe) e andando via via verso le più corte?
__________________
Einstein è un bravo ragazzo, peccato solo sia convinto che le onde elettromagnetiche siano costituite da particelle". M. Planck |
![]() |
![]() |
![]() |
#6 | |
Bannato
Iscritto dal: Oct 2008
Messaggi: 558
|
Quote:
![]() |
|
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
dividerei l'algoritmo in 3 passi 1) raggruppare le parole da collocare suddividendole per lunghezza 2) cercherei le celle di partenza delle parole nello schema, associando a ciascuna cella la lunghezza della parola richiesta. (2 nel caso di celle che sono partenza sia di una verticale che di una orizzontale) Quindi (memoria permettendo, ma direi che ce n'e' tanta), per ciascuna cella di partenza associerei una copia del vettore delle parole esattamente di quella lunghezza. 3) inizerei con un ciclo, sperando nella buona sorte: Ricerca di tutte le celle la cui lista ha una sola parola (nel caso della piu' lunga singola, almeno quela dovrebbe esserci) - Inserimento di tale parola nello schema, e cancellazione della parola appena messa dalla lista delle parole delle celle con partenza di pari lunghezza - A seguito della parola scritta, dalla lista di alcune altre e' possibile che si debbano depennare parole che non possono piu' stare in quella posizione. Le cancello Ricontinuo da 3 fino a che ho finito. Nel caso di dubbi, ovvero se non ci fosse nessuna lista con solo una parola possibile, allora si dovrebbe partire con il backtracking, che non e' mai troppo semplice. In pratica devi iniziare a piazzare le parole "sperando". Nel caso in cui ti trovi in un passo bloccato, allora torni indietro fino all'ultima scelta e ne compi un'altra. Niente di speciale, ma occorre avere informazioni e strutture di appoggio in piu'
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#8 | |
Bannato
Iscritto dal: Oct 2008
Messaggi: 558
|
Quote:
http://en.wikipedia.org/wiki/Shortest_Path_First Da qualche parte sul sito del mio dipartimento dell'UvA dovrebeb esserci qualcosa... mo cerco... |
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
L'analogia la vedo, ma non vedo come rappresentare il concetto di intersezione multipla delle parole con gli archi del grafo o con la lista dei nodi.
|
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Piu' che a Dijkstra assomiglia all'algoritmo che avevo scritto per il risolutore di Sudoku. E' praticamente identico.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Parlo da perfetto ignorante, ma mi viene in mente un approccio simile ad un risolutore di espressioni booleane che ho dovuto sviluppare per l'università: supponendo che il cruciverba abbia una sola configurazione finale possibile (il che è vero
![]() Certo, sarebbe abbastanza dispendioso, forse ci sono metodi migliori... ma potrebbe anche funzionare. ![]()
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Quote:
![]() Sono arrivato tardi... ![]() ciao ![]()
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
![]() |
![]() |
![]() |
#13 |
Junior Member
Iscritto dal: Dec 2007
Città: Catania
Messaggi: 15
|
Lo spreco di memoria non è un problema nel mio caso. Una struttura dati opportuna per velocizzare l'algoritmo si visiona in un secondo momento.
Avevo pensato già un pò a queste proposte fatte e tuttavia l'ordine computazionale rimarrebbe comunque molto elevato. Io avevo pensato di suddividere l'insieme di parole in gruppi per numero di caratteri e iniziare a collocare le parole partendo dal gruppo che ne contiene in minor numero (rispettando eventuali incastri), in modo da avere già in partenza la probabilità più alta per ogni parola di essere collocata nel posto giusto. Di seguito a procedere collocando le parole del secondo gruppo meno numeroso. Nel caso in cui un incastro non dovesse funzionare, si varia l'ordine delle parole inserite. Non penso comunque che l'ordine computazionale così venga ridotto, ma forse si velocizza di qualche fattore il tutto. Aggiungo che questo sistema dovrebbe essere diciamo il più vicino possibile ad un modo di ragionare "umano", cioè all'atto pratico al modo in cui un amante della settimana enigmistica risolverebbe questo problema con carta e penna. Sostanzialmente, non avendo praticità con questi giochini di logica, non so se c'è qualche trucchetto o comunque qualche procedimento sicuro e rapido in particolare per riempire un cruciverba con delle parole già date. Voi come procedereste?
__________________
Einstein è un bravo ragazzo, peccato solo sia convinto che le onde elettromagnetiche siano costituite da particelle". M. Planck Ultima modifica di Enrico Corsaro : 21-10-2008 alle 12:25. |
![]() |
![]() |
![]() |
#14 |
Bannato
Iscritto dal: Oct 2008
Messaggi: 558
|
ciao,
comunque tu scriva l'algoritmo, se l'algoritmo è in grado di risolvere ogni problema sottopostogli, esisterà sempre una particolare coppia di parole/cruciverba che richiederà n! passi, quindi mettiti il cuore in pace ![]() Backtracking con scelta locale greedy è il metodo migliore mi sa. |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2774
|
Ciao, io per diletto ho scritto un programma per risolvere cruciverba, solo che come hai immaginato tu il tempo di risoluzione, quando il numero di parole nel dizionario e' elevato, diventa spropositato. Ad ogni modo il mio algoritmo e' suddiviso in varie parti ma il ragionamento e' il seguente: partendo dalla cella in alto a sinistra cerco, muovendomi verso destra e quando raggiungo la fine della riga passo alla successiva, la prima cella da cui possa partire una parola (prima orizzontale, poi verticale) e provo a infilarne una (e la escludo dalle infilabili successivamente), quando non trovo una parola infilabile torno indietro di un passo, escludo la parola appena usata (solo per questo passo) e provo a infilarne un'altra.
Comunque se ti interessa quando torno a casa te lo posto (se mi ricordo ![]() EDIT: ripensandoci forse nel tuo caso tu hai un dizionario composto solo dalle parole contenute nello schema. Se e' cosi' il metodo di risoluzione che ho usato e' piuttosto veloce (se si tratta di un comune cruciverba tipo settimana enigmistica). Ultima modifica di wingman87 : 21-10-2008 alle 12:53. |
![]() |
![]() |
![]() |
#16 | |
Junior Member
Iscritto dal: Dec 2007
Città: Catania
Messaggi: 15
|
Quote:
__________________
Einstein è un bravo ragazzo, peccato solo sia convinto che le onde elettromagnetiche siano costituite da particelle". M. Planck |
|
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Jan 2005
Città: Siena
Messaggi: 1313
|
Non è esattamente quello che cerchi ma da una lettura qui potresti trovare un paio di spunti.
http://webcrow.dii.unisi.it/webpage/index.html |
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2774
|
Sono tornato a casa e ho ritrovato il codice, te lo posto, spero possa servirti.
La classe che realizza l'algoritmo: Codice:
import java.util.ArrayList; import java.util.Random; import java.util.Scanner; import java.io.*; public class Cruciverba{ private class Coordinata{ int riga; //Si parte da zero!!! (riga zero -> prima riga) int colonna; //Si parte da zero!!! Coordinata(int riga,int colonna){ //Un comodo costruttore per creare velocemente una coordinata this.riga=riga; this.colonna=colonna; } private int compareTo(Coordinata c){ if(riga<c.riga) return -1; if(riga>c.riga) return +1; if(colonna<c.colonna) return -1; if(colonna>c.colonna) return +1; return 0; } } private class Orientamento{ boolean verticale; //Se verticale è true -> verticale, altrimenti orizzontale Orientamento(boolean verticale){ //Un comodo costruttore per creare velocemente un orientamento this.verticale=verticale; } } private char schema[][]; //[RIGHE][COLONNE] Si parte da zero!!! (riga zero -> prima riga) //'#' per i quadrati neri, '.' per gli spazi vuoti private String dizionario[]; //Dizionario completo private String definizioniDizionario[];//Definizioni del dizionario, sono nello stesso ordine del dizionario private String miniDizionari[][]; //[NUMERO_DI_LETTERE_DELLA_PAROLA][PAROLE] private String daDisimpegnare[]; //Parole impegnate da writeWord(), vengono disimpegnate da writeWordNoCheck() e alla fine del riempimento (fill()) private int nPunti=0; //TEST private boolean showLoading=false; //TEST public void setShowLoading(boolean on){ showLoading=on; } public Cruciverba(String pathDizionario)throws IOException,FileNotFoundException{ loadDizionario(pathDizionario); loadMiniDizionari(); } //Funzione che carica una matrice (cruciverba) di caratteri dal file ('#' per i quadrati neri, '.' per gli spazi vuoti) //Si assume che path sia un file di cruciverba valido. public void loadCruciverba(String path)throws IOException,FileNotFoundException{ FileReader fR=new FileReader(path); Scanner file=new Scanner(fR); schema=new char[0][]; int numeroRiga=0; while(file.hasNextLine()){ String rigaLetta=file.nextLine().toLowerCase(); char[][] tempSchema=new char[numeroRiga+1][]; for(int i=0;i<schema.length;i++) tempSchema[i]=schema[i]; tempSchema[numeroRiga]=rigaLetta.toCharArray(); schema=tempSchema; numeroRiga++; } fR.close(); } //Funzione che salva una matrice (cruciverba) di caratteri dal file ('#' per i quadrati neri, '.' per gli spazi vuoti) public void saveCruciverba(String path)throws IOException,FileNotFoundException{ FileWriter fW=new FileWriter(path,false); PrintWriter file=new PrintWriter(fW); for(char[] x:schema){ file.println(new String(x).toUpperCase()); } fW.close(); } //Funzione che riempie lo schema, restituisce true se ci riesce, false altrimenti. public boolean fill(){ //INIZIO TEST if(showLoading){ nPunti++; System.out.print("\r"+genString('.',nPunti)); } //FINE TEST Orientamento orient=new Orientamento(true); Coordinata c=new Coordinata(0,0); try{ c=nextFreeSpace(orient); //Cerco il prossimo spazio in cui inserire una parola }catch(NoMoreSpaceException e){ //Non ci sono altre parole da inserire: HO FINITO! if(daDisimpegnare!=null) //Disimpegno tutte le parole che avevo impegnato con writeWord() for(int i=0;i<daDisimpegnare.length;i++) replace(miniDizionari[daDisimpegnare[i].length()],genString('#',daDisimpegnare[i].length()),daDisimpegnare[i]); daDisimpegnare=null; //INIZIO TEST nPunti=0; System.out.print("\r"); //FINE TEST return true; } String regExpr=intersectingWord(c,orient); //Leggo la regExpr dello spazio in cui devo inserire una nuova parola int lenParola=regExpr.length(); String[] possibiliParole=matchingWords(miniDizionari[lenParola],regExpr); //Cerco le parole che vi si incastrano shuffleWords(possibiliParole); //Le mescolo (serve a non dare sempre la stessa soluzione) for(int i=0;i<possibiliParole.length;i++){ String old=possibiliParole[i]; replace(miniDizionari[lenParola],old,genString('#',lenParola)); //Contrassegno la parola che sto per usare come impegnata if(!possibiliParole[i].substring(0,1).equals("#") && writeWord(possibiliParole[i],c,orient,regExpr)){ //Se questa parola non è una parola già usata e si incastra if(fill()){ //Provo a riempire tutto lo schema con quella parola incastrata replace(miniDizionari[lenParola],genString('#',lenParola),old); //Se ci riesco disimpegno la parola e torno true return true; }else //Se non ci sono riuscito significa che nonostante la parola si incastrasse non era quella giusta writeWordNoCheck(regExpr,c,orient); //Quindi riscrivo sullo schema quello che c'era originariamente } replace(miniDizionari[lenParola],genString('#',lenParola),old); //Disimpegno la parola } //INIZIO TEST if(showLoading){ nPunti--; System.out.print("\r"+genString('.',nPunti)+" "); } //FINE TEST return false; //Torno false se non sono riuscito a mettere nessuna parola } //Funzione che carica il dizionario completo e le definizioni //Questa funzione non gestisce le eccezioni dovute a problemi di I/O ma le rilancia al chiamante private void loadDizionario(String path)throws IOException,FileNotFoundException{ FileReader fR=new FileReader(path); Scanner file=new Scanner(fR); ArrayList<String> parole=new ArrayList<String>(); ArrayList<String> definizioni=new ArrayList<String>(); while(file.hasNext()){ file.useDelimiter(" "); parole.add(file.next().trim()); file.useDelimiter("\\s?\n"); definizioni.add(file.next().trim()); } fR.close(); dizionario=(String[])parole.toArray(new String[0]); definizioniDizionario=(String[])definizioni.toArray(new String[0]); } //Funzione che carica i mini-dizionari dal dizionario completo. (Si assume che il dizionario completo sia già stato caricato) //Per iniziare poniamo che la lunghezza massima delle parole sia 30, quindi bisogna allocare lo spazio per 30 array private void loadMiniDizionari(){ ArrayList<ArrayList<String>> miniDiz=new ArrayList<ArrayList<String>>(); for(int i=0;i<30;i++) miniDiz.add(new ArrayList<String>()); for(int i=0;i<dizionario.length;i++) miniDiz.get(dizionario[i].length()).add(dizionario[i]); miniDizionari=new String[30][]; for(int i=0;i<30;i++) miniDizionari[i]=(String[])miniDiz.get(i).toArray(new String[0]); } //Funzione che aggiunge all'array daDisimpegnare[] parola private void addDaDisimpegnare(String parola){ if(daDisimpegnare==null) daDisimpegnare=new String[0]; String[] nuovoVett=new String[daDisimpegnare.length+1]; for(int i=0;i<daDisimpegnare.length;i++) nuovoVett[i]=daDisimpegnare[i]; nuovoVett[nuovoVett.length-1]=parola; daDisimpegnare=nuovoVett; } //Funzione che toglie dall'array daDisimpegnare[] parola. Torna true se ha tolto qualcosa, false altrimenti private boolean subDaDisimpegnare(String parola){ ArrayList<String> nuovoVett=new ArrayList<String>(); boolean trovato=false; if(daDisimpegnare==null) daDisimpegnare=new String[0]; for(int i=0;i<daDisimpegnare.length;i++){ if(trovato) nuovoVett.add(daDisimpegnare[i]); else if(!daDisimpegnare[i].equals(parola)) nuovoVett.add(daDisimpegnare[i]); else trovato=true; } int oldDim=daDisimpegnare.length; daDisimpegnare=(String[])nuovoVett.toArray(new String[0]); return(oldDim!=daDisimpegnare.length); } //Genera una stringa di n caratteri (n è ripetizioni e carattere è il char che viene ripetuto) private static String genString(char carattere,int ripetizioni){ String ret=""; if(ripetizioni<0) return ret; for(int i=0;i<ripetizioni;i++) ret+=carattere; return ret; } //Funzione che sostituisce la prima occorrenza della key nel vettore con replacement private void replace(String[] vett, String key, String replacement){ for(int i=0;i<vett.length;i++){ if(vett[i].equals(key)){ vett[i]=replacement; break; } } } //Funzione che restituisce un array delle parole che matchano un'expr. regolare. Non restituisce due volte la stessa parola private static String[] matchingWords(String[] dizionario, String regExpr){ ArrayList<String> ret=new ArrayList<String>(); for(int i=0;i<dizionario.length;i++) if(dizionario[i].matches(regExpr)) if(ret.indexOf(dizionario[i])<0) ret.add(dizionario[i]); return (String[])ret.toArray(new String[0]); } //Funzione che mescola un array di stringhe private static void shuffleWords(String[] dizionario){ Random dice=new Random(); for(int i=0;i<dizionario.length;i++){ int index=dice.nextInt(dizionario.length); String temp=dizionario[index]; dizionario[index]=dizionario[0]; dizionario[0]=temp; } } //Funzione che restituisce la parola (reg. expr.) che passa x un punto (in verticale o in orizzontale) data una coordinata //Si assume che coord sia una cordinata interna allo schema //Lancia NonIntersectingWordsException se non c'è una parola che interseca la coordinata (coord è una cella nera o la parola // è di una sola lettera private String intersectingWord(Coordinata coord, Orientamento orient){ if(getSchemaChar(coord)=='#') throw new NonIntersectingWordsException("Cella nera"); String ret=""+getSchemaChar(coord); Coordinata it=new Coordinata(coord.riga,coord.colonna); //it sta per iterator if(orient.verticale){ //Se è in verticale concateno i caratteri in colonna spostandomi di riga it.riga--; while(it.riga>=0 && getSchemaChar(it)!='#'){ ret=getSchemaChar(it)+ret; it.riga--; } it.riga=coord.riga+1; while(it.riga<schema.length && getSchemaChar(it)!='#'){ ret=ret+getSchemaChar(it); it.riga++; } }else{ //Se è in orizzontale concateno i caratteri in riga spostandomi di colonna it.colonna--; while(it.colonna>=0 && getSchemaChar(it)!='#'){ ret=getSchemaChar(it)+ret; it.colonna--; } it.colonna=coord.colonna+1; while(it.colonna<schema[coord.riga].length && getSchemaChar(it)!='#'){ ret=ret+getSchemaChar(it); it.colonna++; } } if(ret.length()==1) throw new NonIntersectingWordsException("Una sola lettera"); return ret; } private char getSchemaChar(Coordinata coord){ return schema[coord.riga][coord.colonna]; } //Funzione che restituisce un array di stringhe in formato reg. expr. con le parole che intersecano un'altra (x coordinate) //Fa uso di intersectingWord() ma bisogna fare attenzione a non uscire dallo schema. //Gestisce il NonIntersectingWordsException di intersectingWord. //Si assume che coord e orient siano una coordinata valida (è la prima cella di una parola) //Lancia NonIntersectingWordsException SOLO se al termine nessuna parola è stata trovata private String[] intersectingWords(Coordinata coord, Orientamento orient){ //coord è l'inizio della parola, orient il suo orientamento Orientamento orientToUse=new Orientamento(!orient.verticale); ArrayList<String> ret=new ArrayList<String>(); String parola=intersectingWord(coord,orient); if(orient.verticale) for(int i=0;i<parola.length();i++){ try{ String temp=intersectingWord(new Coordinata(coord.riga+i,coord.colonna),orientToUse); ret.add(temp); }catch(NonIntersectingWordsException e){ } } else for(int i=0;i<parola.length();i++){ try{ String temp=intersectingWord(new Coordinata(coord.riga,coord.colonna+i),orientToUse); ret.add(temp); }catch(NonIntersectingWordsException e){ } } if(ret.size()==0) throw new NonIntersectingWordsException("Nessuna parola intersecante trovata"); return (String[])ret.toArray(new String[0]); } //Funzione che scrive una parola nella posizione indicata. Restituisce true se la parola è stata inserita con successo, false altrimenti //Deve controllare che le parole che intersecano la parola appena inserita siano ancora valide ossia ci siano delle matchingWords //rispetto alle loro espressioni regolari, se sì torna true, altrimenti cancella la parola appena inserita con writeWordNoCheck //usando il valore di old e torna false. Si assume che coord e orient siano valori validi per la lunghezza di parola e old. //Se inserendo le lettere si completa qualche parola intersecante bisogna impegnarla nel minidizionario corrispondente. private boolean writeWord(String parola, Coordinata coord, Orientamento orient, String old){ Orientamento orientToUse=new Orientamento(!orient.verticale); if(orient.verticale){ for(int i=0;i<parola.length();i++){ if(parola.charAt(i)!=old.charAt(i)){ //Non riscrivo i caratteri uguali schema[coord.riga+i][coord.colonna]=parola.charAt(i); try{ String parolaIntersecante=intersectingWord(new Coordinata(coord.riga+i,coord.colonna),orientToUse); String possibiliParole[]=matchingWords(miniDizionari[parolaIntersecante.length()],parolaIntersecante); boolean ok=false; for(int j=0;j<possibiliParole.length;j++){ if(possibiliParole[j].indexOf("#")<0) ok=true; } if(ok){ if(parolaIntersecante.indexOf(".")<0){ //Se ho completato una parola replace(miniDizionari[parolaIntersecante.length()],parolaIntersecante,genString('#',parolaIntersecante.length())); addDaDisimpegnare(parolaIntersecante); } }else{ writeWordNoCheck(old,coord,orient); return false; } }catch(NonIntersectingWordsException e){ } } } }else{ for(int i=0;i<parola.length();i++){ if(parola.charAt(i)!=old.charAt(i)){ //Non riscrivo i caratteri uguali schema[coord.riga][coord.colonna+i]=parola.charAt(i); try{ String parolaIntersecante=intersectingWord(new Coordinata(coord.riga,coord.colonna+i),orientToUse); String possibiliParole[]=matchingWords(miniDizionari[parolaIntersecante.length()],parolaIntersecante); boolean ok=false; for(int j=0;j<possibiliParole.length;j++){ if(possibiliParole[j].indexOf("#")<0) ok=true; } if(ok){ if(parolaIntersecante.indexOf(".")<0){ //Se ho completato una parola replace(miniDizionari[parolaIntersecante.length()],parolaIntersecante,genString('#',parolaIntersecante.length())); addDaDisimpegnare(parolaIntersecante); } }else{ writeWordNoCheck(old,coord,orient); return false; } }catch(NonIntersectingWordsException e){ } } } } return true; } //Funzione che scrive una parola nella posizione indicata senza controllare la sua correttezza. (Serve a cancellare parole già inserite) //Si assume che coord e orient siano valori validi per la lunghezza di parola. //Se inserisce dei '.' dove prima c'era una parola completa deve disimpegnare quella parola dal minidizionario corrispondente. private void writeWordNoCheck(String parola, Coordinata coord, Orientamento orient){ Orientamento orientToUse=new Orientamento(!orient.verticale); if(orient.verticale){ for(int i=0;i<parola.length();i++){ if(parola.charAt(i)=='.'){ try{ String temp=intersectingWord(new Coordinata(coord.riga+i,coord.colonna),orientToUse); if(temp.indexOf(".")<0){ //Se sto per cancellare una parola completa if(subDaDisimpegnare(temp)) //Se era una parola impegnata replace(miniDizionari[temp.length()],genString('#',temp.length()),temp); //Prima la disimpegno } }catch(NonIntersectingWordsException e){ } } schema[coord.riga+i][coord.colonna]=parola.charAt(i); } }else{ for(int i=0;i<parola.length();i++){ if(parola.charAt(i)=='.'){ try{ String temp=intersectingWord(new Coordinata(coord.riga,coord.colonna+i),orientToUse); if(temp.indexOf(".")<0){ //Se sto per cancellare una parola completa if(subDaDisimpegnare(temp)) //Se era una parola impegnata replace(miniDizionari[temp.length()],genString('#',temp.length()),temp); //Prima la disimpegno } }catch(NonIntersectingWordsException e){ } } schema[coord.riga][coord.colonna+i]=parola.charAt(i); } } } //Funzione che trova il primo spazio libero (prima orizzontale, poi verticale) dove inserire la prossima parola (quindi uno spazio di almeno 2 lettere) //Lancia NoMoreSpaceException se non ci sono più spazi liberi //Fa uso della funzione seguente (nextOrientedFreeSpace()) //nextFreeSpace() deve essere ottimizzata in modo da cercare il posto più conveniente dove mettere la prossima parola in modo da //incrementare il numero di intersezioni con altre parole e quindi permettere di capire più in fretta se le parole che si stanno //inserendo non sono adatte allo schema //A questo scopo la prima versione di nextFreeSpace deve ricercare il primo spazio libero verticale e quello orizzontale e restituire //quello più "vicino all'origine" (Riga zero, Colonna zero). In caso di parità ritornare lo spazio orizzontale. Inoltre le righe hanno //la priorità sulle colonne cioè la posizione [0][15] è più "vicina all'origine" della posizione [1][0] private Coordinata nextFreeSpace(Orientamento orient){ //orient è un valore di ritorno aggiuntivo che dice in che verso è lo spazio libero Coordinata cOriz=null; Coordinata cVert=null; try{ cOriz=nextOrientedFreeSpace(new Orientamento(false)); }catch(NoMoreSpaceException e){ } try{ cVert=nextOrientedFreeSpace(new Orientamento(true)); }catch(NoMoreSpaceException e){ } if(cOriz==null && cVert==null) throw new NoMoreSpaceException("Sono finiti gli spazi vuoti!"); if(cOriz==null || cVert!=null && cVert.compareTo(cOriz)<0){ orient.verticale=true; return cVert; } orient.verticale=false; return cOriz; } //Lancia NoMoreSpaceException se non ci sono più spazi liberi nell'orientamento indicato private Coordinata nextOrientedFreeSpace(Orientamento orient){ //orient indica in che verso va ricercato lo spazio libero for(int r=0;r<schema.length;r++){ for(int c=0;c<schema[r].length;c++){ try{ String temp=intersectingWord(new Coordinata(r,c),orient); if(temp.indexOf(".")>=0) return new Coordinata(r,c); }catch(NonIntersectingWordsException e){ } } } throw new NoMoreSpaceException("Finiti spazi vuoti (orient.verticale="+orient.verticale+")"); } //ECCEZIONI private class NonIntersectingWordsException extends RuntimeException{ NonIntersectingWordsException(String msg){ super(msg); } } private class NoMoreSpaceException extends RuntimeException{ NoMoreSpaceException(String msg){ super(msg); } } } Codice:
import java.util.Scanner; class ProgettoCruciverba{ public static void main(String[] args){ Cruciverba c=null; String schema="Schemi\\"; String pathSave="Soluzioni\\"; try{ c=new Cruciverba("Definizioni.txt"); }catch(Exception e){ System.out.println("Errore nell'apertura di Definizioni.txt"); System.out.println(e.getMessage()); return; } System.out.println("Dizionario Caricato"); Scanner tastiera=new Scanner(System.in); System.out.println(); System.out.println("Si desidera mostrare il progresso della risoluzione(piu' lento)? (yes/no)"); if(tastiera.nextLine().equalsIgnoreCase("yes")){ c.setShowLoading(true); System.out.println(); System.out.println("ATTIVATO!"); }else{ System.out.println(); System.out.println("NON ATTIVATO!"); } while(true){ System.out.println(); System.out.println("Inserire il nome dello schema da risolvere (senza .txt):"); String inp1=tastiera.nextLine(); System.out.println(); try{ c.loadCruciverba(schema+inp1+".txt"); }catch(Exception e){ System.out.println("Errore nell'apertura di "+schema+inp1+".txt"); continue; } if(c.fill()){ System.out.println("Soluzione trovata. Inserire il nome del file su cui salvare la soluzione (senza .txt):"); String inp2=tastiera.nextLine(); try{ c.saveCruciverba(pathSave+inp2+".txt"); }catch(Exception e){ System.out.println(); System.out.println("Errore nel salvataggio di "+pathSave+inp2+".txt"); } } else System.out.println("Nessuna soluzione trovata per questo schema"); } } } Ah, ti do anche degli schemi con cui l'ho testato e le soluzioni e il dizionario che mi sono scritto copiando le definizioni di un bel po' di cruciverba. |
![]() |
![]() |
![]() |
#19 |
Junior Member
Iscritto dal: Dec 2007
Città: Catania
Messaggi: 15
|
Vi ringrazio per le risposte...
grazie wingman anche per il codice, tuttavia non è ciò che al momento mi interessa, oltre a non essere nel linguaggio in cui devo lavorare, ma vedrò di darci comunque un occhio nel caso serva ![]()
__________________
Einstein è un bravo ragazzo, peccato solo sia convinto che le onde elettromagnetiche siano costituite da particelle". M. Planck |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 04:12.