
#include "stdafx.h"

/*
Név: Kis Lázár Bence
Iskola: Magyar Tanítási Nyelvű Magángimnázium
Helység: Dunaszerdahely
Osztály: 11.

Fejlesztői környezet: Microsoft Visual Studio 2015
*/

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>

using namespace std;

//-----------------------//
//       KONSTANSOK      //
//-----------------------//

const string fLoc = "kozep.txt";	// kimeneti fájl helye

//-----------------------//
//       OSZTÁLYOK       //
//-----------------------//

class Layer {
public:
	Layer() { minLoc = 0; maxLoc = 0; vanished = false; };
	int data[200];		// mért adatok
	int minLoc;		// legkisebb vastagság helye, a mérés azonosítója
	int maxLoc;		// legnagyobb vastagság helye, a mérés azonosítója
	bool vanished;		// teljes elvékonyodás
	int mid[200];	// a középvonal értéke
};


//-----------------------//
//       FUNKCIÓK        //
//-----------------------//

int findLentilStart(int, int);		// visszaadja a lencse kezdetét
int findLentilEnd(int, int);		// visszaadja a lencse végét
bool checkSurface(int, int);		// visszaadja, hogy van-e réteg még fölötte az adott mérési ponton

//-----------------------//
//   GLOBÁLIS VÁLTOZÓK   //
//-----------------------//

int m = 0;		// mérések száma
int r = 0;		// rétegek száma
Layer layers[20];		// rétegek

//-----------------------//
//       FŐPROGRAM      //
//-----------------------//

