[C++] Vettori palindromi con tappo negativo.
Scrivere in C++ un programmma che dato in input una sequenza di numeri positivi terminata da un tappo negativo:
a) memorizi la sequenza in un array;
b) stampi "la sequenza è palindroma" se la sequenza è palindroma.
Il mio tentativo è questo. Il programma gira, finora non mi ha dato problemi. La disgrazia è che il programma non è elegante, mentre la mia insegnante pretende la perfezione
.
Il mio intento è quello di modificare questo pezzo di codice che mi sembra abbastanza prolisso. Ho visto altri programmi per la verifica dei palindromi e non fanno questa distinzione, ma per come ho agito mi sembra necessario. Mi aiutate a modificarlo per rendere il codice più elegante?
Mille grazie!
Ps: molti di questi cout verranno eliminati. Servivano a me per capire come si muovevano gli indici, non essendo ancora in grado di fare queste cose ad occhio ho bisogno di visualizzare il comportamento di ciascuna variabile.
a) memorizi la sequenza in un array;
b) stampi "la sequenza è palindroma" se la sequenza è palindroma.
Il mio tentativo è questo. Il programma gira, finora non mi ha dato problemi. La disgrazia è che il programma non è elegante, mentre la mia insegnante pretende la perfezione

#include<iostream>//libreria che contiene i comandi cin cout using namespace std; const int m=10; //costante globale indicante la dimensione dell'array statico int main()//funzione principale { int A[m];//dichiarazione dell'array di dimensione m int i=0;//dichiarazione e inizializzazione della variabile intera int j=0;//dichiarazione e inizializzazione della variabile intera int n=0;//dichiarazione e inizializzazione della variabile intera while(i<m && j!=-1) { cout<<"inserisci l'elemento A("<<i<<") "<<endl; cin>>j; A[i]=j; i++; cout<<"i="<<i<<endl; }//istruzione che permette di inserire gli elementi dell'array if(i-1==0 && j==-1) { cout<<"il vettore inserito e' vuoto"<<endl; return 0; } else { cout<<"(i-2)/2= "<<(i-2)/2<<endl; for(int k=0; k<=(i-2)/2;k++) { cout<<"A("<<k<<")="<<A[k]<<endl; cout<<"A("<<i-2-k<<")="<<A[i-2-k]<<endl; if(A[k]==A[i-2-k])//condizione che permette di verificare se l'array è palindromo oppure no { n++;//incremento della variabile n cout<<"n= "<<n<<endl; cout<<"k= "<<k<<endl; } } if((i-2)%2==0)//sorgono problemi con la dimensione dell'array { if(n==(i-1)/2+1) cout<<"il vettore e' palindromo"<<endl; else cout<<"il vettore non e' palindromo"<<endl; } else if(n==(i-1)/2) cout<<"il vettore e' palindromo"<<endl; else cout<<"il vettore non e' palindromo"<<endl; } return 0; }
Il mio intento è quello di modificare questo pezzo di codice che mi sembra abbastanza prolisso. Ho visto altri programmi per la verifica dei palindromi e non fanno questa distinzione, ma per come ho agito mi sembra necessario. Mi aiutate a modificarlo per rendere il codice più elegante?
if((i-2)%2==0)//sorgono problemi con la dimensione dell'array { if(n==(i-1)/2+1) cout<<"il vettore e' palindromo"<<endl; else cout<<"il vettore non e' palindromo"<<endl; } else if(n==(i-1)/2) cout<<"il vettore e' palindromo"<<endl; else cout<<"il vettore non e' palindromo"<<endl; } return 0; }
Mille grazie!

Ps: molti di questi cout verranno eliminati. Servivano a me per capire come si muovevano gli indici, non essendo ancora in grado di fare queste cose ad occhio ho bisogno di visualizzare il comportamento di ciascuna variabile.
Risposte
if(A[k]==A[i-2-k])//condizione che permette di verificare se l'array è palindromo oppure no
a me non è chiara questa istruzione:
se ho ben capito l'ultimo elemento del vettore è il tappo, se ho 10 numeri, quindi l'undicesimo è il tappo. E' cosi' ?
In questo caso nel primo ciclo te confronti il 1^ con l'ottavo ? (i-2-k) ovvero (11-2-1)
Mi sfugge qualcosa...
Opperbacco!! Non funziona.. Se la dimensione dell'array è 10 mi sballa tutto. Lo devo rifare
.
Grazie Umby per avermi fatto notare l'errore, ho sempre fatto prove con vettori di lunghezza minore e andava bene (anche se mi rendo conto che non è un bellissimo programma, ne ho visti un paio davvero molto eleganti..).
Mi rimetto all'opera. Tu hai qualche suggerimento in merito? Grazie
[size=75]Edit: autocensura[/size]

