#include // konstandid const true = -1; const false = 0; // Kaardi konstandid const mapEmpty = 45; // - const mapFull = 88; // X const mapStart = 97; // a const mapRoad = 98; // b const mapExtra = 43; // + // Punktitüüp struct point { int X; int Y; }; // globaalsed muutujad char *gFileName; int *gMap; // massiiv, mis laetakse failist int gRowCount; // ridade arv int gColCount; // veergude arv int gDistance; // teepikkus struct point gStartPoint; struct point gTopLeft; struct point gTopRight; struct point gBottomLeft; struct point gBottomRight; /** Loeb infot parameetritest. hetkel parameetreid pole. */ int TranslateParameter(char parameter) { switch (parameter) { default: return false; } } /** Loeb prgrammile antud argumentidest infot Kui argumendid pole korrektsed, siis tagastab false */ int TranslateArguments(int argc, char *argv[]) { int i; // Alustame teisest, sest esimene on programmi enda nimi for (i=1; i, // kusjuures enne korrutame viimast kümnega (nihutame vasakule). while (text[i] >= 48 && text[i] <= 57) { ret_val = (10 * ret_val) + (text[i] - 48); i++; } return ret_val; } /** Laeb andmed etteantud failist massiivi massiivi jaoks eraldab mälu */ int LoadFile(char *FileName) { int i, j; char row[128]; // rida FILE *input_file=fopen(FileName, "r"); // esimesest kahest reast loeme ridade ja veergude arvu gRowCount = StrToInt(fgets(row, 128, input_file)); gColCount = StrToInt(fgets(row, 128, input_file)); // loome vastava suurusega kahemõõtmelise massiivi gMap = (int *) malloc(sizeof(int) * gRowCount * gColCount); // kanname andmed failist rida-rea haaval massiivi for (i=0; i=0; j--) { if (gMap[(j+gTopRight.Y)*gColCount+(i+j)]==mapFull) { return i+1; break; } } i--; } while (ret_val==-2); return false; } /** joonistab ülemisse paremasse nurka diagonaali. --\--- ---\-- ----\- -----\ ------ */ int DrawTopRightDiagonals(int i) { int j; for (j=gTopRight.X-i; j>=0; j--) { if (gMap[(j+gTopRight.Y)*gColCount+(i+j)]==mapEmpty) { gMap[(j+gTopRight.Y)*gColCount+(i+j)] = mapRoad; // joonistamine } } return true; } /** alumisest vasakust nurgast alustades hakkab läbi käima diagonaale, kuni puutub kokku saarega. ------ \----- \\---- \\\--- \\\\-- */ int BottomLeftDiagonals(void) { int i=gBottomLeft.X; int j; int ret_val = -2; do { for (j=0; j<=i-gBottomLeft.X; j++) { if (gMap[(gBottomLeft.Y-j)*gColCount+(i-j)]==mapFull) { return i-1; break; } } i++; } while (ret_val==-2); return false; } /** joonistab alumisse vasakusse nurka diagonaali. ------ \----- -\---- --\--- ---\-- */ int DrawBottomLeftDiagonals(int i) { int j; for (j=0; j<=i-gBottomLeft.X; j++) { if (gMap[(gBottomLeft.Y-j)*gColCount+(i-j)]==mapEmpty) { gMap[(gBottomLeft.Y-j)*gColCount+(i-j)] = mapRoad; // joonistamine } } return true; } /** alumisest paremast nurgast alustades hakkab läbi käima diagonaale, kuni puutub kokku saarega. ------ -----/ ----// ---/// --//// */ int BottomRightDiagonals(void) { int i=gBottomRight.X; int j; int ret_val = -2; do { for (j=0; j<=gBottomRight.X-i; j++) { if (gMap[(gBottomRight.Y-j)*gColCount+(i+j)]==mapFull) { return i+1; break; } } i--; } while (ret_val==-2); return false; } /** joonistab alumisse paremasse nurka diagonaali. ------ -----/ ----/- ---/-- --/--- */ int DrawBottomRightDiagonals(int i) { int j; for (j=0; j<=gBottomRight.X-i; j++) { if (gMap[(gBottomRight.Y-j)*gColCount+(i+j)]==mapEmpty) { gMap[(gBottomRight.Y-j)*gColCount+(i+j)] = mapRoad; // joonistamine } } return true; } /** sulgeb vasaku külje -/----- /------ |------ |------ \------ -\----- */ int CapHolesLeft(void) { int x=gTopLeft.X; int y; int start = -1; int finish = -1; // otsime alguse ja lõpu for (y=gTopLeft.Y; y-1) { finish = y; }else{ start = y; } } } if (finish > start) { for (y=start; y-1) { finish = y; }else{ start = y; } } } if (finish > start) { for (y=start; y-1) { finish = x; }else{ start = x; } } } if (finish > start) { for (x=start; x-1) { finish = x; }else{ start = x; } } } if (finish > start) { for (x=start; xX = 1; connection->Y = 0; return true; } }else{ stop++; } // vasakule if (gStartPoint.X - i >= 0) { if (gMap[gStartPoint.Y * gColCount + gStartPoint.X - i] == mapRoad) { connection->X = -1; connection->Y = 0; return true; } }else{ stop++; } // üles if (gStartPoint.Y - i >= 0) { if (gMap[(gStartPoint.Y - i) * gColCount + gStartPoint.X] == mapRoad) { connection->X = 0; connection->Y = -1; return true; } }else{ stop++; } // alla if (gStartPoint.Y + i < gRowCount) { if (gMap[(gStartPoint.Y + i) * gColCount + gStartPoint.X] == mapRoad) { connection->X = 0; connection->Y = 1; return true; } }else{ stop++; } // alla paremale if (gStartPoint.Y + i < gRowCount && gStartPoint.X + i < gColCount) { if (gMap[(gStartPoint.Y + i) * gColCount + gStartPoint.X + i] == mapRoad || gMap[(gStartPoint.Y + i - 1) * gColCount + gStartPoint.X + i] == mapRoad) { connection->X = 1; connection->Y = 1; return true; } }else{ stop++; } // alla vasakule if (gStartPoint.Y + i < gRowCount && gStartPoint.X - i >= 0) { if (gMap[(gStartPoint.Y + i) * gColCount + gStartPoint.X - i] == mapRoad || gMap[(gStartPoint.Y + i - 1) * gColCount + gStartPoint.X - i] == mapRoad) { connection->X = -1; connection->Y = 1; return true; } }else{ stop++; } // üles paremale if (gStartPoint.Y - i >= 0 && gStartPoint.X + i < gColCount) { if (gMap[(gStartPoint.Y - i) * gColCount + gStartPoint.X + i] == mapRoad || gMap[(gStartPoint.Y - i + 1) * gColCount + gStartPoint.X + i] == mapRoad) { connection->X = 1; connection->Y = -1; return true; } }else{ stop++; } // üles vasakule if (gStartPoint.Y - i >= 0 && gStartPoint.X - i >= 0) { if (gMap[(gStartPoint.Y - i) * gColCount + gStartPoint.X - i] == mapRoad || gMap[(gStartPoint.Y - i + 1) * gColCount + gStartPoint.X - i] == mapRoad) { connection->X = -1; connection->Y = -1; return true; } }else{ stop++; } } while (stop<8); return false; } /** Joonistab ühenduse alguspunktist kuni saart ümbritseva teeni */ int DrawStartConnection(struct point *connection) { int i=0; while (true) { i++; if (gMap[(gStartPoint.Y + (connection->Y*i)) * gColCount + gStartPoint.X + (connection->X*i)] == mapRoad) { return i; }else{ gMap[(gStartPoint.Y + (connection->Y*i)) * gColCount + gStartPoint.X + (connection->X*i)] = mapRoad; if (gMap[(gStartPoint.Y + (connection->Y*(i+1))) * gColCount + gStartPoint.X + (connection->X*i)] == mapRoad) { return i; } } } } /** Liigub sammu võrra edasi mööda saart ümbritsevat teed. tagastab muutunud x ja y koordinaadid. Kui tee hargneb, siis saab väärtuseks */ int TakeOneStep(int *x, int *y, int *road_split) { int dx, dy; int first_found = false; int first_x; int first_y; // Käime läbi kõik punkti (x,y) ümbritsevad punktid: // *** // *X* // *** for (dx=-1; dx<=1; dx++) { for (dy=-1; dy<=1; dy++) { // punkti (x,y) ennast me ei arvesta if (dx == 0 && dy == 0) { }else{ // kui punktis (x+dx, y+dx) on teerada if (gMap[(*y + dy) * gColCount + (*x + dx)] == mapRoad) { // kui üks teerada on juba leitud if (first_found) { // teatame, et tee haruneb *road_split = true; // väljastame varem meelde jäetud parameetrid ning *x = first_x; *y = first_y; return true; }else{ // kui leitakse esimene teerada, siis // märgime kaardile, et seal on juba käidud gMap[(*y + dy) * gColCount + (*x + dx)] = mapExtra; first_found = true; // jätame meelde selle koha koordinaadid first_x = *x+dx; first_y = *y+dy; // kui tee on juba korra harunenud, siis if (*road_split) { // väljastame parameetrid ning *x = first_x; *y = first_y; return true; } } } } } } // kui kõik ümbritsevad punktid on läbi vaadatud ning üks teerada leitud, if (first_found) { // väljastame selle koordinaadid ning *x= first_x; *y= first_y; return true; }else{ // Vastasel juhul anname teada, et ühtki teed ei leitud // ning sellest punktist seega edasi liikuda ei saa. return false; } } /** Leiab teepikkuse */ int MeasureDistance(void) { int x = gStartPoint.X; int y = gStartPoint.Y; int i=0; int road_split = false; int road_split_done = false; // seni kuni saame edasi minna mööda läbikäimata rada while (TakeOneStep(&x, &y, &road_split)) { i++; // kui tee hargneb, siis if (road_split && !road_split_done) { // Kui tee ei harune alguspunktis, siis korrutame senise teepikkuse // kahega. // Kuna kahega korrutamisel saab ühtlasi kaasa arvatud ka // alguspunkt, siis lahutame selle, sest lõpus lisatakse see // niikuinii. if (i>1) { i=i * 2 - 1; } // rohkem kui üks kord tee haruneda ei saa road_split_done = true; } } // Kuna alguspunkti pole veel kaasa arvatud, // siis lisame selle lõpptulemusele return i+1; } /** Teostab kõik analüüsid laetud kaardil. Joonistab kaardile teekonna Mõõdab teepikkuse */ int Analize(void) { // alguspunkti ja saart ümbritseva tee ühendustee suund struct point connection; // määrame saart ümbritseva ristküliku // ühtlasi saame teada ka alguspunkti FindFirstAndLastRowAndStartPoint(); FindFirstAndLastCol(); // leiame kui palju me saame nimetatud ristküliku nurkasid maha lõigata // seejärel joonistame vastavad diagonaalid DrawTopLeftDiagonals(TopLeftDiagonals()); DrawTopRightDiagonals(TopRightDiagonals()); DrawBottomLeftDiagonals(BottomLeftDiagonals()); DrawBottomRightDiagonals(BottomRightDiagonals()); // ning joonistame ristküliku servad, mis jäeti alles CapHolesLeft(); CapHolesRight(); CapHolesTop(); CapHolesBottom(); // leiame ühendustee stardipunkti ja saart ümbritseva teee vahel FindStartConnection(&connection); // ja joonistame selle DrawStartConnection(&connection); // mõõdame teepikkuse gDistance = MeasureDistance(); return true; } int main(int argc, char *argv[]) { if (TranslateArguments(argc, argv)) { // laeme faili LoadFile(gFileName); // teostame analüüsid Analize(); // väljastame teepikkuse printf("%d\n", gDistance); // väljastame kaardi OutputMap(); // vabastame mälu free(gMap); return 0; }else{ printf("Viga parameetrites!\n"); return 1; } }