|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#21 | |
|
Member
Iscritto dal: Feb 2010
Messaggi: 31
|
Quote:
Sono iscritto da 5 mesi (è puoi controllarlo dalla data di iscrizione)e non ho mai fatto una sola domanda , questo dovrebbe dimostrarti che quello che hai scritto è una grandissima caxxaxa! Mi sono iscritto perchè mi piaceva il sito , e leggevo anche il forum, ora ho dei problemi ed ho chiesto un aiuto ,non riesco a capire cosa ci sia di sbagliato.
__________________
-.-'' |
|
|
|
|
|
|
#22 | |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Quote:
Puoi cioè esprimere una soluzione di carattere generale e fare in modo che il programma "ti segua". L'esercizio ha un limite che sembra proibire l'uso delle liste: non puoi caricare in memoria tutti numeri e poi ordinarli, devi leggere e scrivere tout-court. Dai libero sfogo alla tua fantasia. Hai N file che contengono ciascuno una sequenza di numeri in ordine crescente. Devi scrivere in un file di destinazione l'unione di quelle sequenza, sempre in ordine crescente. Sappiamo che se le sequenze nei file sono ordinate, trattando i file come se fossero delle pile di numeri, otteniamo il risultato voluto estraendo il minore tra i valori in testa a ciascun file e trasferendolo nella destinazione. Ergo, in termini generali, la soluzione è piuttosto semplice: Codice:
finchè almeno uno dei file sorgente ha un valore in testa
rimuovi dalla sua sorgente il minore tra quei quei valori e mettilo nella destinazione
Partiamo dalla soluzione: Codice:
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
SorgenteEntità fileUno = new SorgenteEntità(args[0]);
SorgenteEntità fileDue = new SorgenteEntità(args[1]);
DestinazioneEntità fileTre = new DestinazioneEntità(args[2]);
SequenzaUnioneSorgenti sequenzaUnioneSorgenti = new SequenzaUnioneSorgenti(fileUno, fileDue);
while(sequenzaUnioneSorgenti.hasNext()) {
fileTre.enqueue(sequenzaUnioneSorgenti.next());
}
}
}
Dov'è il trucco? Il trucco sta nel far si che il linguaggio ci segua cioè nell'andare a creare quelle definizioni particolareggiate che permettano a quelle sette righe di fare ciò che sembra che facciano. Partiamo dalle sorgenti. Codice:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class SorgenteEntità {
private final Scanner scanner;
private EntitàNumerica current;
public SorgenteEntità(String filePath) throws IOException {
scanner = new Scanner(new File(filePath)).useDelimiter("\\D+");
current = new EntitàNumerica(this, scanner.nextInt());
}
public void remove(EntitàNumerica e) {
if(e != current) {
throw new IllegalStateException(e + " != " + current);
}
if(hasNext() && scanner.hasNextInt()) {
current = new EntitàNumerica(this, scanner.nextInt());
} else {
current = null;
}
}
public boolean hasNext() {
return current != null;
}
public EntitàNumerica peekMinimum(EntitàNumerica entità) {
if(current == null) {
return entità;
} else if(entità == null) {
return current;
} else {
return current.getValore().doubleValue() < entità.getValore().doubleValue() ?
current : entità;
}
}
}
Il metodo remove estrae la testa e passa all'elemento successivo se la testa è l'elemento che si vuole rimuovere, altrimenti rilascia un'eccezione. Tutta 'sta roba è lì perchè è il minimo necessario e sufficiente affinchè il nostro meccanismo possa funzionare: se ne avessimo ideato un altro avremmo scritto cose affatto diverse. L'entità numerica è ciò di cui parlavamo prima: un numero che conosce la propria sorgente ed è in grado di rimuoversi da essa. Codice:
public class EntitàNumerica {
private final Number VALORE;
private final SorgenteEntità SORGENTE;
public EntitàNumerica(SorgenteEntità sorgente, Number valore) {
VALORE = valore;
SORGENTE = sorgente;
}
public Number getValore() {
return VALORE;
}
public EntitàNumerica rimuoviDaSorgente() {
SORGENTE.remove(this);
return this;
}
}
DestinazioneEntità è anche più stringata: Codice:
import java.io.IOException;
import java.io.PrintStream;
public class DestinazioneEntità {
private final PrintStream OUTPUT;
private boolean first = true;
public DestinazioneEntità(String file) throws IOException {
OUTPUT = new PrintStream(file);
}
public void enqueue(EntitàNumerica next) {
if(first) {
first = false;
OUTPUT.print(next.getValore());
} else {
OUTPUT.print(",");
OUTPUT.print(next.getValore());
}
OUTPUT.flush();
}
}
Il ghirigoro dell'if-else serve per produrre dei numeri separati da virgola, evitando di mettere virgole di troppo. L'ultimo pezzo del puzzle è SequenzaUnioneSorgenti. Dal Main vediamo che ha tre caratteristiche: 1. richiede una successione di sorgenti per l'inizializzazione 2. ha un metodo hasNext() che presumibilmente restituisce true se l'unione ha un valore ulteriore, false altrimenti 3. ha un metodo next() che restituisce il valore successivo della sequenza. Anche qui si tratta di una classe di poche righe: Codice:
public class SequenzaUnioneSorgenti {
private final SorgenteEntità[] SORGENTI;
public SequenzaUnioneSorgenti(SorgenteEntità... sorgenti) {
SORGENTI = sorgenti;
}
public boolean hasNext() {
for (int i = 0; i < SORGENTI.length; i++) {
if (SORGENTI[i].hasNext()) {
return true;
}
}
return false;
}
public EntitàNumerica next() {
EntitàNumerica entità = null;
for (int i = 0; i < SORGENTI.length; i++) {
entità = SORGENTI[i].peekMinimum(entità);
}
return entità.rimuoviDaSorgente();
}
}
next() opera in modo simile: deve restituire il minore tra i valori in testa ad ogni sorgente-pila. Usa un valore cache, inizialmente vuoto. Per ogni pila, la cache diventa il minimo tra la cache e il valore in testa alla pila attualmente esaminata. AL termine del ciclo è giocoforza che (se hasNext restituisce true) entità sia il minimo tra i valori in testa alle pile. Rimuove quindi quel valore dalla sua sorgente (l'entità sa chi sia) e lo restituisce. Il formato dei file in input è specificato da SorgenteEntità. new Scanner(new File(filePath)).useDelimiter("\\D+"); questo significa che lo scanner usa come delimitatore una qualsiasi successione di caratteri che non siano cifre. In soldoni, piglia solo numeri interi. E questa è una soluzione. Come vedi è fatta di pochi piccoli pezzi dal significato peraltro indecifrabile a meno che non si conosca l'idea da cui si è partiti: con quell'idea le cose dovrebbeo assumere il loro senso. L'ho scritta per darti un'idea del modus operandi: non limitarti a ciò che sai del linguaggio o a ciò che il linguaggio offre attraverso le sue librerie. Pensa a come risolveresti tu il problema da un punto di vista astratto, se potessi avere a disposizione tutti gli strumenti che preferisci, tutte le definizioni che puoi dare. A quel punto il programma, qualsiasi programma, non sarà altro che un mettere insieme definizione specifiche con quelle, più generali, offerte dalla piattaforma che decidi di usare.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
|
|
|
|
|
|
#23 |
|
Member
Iscritto dal: Feb 2010
Messaggi: 31
|
grazie PGI-bis, ora studiero per bene quello che hai scritto...ti farò sapere se riusciro a capire questi "benedetti" file ... grazie
__________________
-.-'' |
|
|
|
|
|
#24 |
|
Member
Iscritto dal: Feb 2010
Messaggi: 31
|
grazie PGI-bis, ora studiero per bene quello che hai scritto...ti farò sapere se riusciro a capire questi "benedetti" file ... grazie
__________________
-.-'' |
|
|
|
|
|
#25 | |||
|
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
Quote:
Quote:
Quote:
2) non hai usato il tag CODE; 3) di conseguenza non hai neanche potuto indentare il codice; 4) sarebbe gradito leggere italiano corretto a meno di (sporadiche) sviste ortografiche. EDIT 5) contestualizza: oramai hai modificato il post iniziale, ma ti garantisco che non era molto lucido (non che adesso sia perfetto comunque).
__________________
3D Volley Demo (Facebook) | Reversi (Facebook) | Blockout (Facebook) | Puzzle15 (Facebook) Ultima modifica di fero86 : 18-07-2010 alle 20:00. |
|||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 10:45.





















