/* 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;
}