Grazie Umby per avermi fatto notare l'errore, ho sempre fatto prove con vettori di lunghezza minore e andava bene (anche se mi rendo conto che non è un bellissimo programma, ne ho visti un paio davvero molto eleganti..).
Mi rimetto all'opera. Tu hai qualche suggerimento in merito? Grazie

[size=75]Edit: autocensura[/size]
"Mathematico":
Tu hai qualche suggerimento in merito? Grazie
a me non piace quella parte del codice finale (così come ti hanno già detto)
Io utilizzerei uno switch (ovvero una variabile che inizialmente la posizioni a zero, e poi la setti ad 1 nel caso incontri due numeri diversi).
A fine ciclo se lo switch è settato a zero --> Tutto Ok, se è 1 NO.
Io utilizzerei due indici invece che uno solo e mi fermerei quando si scambiano di ordine per testare se un array e palindromo. Qualcosa come:
dove A è l'array da testare e end è la sua dimensione. Ovviamente da questo codice con due indici si può passare ad uno che ne utilizza uno solo notando che high = end - 1 - low. Ma sinceramente non credo che in pratica ci siano vantaggi né a livello di performance, né di chiarezza del codice. Nota che ho semplicemente usato una variabile booleana per verificare se l'array è palindromo come suggerito da Umby. È sicuramente più semplice che cercare di capirlo a partire dalla posizione degli indici.
Due altre piccole note sul tuo programma.
- Usa nomi più espressivi per le variabili. In questo modo la loro funzione è subito chiara a partire dal nome.
- Usa commenti per spiegare cosa fa il codice e non il significato delle istruzione che usi. Ben presto ti saranno subito evidenti ma il significato di cicli o variabili da te usati non lo sarà probabilmente più. Mi riferisco in particolare ai commenti alle righe in cui inizializzi le variabili. È inutile dire che stai inizializzando una variabile, chiunque abbia un minimo di esperienza in C/C++/Java/C#... lo saprebbe ma il significato di i, j e k non è chiaro dal tuo programma immediatamente. Normalmente vengono usate solo come contatori ma tu dai loro un significato più preciso a partire da un certo punto del programma e quindi è meglio renderlo evidente con un commento.
- Il tuo programma va in crash se vengono inseriti più di 10 elementi nel tuo array.
P.S. Ho appena notato che l'ultimo elemento dell'array non deve essere considerato. In questo caso il codice precedente va semplicemente modificato scrivendo end - 2 al posto di end - 1.
bool is_palindromo = true; for (int low = 0, high = end - 1; low < high; ++low, --high) { if (A[low] != A[high]) { cout << "Il vettore non è palindromo\n"; is_palindromo = false; break; } } if (is_palindromo) { cout << "Il vettore è palindromo\n"; }
dove A è l'array da testare e end è la sua dimensione. Ovviamente da questo codice con due indici si può passare ad uno che ne utilizza uno solo notando che high = end - 1 - low. Ma sinceramente non credo che in pratica ci siano vantaggi né a livello di performance, né di chiarezza del codice. Nota che ho semplicemente usato una variabile booleana per verificare se l'array è palindromo come suggerito da Umby. È sicuramente più semplice che cercare di capirlo a partire dalla posizione degli indici.
Due altre piccole note sul tuo programma.
- Usa nomi più espressivi per le variabili. In questo modo la loro funzione è subito chiara a partire dal nome.
- Usa commenti per spiegare cosa fa il codice e non il significato delle istruzione che usi. Ben presto ti saranno subito evidenti ma il significato di cicli o variabili da te usati non lo sarà probabilmente più. Mi riferisco in particolare ai commenti alle righe in cui inizializzi le variabili. È inutile dire che stai inizializzando una variabile, chiunque abbia un minimo di esperienza in C/C++/Java/C#... lo saprebbe ma il significato di i, j e k non è chiaro dal tuo programma immediatamente. Normalmente vengono usate solo come contatori ma tu dai loro un significato più preciso a partire da un certo punto del programma e quindi è meglio renderlo evidente con un commento.
- Il tuo programma va in crash se vengono inseriti più di 10 elementi nel tuo array.
P.S. Ho appena notato che l'ultimo elemento dell'array non deve essere considerato. In questo caso il codice precedente va semplicemente modificato scrivendo end - 2 al posto di end - 1.
"apatriarca":
[...]
Due altre piccole note sul tuo programma.
- Usa nomi più espressivi per le variabili. In questo modo la loro funzione è subito chiara a partire dal nome.
- Usa commenti per spiegare cosa fa il codice e non il significato delle istruzione che usi. Ben presto ti saranno subito evidenti ma il significato di cicli o variabili da te usati non lo sarà probabilmente più. Mi riferisco in particolare ai commenti alle righe in cui inizializzi le variabili. È inutile dire che stai inizializzando una variabile, chiunque abbia un minimo di esperienza in C/C++/Java/C#... lo saprebbe ma il significato di i, j e k non è chiaro dal tuo programma immediatamente. Normalmente vengono usate solo come contatori ma tu dai loro un significato più preciso a partire da un certo punto del programma e quindi è meglio renderlo evidente con un commento.
Ti ringrazio, sono consigli ottimi, devo ficcarmeli bene in mente

