Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione Samsung Galaxy Z Fold7: un grande salto generazionale
Recensione Samsung Galaxy Z Fold7: un grande salto generazionale
Abbiamo provato per molti giorni il nuovo Z Fold7 di Samsung, un prodotto davvero interessante e costruito nei minimi dettagli. Rispetto al predecessore, cambiano parecchie cose, facendo un salto generazionale importante. Sarà lui il pieghevole di riferimento? Ecco la nostra recensione completa.
The Edge of Fate è Destiny 2.5. E questo è un problema
The Edge of Fate è Destiny 2.5. E questo è un problema
Bungie riesce a costruire una delle campagne più coinvolgenti della serie e introduce cambiamenti profondi al sistema di gioco, tra nuove stat e tier dell’equipaggiamento. Ma con risorse limitate e scelte discutibili, il vero salto evolutivo resta solo un’occasione mancata
Ryzen Threadripper 9980X e 9970X alla prova: AMD Zen 5 al massimo livello
Ryzen Threadripper 9980X e 9970X alla prova: AMD Zen 5 al massimo livello
AMD ha aggiornato l'offerta di CPU HEDT con i Ryzen Threadripper 9000 basati su architettura Zen 5. In questo articolo vediamo come si comportano i modelli con 64 e 32 core 9980X e 9970X. Venduti allo stesso prezzo dei predecessori e compatibili con il medesimo socket, le nuove proposte si candidano a essere ottimi compagni per chi è in cerca di potenza dei calcolo e tante linee PCI Express per workstation grafiche e destinate all'AI.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 20-10-2008, 20:28   #1
Enrico Corsaro
Junior Member
 
L'Avatar di Enrico Corsaro
 
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.
Enrico Corsaro è offline   Rispondi citando il messaggio o parte di esso
Old 20-10-2008, 20:33   #2
yggdrasil
Senior Member
 
L'Avatar di yggdrasil
 
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
yggdrasil è offline   Rispondi citando il messaggio o parte di esso
Old 20-10-2008, 20:40   #3
Enrico Corsaro
Junior Member
 
L'Avatar di Enrico Corsaro
 
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
Enrico Corsaro è offline   Rispondi citando il messaggio o parte di esso
Old 20-10-2008, 20:52   #4
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
Quote:
Originariamente inviato da Enrico Corsaro Guarda i messaggi
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!
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 20-10-2008, 21:03   #5
Enrico Corsaro
Junior Member
 
L'Avatar di Enrico Corsaro
 
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
Enrico Corsaro è offline   Rispondi citando il messaggio o parte di esso
Old 20-10-2008, 21:04   #6
wlog
Bannato
 
Iscritto dal: Oct 2008
Messaggi: 558
Quote:
Originariamente inviato da Enrico Corsaro Guarda i messaggi
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!
Scordati un metodo veloce, il tuo problema è isomorfo all'ordinamento di un grafo (capacità di costruire una mappa biunivoca con un altro grafo). Esistono vari metodi, ma nessuno è veloce
wlog è offline   Rispondi citando il messaggio o parte di esso
Old 20-10-2008, 21:20   #7
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
Quote:
Originariamente inviato da Enrico Corsaro Guarda i messaggi
intendi dire di collocare le parole partendo dalla più lunga (o dalle più lunghe) e andando via via verso le più corte?
si', e se la piu' lunga e' unica sei messo abbastanza bene.
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 20-10-2008, 21:23   #8
wlog
Bannato
 
Iscritto dal: Oct 2008
Messaggi: 558
Quote:
Originariamente inviato da gugoXX Guarda i messaggi
si', e se la piu' lunga e' unica sei messo abbastanza bene.
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'
Il tuo algoritmo assomiglia molto a quello di Dijkstra:

http://en.wikipedia.org/wiki/Shortest_Path_First

Da qualche parte sul sito del mio dipartimento dell'UvA dovrebeb esserci qualcosa... mo cerco...
wlog è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 08:39   #9
cionci
Senior Member
 
