// testas testas testas
/*
D(k,l)- sveiku skaiciu matrica. 
Rasti kiekvienos eilutes teigiamu elementu vidurki.
Kiekvienos eilutes paskutini elementa pakeisti tos eilutes min elemento reiksme.
Iterpti (pasalinti) matricos pradzioje tiek eiluciu, kad matrica taptu kvadratine.
Iterpiamos tuscios eilutes.
*/
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cmath>
using namespace std;

// Konstantos
const int Cn = 100;
const int Cm = 50;
const string CDuom = "Masyvas.txt";
const string CRez = "Rezultatai.txt";

// Funkcij prototipai
void Skaityti(const string failas, int Duom[][Cm], int &n, int &m);
void Linija(ofstream &fr, int k);
void Antraste(ofstream &fr, string tekstas, int m);
void Rasyti(const string failas, string tekstas, int Duom[][Cm], int n, int m);
void SpausdintiEiluciuTeigiamuElementuVidurkius(const string failas, int Duom[][Cm], int n, int m);
double EilutesTeigiamuElementuVidurkis(int Mas[], int k);
void PakeistiPaskutiniusElementusMinElementu(int Duom[][Cm], int n, int m);
int Mini(int Mas[], int k);
void FormuotiKvadratineMatrica(int Duom[][Cm], int &n, int m);
void PasalintiPirmaEilute(int Mas[][Cm], int &n, int m);
void IteprtiEiluteIPradzia(int Mas[][Cm], int &n, int m);

int main ()
{
 int Mas[Cn][Cm];
 int n, m;
 ofstream fr(CRez.c_str());
 fr.close();
 Skaityti(CDuom, Mas, n, m);
 Rasyti(CRez, " Pradiniai duomenys:", Mas, n, m);
 SpausdintiEiluciuTeigiamuElementuVidurkius(CRez, Mas, n, m);
 PakeistiPaskutiniusElementusMinElementu(Mas, n , m);
 Rasyti(CRez, " Pakeitimo rezultatai:", Mas, n, m);
 FormuotiKvadratineMatrica(Mas, n, m);
 Rasyti( CRez, " Formavimo rezultatai:", Mas, n, m);
 cout << endl << "Rezultatu ieskokite faile: " << CRez.c_str() << "." << endl;
 system("pause");
 return 0;
}

// veda duomenis i failo  dvimat masyv.
// failas  duomen failo vardas
// Duom  dvimatis masyvas
// n  masyvo eilui kiekis
// m  masyvo stulpeli kiekis
void Skaityti(const string failas, int Duom[][Cm], int &n, int &m)
{
 ifstream fd(failas.c_str());
 fd >> n >> m;
 for (int i = 0; i < n; i++)
  for (int j = 0; j < m; j++)
   fd >> Duom[i][j];
 fd.close();
}

// Spausdina nurodyto ilgio linij  sraut.
// fr  srautas,  kur spausdinama
// k  spausdinamos linijos ilgis
void Linija(ofstream &fr, int k)
{
 fr << " -";
 for (int i = 0; i < k; i++)
  fr << "-";
 fr << endl;
}

// Spausdina lentels antrat  tekstin fail.
// fr  srautas,  kur spausdinama
// tekstas  aikinamasis tekstas, spausdinamas prie lentel
// m  masyvo stulpeli kiekis
void Antraste(ofstream &fr, string tekstas, int m)
{
 fr << endl << tekstas.c_str() << endl;
 Linija( fr, m+1);
 fr << " | E.\\S. | ";
 for (int j = 0; j < m; j++)
  fr << setw(5) << j+1 << " | ";
 fr << endl;
 Linija(fr, m+1);
}

// Spausdina masyvo duomenis  tekstin fail.
// failas  rezultat failo vardas
// tekstas  aikinamasis tekstas, spausdinamas prie lentel
// Duom  dvimatis masyvas
// n  masyvo eilui kiekis
// m  masyvo stulpeli kiekis
void Rasyti( const string failas, string tekstas,int Duom[][Cm], int n, int m)
{
 ofstream fr(failas.c_str(), ios::app);
 Antraste(fr, tekstas, m);
 for (int i = 0; i < n; i++){
  fr << " | " << setw(5) << i+1 << " | ";
  for (int j = 0; j < m; j++)
   fr << setw(5) << Duom[i][j] << " | ";
  fr << endl;
 }
 Linija(fr, m+1);
 fr << endl;
 fr.close();
}