int main() {
	cin >> m >> r;

	for (int i = 0; i < r; i++)
		for (int j = 0; j < m; j++) {
			cin >> layers[i].data[j];

			if (layers[i].data[j] < layers[i].data[layers[i].minLoc])			// kisebb az eddigi minimumnál
				layers[i].minLoc = j;
			else if (layers[i].data[j] > layers[i].data[layers[i].maxLoc])		// nagyobb az eddigi maximumnál
				layers[i].maxLoc = j;

			if (layers[i].data[j] == 0)			// teljesen elvékonyodott
				layers[i].vanished = true;
		}


	////    1. FELADAT    \\\\

	cout << "1. feladat:" << endl;
	cout << "\tUt: " << (m - 1)*500 << " meter" << endl;		// közök száma szorozva 500 méterrel
	cout << "\tRetegek szama: " << r << endl;


	////    2. FELADAT    \\\\

	int id;
	cout << "2. feladat:" << endl;
	cin >> id;
	id--;		// 0-val kezdődő indexelés miatt
	cout << "\tA(z) " << layers[id].maxLoc + 1 << ". meresnel volt a legvastagabb (" << layers[id].data[layers[id].maxLoc] << " meter), es a(z) " << layers[id].minLoc + 1 << ". meresnel volt a legvekonyabb (" << layers[id].data[layers[id].minLoc] << " meter) a(z) " << id + 1 << ". reteg" << endl;


	////    3. FELADAT    \\\\

	int vanishedNum = 0;
	for (int i = 0; i < r; i++)
		if (layers[i].vanished)
			vanishedNum++;

	cout << "3. feladat:" << endl << "\t";
	if (vanishedNum > 0)
		cout << vanishedNum << " reteg vekonyodott el teljesen." << endl;
	else
		cout << "Nem volt teljesen elvekonyodott reteg." << endl;


	////    4. FELADAT    \\\\

	int maxdepth = 0, maxdepthId;		// legmélyebb réteghatár nagysága és helye
	for (int j = 0; j < m; j++) {
		int depth = 0;		// az adott mérés teljes mélysége
		for (int i = 0; i < r; i++)
			depth += layers[i].data[j];
		if (depth > maxdepth) {			// nagyobb az eddigi maximumnál
			maxdepth = depth;
			maxdepthId = j;
		}
	}
	cout << "4. feladat:" << endl;
	cout << "\tA(z) " << maxdepthId + 1 << ". meresi helyen " << maxdepth << " meter melyen van a legmelyebb felterkepezett reteghatar." << endl;


	////    5. FELADAT    \\\\

	long long int depthDetect;		// a mélység, ahol meg akarjuk állapítani a réteg típusát
	cin >> depthDetect;

	cout << "5. feladat:" << endl << "\t";
	for (int i = 0; i < m; i++) {
		int depth = layers[0].data[i];
		int layerId = 0;		// réteg azonosítója, ahol az adott mélység van
		while (depth < depthDetect && layerId < r - 1)
			depth += layers[++layerId].data[i];
		if (depth >= depthDetect)
			cout << layerId + 1 << " ";
		else
			cout << "- ";
	}
	cout << endl;


	////    6. FELADAT    \\\\

	bool surface[20];		// tárolja, hogy az adott réteg feljön-e a felszínre valahol
	for (int i = 0; i < 20; i++)
		surface[i] = false;

	for (int j = 0; j < m; j++)
		for (int i = 0; i < r; i++)
			if (layers[i].data[j] > 0) {
				surface[i] = true;
				break;
			}

	int onSurface = 0;		// a felszínre feltörő rétegek száma
	for (int i = 0; i < r; i++)
		if (surface[i])
			onSurface++;

	cout << "6. feladat: " << onSurface << endl;


	////    7. FELADAT    \\\\

	cout << "7. feladat:" << endl;

	for (int i = 1; i < r; i++) {
		int lentilStart, lentilEnd, offset = 0;

		while (1) {
			lentilStart = findLentilStart(i, offset);
			if (lentilStart < 0)		// ha nem vékonyodik el egyszer sem teljesen, akkor nézzük a következő réteget
				break;

			lentilEnd = findLentilEnd(i, lentilStart + 1);
			if (lentilEnd < 0)			// ha nem vékonyodik el másodszor is, akkor nézzük a következő réteget
				break;

			bool cont = false;		// következő lencse keresése, ha igaz
			for (int j = lentilStart; j <= lentilEnd; j++)
				if (!checkSurface(i, j)) {		// van olyan része a lencsének, ami följön a felszínre
					cont = true;
					break;
				}
			offset = lentilEnd;		// onnan kezdjük a következő lencse keresését, ahol az előző végződött

			if (cont)		// valahol a réteg feljön a felszínre, következő lencse keresése ugyanebben a rétegben
				continue;

			cout << "\t" << i + 1 << ". reteg: " << (lentilEnd - lentilStart) * 500 << " meter" << endl;
		}
	}


	////    8. FELADAT    \\\\

	ofstream f;
	f.open(fLoc, ios::out);

	for (int i = 0; i <= (m - 1) * 5; i++)		// az utolsó mérés után már nincsenek közök
		f << i * 100 << "; ";
	f << endl;

	for (int j = 0; j < m; j++) {
		layers[0].mid[j] = (0 + layers[0].data[j]) / 2;		// a legfelső réteg középvonala
		int depth = layers[0].data[j];		// a réteg felső szintjének helye
		for (int i = 1; i < r; i++) {
			layers[i].mid[j] =  depth + layers[i].data[j] / 2;	// középvonalak
			depth += layers[i].data[j];		
		}
	}

	for (int i = 0; i < r; i++) {		
		for (int j = 0; j < m-1; j++)			// az utolsó mérés után már nincsenek közök
			for (int k = 0; k < 5; k++) {
				double mid = layers[i].mid[j] + (k / (double)5) * (layers[i].mid[j+1] - layers[i].mid[j]);
				f << floor(mid + 0.5) << "; ";
			}
		f << layers[i].mid[m-1] << "; ";
		f << endl;
	}
	return 0;
}


//-----------------------//
//        FUNKCIÓK       //
//-----------------------//

int findLentilStart(int layerId, int startFrom) {
	int i = startFrom;
	while (i < m) {
		if (layers[layerId].data[i] == 0) {		// megvan az elvékonyodás kezdete
			while (layers[layerId].data[i + 1] == 0 && i < m)	// de még meg kell keresnünk a lencse kezdetét
				i++;
			return i;
		}
		i++;
	}
	return -1;		// nincs teljes elvékonyodás
}

int findLentilEnd(int layerId, int startFrom) {
	int i = startFrom;
	while (i < m) {
		if (layers[layerId].data[i] == 0)		// megvan az elvékonyodás kezdete
			return i;
		i++;
	}
	return -1;		// nincs teljes elvékonyodás
}

bool checkSurface(int layerId, int measurement) {
	for (int i = 0; i < layerId; i++)
		if (layers[i].data[measurement] != 0)
			return true;
	return false;
}