[C++] Vettori palindromi con tappo negativo.

salvozungri
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 :?.

#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! :D

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
Umby2
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...

salvozungri
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 :D

[size=75]Edit: autocensura[/size]

Umby2
"Mathematico":


Tu hai qualche suggerimento in merito? Grazie :D



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.

apatriarca
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:
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.

salvozungri
"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 :?.

apatriarca
Hai ragione, non avevo notato che c'era anche il test i
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.

Umby2
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.

salvozungri
"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 :( , bel quesito comunque, spero che qualcuno possa inserire il codice :D!

vict85
"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.

Umby2
Non sempre $(N/2)!$,
dipende da quante volte una certa cifra si ripete.
Se, ad esempio, prendi:
AAAABBBCCCCAAAABBBCCCC
le permutazioni sono inferiori

Umby2
"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 ? )

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.