L'Avatar di cionci
 
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.
cionci è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 08:53   #10
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
Quote:
Originariamente inviato da cionci Guarda i messaggi
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.
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 11:11   #11
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
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 ), si potrebbe provare ad inserire immediatamente le parole che sono forzate (le uniche di una certa lunghezza) e poi tentare una scelta per ognuna delle altre e si ripete l'inserimento, etc. In caso di conflitti si può fare un backtracking fino all'ultima scelta e tentare un'altra strada, fino a che non si trova una scelta soddisfacente.

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!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 11:17   #12
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quote:
Originariamente inviato da gugoXX Guarda i messaggi
si', e se la piu' lunga e' unica sei messo abbastanza bene.
[...]
Niente di speciale, ma occorre avere informazioni e strutture di appoggio in piu'
Come non detto, mi era sfuggito questo post!

Sono arrivato tardi...
ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 12:16   #13
Enrico Corsaro
Junior Member
 
L'Avatar di Enrico Corsaro
 
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.
Enrico Corsaro è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 12:50   #14
wlog
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.
wlog è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 12:50   #15
wingman87
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.
wingman87 è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 13:13   #16
Enrico Corsaro
Junior Member
 
L'Avatar di Enrico Corsaro
 
Iscritto dal: Dec 2007
Città: Catania
Messaggi: 15
Quote:
Originariamente inviato da wlog Guarda i messaggi
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.
Siamo d'accordo che l'ordine è il fattoriale, ma tra 1 fattore 1 e un fattore 0.2 per quanto non cambi l'ordine, c'è comunque una differenza sostanziale di velocità, quindi diciamo che se si riesce a trovare un modo per ridurre al minimo questo fattore, e ce ne dovrebbe essere uno solo possibile, allora è il caso che fa per me.
__________________
Einstein è un bravo ragazzo, peccato solo sia convinto che le onde elettromagnetiche siano costituite da particelle". M. Planck
Enrico Corsaro è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 13:16   #17
astorcas
Senior Member
 
L'Avatar di astorcas
 
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
astorcas è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 18:57   #18
wingman87
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);
		}
	}

}
Quella che la usa:
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");
		}
	}

}
So che non è molto elegante come codice ma una volta che mi sono reso conto della lentezza dell'algoritmo ho sospeso il progetto per tornarci qualora avessi avuto qualche idea per migliorarlo.
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.
Allegati
File Type: zip SchemiEDiz.zip (13.5 KB, 25 visite)
wingman87 è offline   Rispondi citando il messaggio o parte di esso
Old 21-10-2008, 20:34   #19
Enrico Corsaro
Junior Member
 
L'Avatar di Enrico Corsaro
 
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
Enrico Corsaro è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Recensione Samsung Galaxy Z Fold7: un grande salto generazionale Recensione Samsung Galaxy Z Fold7: un grande sal...
The Edge of Fate è Destiny 2.5. E questo è un problema The Edge of Fate è Destiny 2.5. E questo ...
Ryzen Threadripper 9980X e 9970X alla prova: AMD Zen 5 al massimo livello Ryzen Threadripper 9980X e 9970X alla prova: AMD...
Acer TravelMate P4 14: tanta sostanza per l'utente aziendale Acer TravelMate P4 14: tanta sostanza per l'uten...
Hisense M2 Pro: dove lo metti, sta. Mini proiettore laser 4K per il cinema ovunque Hisense M2 Pro: dove lo metti, sta. Mini proiett...
Il telescopio spaziale James Webb ha cat...
Amazon scatenata nel weekend: sconti sug...
Pulizia per 45 giorni senza pensieri: il...
Apple taglia il prezzo degli AirPods Pro...
Tutti i MacBook Air M4 2025 da 13 pollic...
Roborock QV 35A a 429€ o Dreame L40 Ultr...
SpaceX Starship: Ship 37 ha eseguito due...
Sharkoon punta sui case a basso costo, m...
La tua rete Wi-Fi fa pena? Questi FRITZ!...
Amazon, un weekend di fuoco per gli scon...
Ancora 3 smartwatch Amazfit in forte sco...
Sharkoon A60 RGB: dissipatore ad aria du...
HONOR 400 Pro a prezzo bomba su Amazon: ...
Offerte da non perdere: robot aspirapolv...
Apple Watch e Galaxy Watch ai minimi sto...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 04:12.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v