// Randa bei ispausdina dvimaio masyvo kiekvienos eiluts teigiam element vidurkius
// failas  rezultat failo vardas
// Duom  dvimatis masyvas
// n  masyvo eilui kiekis
// m  masyvo stulpeli kiekis
void SpausdintiEiluciuTeigiamuElementuVidurkius(const string failas, int Duom[][Cm], int n, int m)
{
 ofstream fr(failas.c_str(), ios::app);
 fr << "Dvimaio masyvo kiekvienos eiluts teigiam element vidurkiai:" << endl;
 for (int i = 0; i < n; i++) {
  fr << "Eilut nr. " << i+1 << ": " << fixed << setprecision(2) << (double)EilutesTeigiamuElementuVidurkis(Duom[i], m) << "." << endl;
 }
 fr << endl;
 fr.close();
}

// Randa ir grina vienmaio masyvo teigiam element sum vidurk.
// Mas  vienmatis masyvas
// k  masyvo element kiekis
double EilutesTeigiamuElementuVidurkis(int Mas[], int k)
{
 double vidurkis = 0;
 int suma= 0, kiekis = 0;
 for (int i = 0; i < k; i++)
  if (Mas[i] > 0) {
	suma += Mas[i];
	kiekis++;
  }   
 vidurkis = (double)suma/kiekis;
 return vidurkis;
}

// Pakeiia paskutinius dvimaio masyvo kiekvienos eiluts elementus tos eiluts min elementu
// Duom  dvimatis masyvas
// n  masyvo eilui kiekis
// m  masyvo stulpeli kiekis
void PakeistiPaskutiniusElementusMinElementu(int Duom[][Cm], int n, int m)
{
 int min;
 for (int i = 0; i < n; i++){
  min = Mini(Duom[i], m);
  Duom[i][m-1] = min;
 }
}

// Randa ir grina vienmaio masyvo maiausio elemento reikm.
// Mas  vienmatis masyvas
// k  masyvo element kiekis
int Mini(int Mas[], int k)
{
 int mini = Mas[0];
 for (int i = 1; i < k; i++)
  if (Mas[i] < mini)
   mini = Mas[i];
 return mini;
}

// terpia (paalina) matricos pradioje tiek eilui, kad matrica tapt kvadratine.
// Duom  dvimatis masyvas
// n  masyvo eilui kiekis
// m  masyvo stulpeli kiekis
void FormuotiKvadratineMatrica(int Duom[][Cm], int &n, int m)
{
 if (n > m) {
  int salinti = n - m;
  for (int i = 0; i < salinti; i++)
	 PasalintiPirmaEilute(Duom, n, m);
 }
  else if (n < m) {
  int prideti = m - n;
  for (int i = 0; i < prideti; i++)
	 IteprtiEiluteIPradzia(Duom, n, m);
  }
}

// Paalina pirm eilut i dvimaio masyvo
// Duom  dvimatis masyvas
// n  masyvo eilui kiekis
// m  masyvo stulpeli kiekis
void PasalintiPirmaEilute(int Mas[][Cm], int &n, int m)
{
 for (int i = 0; i < n-1; i++)
  for (int j = 0; j < m; j++)
	Mas[i][j] = Mas[i+1][j];
 n -= 1;
}

// terpia eilut  dvimaio masyvo pradi
// Duom  dvimatis masyvas
// n  masyvo eilui kiekis
// m  masyvo stulpeli kiekis
void IteprtiEiluteIPradzia(int Mas[][Cm], int &n, int m)
{
 for (int i = n-1; i > -1; i--)
  for (int j = 0; j < m; j++)
	Mas[i+1][j] = Mas[i][j];
 for (int k = 0; k < m; k++)
  Mas[0][k] = 0;
 n += 1;
}