#include <iostream>
#include <cstdlib>
#include <iomanip>

using namespace std;

void demonstrateHeapAllocation(){
	cout<<"\n--- 1. ΔΥΝΑΜΙΚΗ ΔΕΣΜΕΥΣΗ ΣΤΟ HEAP ---"<<endl;
	int size;
	cout<<"Δώσε το μέγεθος του πίνακα που θες: ";
	cin>>size;
	if(size<=0){
		cout<<"Μη έγκυρο μέγεθος!"<<endl;
		return;
	}
	int *p=new int[size];
	//Το 'p' ζει στο stack αλλά τα δεδομένα που δείχνει ζουν στο heap.
	cout<<"Επιτυχεία!"<<endl;
	for(int i=0;i<size;i++){
		p[i]=(i+1)*10;
	}
	cout<<"Τα πρώτα στοιχεία είναι: ";
	for(int i=0;i<(size>5?5:size);i++){
		cout<<p[i]<<" ";
	}
	cout<<(size>5?"...":"")<<endl;
	delete[] p;
	cout<<"[MEMORY FREED]"<<endl;
}

void demonstrateSizeofQuirk(int *dynamicArray, int staticArray[5]){
	cout<<"\n--- 2. ΤΟ ΠΡΟΒΛΗΜΑ ΤΟΥ SIZEOF ---"<<endl;
	cout<<" - sizeof(dynamicArray): "<<sizeof(dynamicArray)<<" bytes (Μέγεδος δείκτη)"<<endl;
	cout<<" - sizeof(staticArray): "<<sizeof(staticArray)<<" bytes (Μέγεθος δείκτη πάλι)"<<endl;
	cout<<"\nΓι'αυτό ποτέ δεν βασιζόμαστε στο sizeof() για το μήκος δυναμηκού πίνακα."<<endl;
}

void demonstrateArrayReductionAndExpansion(){
	cout<<"\n--- 3. REDUCTION ΚΑΙ EXPANSION ---"<<endl;
	int initialSize=5;
	int *A=new int[initialSize];
	for(int i=0;i<initialSize;i++) A[i]=i+1;
	cout<<"Αρχικός πίνακας: ";
	for(int i=0;i<initialSize;i++) cout<<"\nΔιεύθυνση αρχικού: "<<A<<endl;
	//REDUCTION - Μείωση σε 3 στοιχεία
	cout<<"[Reduction] Μείωση σε 3 στοιχεία..."<<endl;
	int newSize=3;
	int *B=new int[newSize];
	for(int i=0;i<newSize;i++) B[i]=A[i];//Αντιγραφή
	delete[] A;
	A=B;
	cout<<"Νέος πίνακας: ";
	for(int i=0;i<newSize;i++) cout<<A[i]<<" ";
	cout<<"\nΔιεύθυνση νέου: "<<A<<endl;
	//---------------------------------------------
	//EXPANSION - Επέκταση με realloc
	cout<<"\n[Expansion] Επέκταση κατά 2 στοιχεία..."<<endl;
	int addedSize=2;
	int totalSize=newSize+addedSize;
	A=reinterpret_cast<int *>(realloc(A,totalSize*sizeof(int)));
	A[3]=99;
	A[4]=100;
	cout<<"Επεκταμένος πίνακας: ";
	for(int i=0;i<totalSize;i++) cout<<A[i]<<" ";
	cout<<"\nΤελική διεύθυνση: "<<A<<endl;
	free(A);//free() με realloc όχι delete
	cout<<"[MEMORY FREED]"<<endl;
}

void demonstrate2DDynamicArray(){
	cout<<"\n--- 4. ΔΥΝΑΜΙΚΟΣ 2D ΠΙΝΑΚΑΣ ---"<<endl;
	int rows=4;
	int cols=5;
	int **matrix=new int*[rows];
	for(int i=0;i<rows;i++){
		matrix[i]=new int[cols];
	}
	for(int i=0;i<rows;i++){
		for(int j=0;j<cols;j++){
			matrix[i][j]=(i+1)*10+(j+1);
		}
	}
	cout<<"Περιεχόμενα: "<<endl;
	for(int i=0;i<rows;i++){
		for(int j=0;j<cols;j++){
			cout<<setw(4)<<matrix[i][j]<<" ";
		}
		cout<<endl;
	}
	for(int i=0;i<rows;i++){
		delete[] matrix[i];
	}
	delete[] matrix;
	cout<<"[MEMORY FREED]"<<endl;
}

void demonstrateNonSquareArray(){
	cout<<"\n--- 5. ΜΗ ΤΕΤΡΑΓΩΝΙΚΟΣ 2D ΠΙΝΑΚΑΣ ---"<<endl;
	int rows=5;
	int **pyramid=new int*[rows];
	for(int i=0;i<rows;i++){
		pyramid[i]=new int[i+1];
		for(int j=0;j<=i;j++){
			pyramid[i][j]=1;
		}
	}
	for(int i=0;i<rows;i++){
		for(int j=0;j<=i;j++){
			cout<<pyramid[i][j]<<" ";
		}
		cout<<endl;
	}
	for(int i=0;i<rows;i++){
		delete[] pyramid[i];
	}
	delete[] pyramid;
	cout<<"[MEMORY FREED]"<<endl;
}

void showMenuPart3(){
	cout<<"\n======================================="<<endl;
	cout<<"   ΕΚΠΑΙΔΕΥΤΙΚΟ ΜΕΝΟΥ ΔΕΙΚΤΩΝ"<<endl;
	cout<<"======================================="<<endl;
	cout<<"1. Δυναμική Δέσμευση"<<endl;
	cout<<"2. Το παράδοξο του sizeof"<<endl;
	cout<<"3. Αυξομείωση Πινάκων"<<endl;
	cout<<"4. Δυναμικός 2D Πίνακας"<<endl;
	cout<<"5. Μη Τετραγωνικός 2D Πίνακας"<<endl;
	cout<<"0. Έξοδος"<<endl;
	cout<<"======================================="<<endl;
	cout<<"Επίλεξε μια λειτουργία (0-5): ";
}

int main(){
	int choice=-1;
	while(choice!=0){
		showMenuPart3();
		cin>>choice;
		if(cin.fail()){
			cin.clear();
			cin.ignore(10000,'\n');
			cout<<"Εισάγετε έναν έγκυρο αριθμό."<<endl;
			continue;
		}
		switch(choice){
			case 1:
				demonstrateHeapAllocation();
			case 2:
				{
					int *dyn=new int[5];
					int stat[5];
					demonstrateSizeofQuirk(dyn,stat);
					delete[] dyn;
				}
				break;
			case 3:
				demonstrateArrayReductionAndExpansion();
				break;
			case 4:
				demonstrate2DDynamicArray();
			case 5:
				demonstrateNonSquareArray();
				break;
			case 0:
				cout<<"Ολοκλήρωση!"<<endl;
				break;
			default:
				cout<<"Μη έγκυρη επιλογή. Προσπάθησε ξανά."<<endl;
				break;
		}
	}
	return 0;
}