"apatriarca":
- Il tuo programma va in crash se vengono inseriti più di 10 elementi nel tuo array.
Il problema è che se inserisco un vettore tipo
$(1,1,1,1,1,1,1,1,1,2)$ secondo il mio programma risulta palindromo, quando in realtà non lo è. In pratica non prende in considerazione $A(9)$. Finquando inseriscono vettori la cui lunghezza è minore di 10 allora funzia. Inoltre non è possibile inserire più di 10 elementi, perchè il while non lo permette

Hai ragione, non avevo notato che c'era anche il test i
A questo punto gli elementi validi dell'array vanno da 0 a i-1 in ogni caso.
for (i = 0; i < m; ++i) { cout << "inserisci l'elemento A(" << i << ") " << endl; cin >> A[i]; // termina la lettura dell'array prematuramente if (A[i] == -1) break; }
A questo punto gli elementi validi dell'array vanno da 0 a i-1 in ogni caso.
A questo punto proverei a complicare un po il problema modificandolo così:
Dato un vettore con lunghezza n, ordinarlo per renderlo palindromo, stabilendo se sia o meno possibile.
Dato un vettore con lunghezza n, ordinarlo per renderlo palindromo, stabilendo se sia o meno possibile.
"Umby":
A questo punto proverei a complicare un po il problema modificandolo così:
Dato un vettore con lunghezza n, ordinarlo per renderlo palindromo, stabilendo se sia o meno possibile.
Mmm, su questo ci devo pensare un po', e purtroppo non ho molto tempo per ragionarci su


"Umby":
A questo punto proverei a complicare un po il problema modificandolo così:
Dato un vettore con lunghezza n, ordinarlo per renderlo palindromo, stabilendo se sia o meno possibile.
Ma il modo non è unico... cioé
AAMM
ha come ordinamenti palindromi
MAAM e AMMA
Se prendiamo ABCABC allora sono
ABCCBA
ACBBCA
BACCAB
BCAACB
CABBAC
CBAABC
Cioé dato una stringa palindroma esistono $(N//2)!$ permutazioni degli elementi della stringa che mantengono la caratteristica di essere palindroma...
Per il test è facile. Basta controllare che se il vettore ha lunghezza pari allora il numero di ripetizioni di una lettera nel vettore sia sempre pari, altrimenti che ce ne sia esattamente una con ripetizioni dispari.
Per crearlo basta contare le lettere e inserire le lettere in ordine alfabetico e poi al contrario. Nel caso di vettore dispari basta memorizzare la lettera che compare un numero di volte dispari.
Non sempre $(N/2)!$,
dipende da quante volte una certa cifra si ripete.
Se, ad esempio, prendi:
AAAABBBCCCCAAAABBBCCCC
le permutazioni sono inferiori
dipende da quante volte una certa cifra si ripete.
Se, ad esempio, prendi:
AAAABBBCCCCAAAABBBCCCC
le permutazioni sono inferiori
"vict85":
. Nel caso di vettore dispari basta memorizzare la lettera che compare un numero di volte dispari.
... e disporla al centro del vettore ... (intendevi questo ? )