Skip to content

Reforestation (additional task) #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions additional_tasks/template_task/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# Шаблонная задача
# Reforestation simulation

Описание задачи
There was a large rectangular forest consisting of M * N chunks. But unfortunately there was a forest fire and some of the chunks were burned to the ground, some were partially burned, and the rest were completely salvaged.

The forest after the fire is represented as a matrix M * N where each cell contains a value 0, 1 or 2 which has the following value:

0: Burned to the ground

1: Partially burned

2: Completely preserved

The goal is find the time nedeed to recover all partially burned chunks. A salvaged chunk with index (i, j) can recover partially burned neighboring chunks (up, down, left and right). If it is not possible to recover all partially burned chunks, just return -1 and the list of indecies of the chunks that can't be recovered.

P.S. This problem does not use the graph classes from lib, but a kind of BFS graph traversal.
32 changes: 31 additions & 1 deletion additional_tasks/template_task/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,31 @@
int main() { return 0; }
#include "utils.hpp"

void PrintResult(int result,
const std::vector<std::pair<int, int>>& unrecovered) {
std::cout << "Time: " << result << std::endl;
if (result == -1) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]

Suggested change
std::cout << "Time: " << result << std::endl;
std::cout << "Time: " << result << '\n';

std::cout << "Unrecovered chunks at indices:" << std::endl;
for (const auto& p : unrecovered)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]

Suggested change
std::cout << "Unrecovered chunks at indices:" << std::endl;
std::cout << "Unrecovered chunks at indices:" << '\n';

std::cout << "(" << p.first << ", " << p.second << ") ";
std::cout << std::endl;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]

Suggested change
std::cout << std::endl;
std::cout << '\n';

}

int main() {
std::vector<std::vector<int>> forest_1 = {{2, 1, 0}, {1, 1, 1}, {0, 1, 2}};
std::vector<std::pair<int, int>> unrecovered_1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'forest_1' of type 'std::vector<std::vector>' can be declared 'const' [misc-const-correctness]

Suggested change
std::vector<std::vector<int>> forest_1 = {{2, 1, 0}, {1, 1, 1}, {0, 1, 2}};
std::vector<std::vector<int>> const forest_1 = {{2, 1, 0}, {1, 1, 1}, {0, 1, 2}};

int result_1 = RecoverForest(forest_1, unrecovered_1);
PrintResult(result_1, unrecovered_1);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'result_1' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int result_1 = RecoverForest(forest_1, unrecovered_1);
int const result_1 = RecoverForest(forest_1, unrecovered_1);


std::vector<std::vector<int>> forest_2 = {{2, 0, 0}, {0, 1, 0}, {0, 0, 0}};
std::vector<std::pair<int, int>> unrecovered_2;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'forest_2' of type 'std::vector<std::vector>' can be declared 'const' [misc-const-correctness]

Suggested change
std::vector<std::vector<int>> forest_2 = {{2, 0, 0}, {0, 1, 0}, {0, 0, 0}};
std::vector<std::vector<int>> const forest_2 = {{2, 0, 0}, {0, 1, 0}, {0, 0, 0}};

int result_2 = RecoverForest(forest_2, unrecovered_2);
PrintResult(result_2, unrecovered_2);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'result_2' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int result_2 = RecoverForest(forest_2, unrecovered_2);
int const result_2 = RecoverForest(forest_2, unrecovered_2);


std::vector<std::vector<int>> forest_3 = {{2, 1, 2}, {1, 0, 1}};
std::vector<std::pair<int, int>> unrecovered_3;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'forest_3' of type 'std::vector<std::vector>' can be declared 'const' [misc-const-correctness]

Suggested change
std::vector<std::vector<int>> forest_3 = {{2, 1, 2}, {1, 0, 1}};
std::vector<std::vector<int>> const forest_3 = {{2, 1, 2}, {1, 0, 1}};

int result_3 = RecoverForest(forest_3, unrecovered_3);
PrintResult(result_3, unrecovered_3);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'result_3' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int result_3 = RecoverForest(forest_3, unrecovered_3);
int const result_3 = RecoverForest(forest_3, unrecovered_3);


return 0;
}
87 changes: 83 additions & 4 deletions additional_tasks/template_task/src/test.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,87 @@

#include <gtest/gtest.h>

#include <stack>

#include "utils.hpp"

TEST(Template, Simple) { ASSERT_EQ(true, true); }
// Test Case 1: Single Row with Mixed States
TEST(RecoverForestTests, SingleRowMixedStates) {
std::vector<std::vector<int>> forest = {{2, 1, 0, 1, 2}};
std::vector<std::pair<int, int>> unrecovered;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'forest' of type 'std::vector<std::vector>' can be declared 'const' [misc-const-correctness]

Suggested change
std::vector<std::vector<int>> forest = {{2, 1, 0, 1, 2}};
std::vector<std::vector<int>> const forest = {{2, 1, 0, 1, 2}};

int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, 1);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'result' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int result = RecoverForest(forest, unrecovered);
int const result = RecoverForest(forest, unrecovered);

}

// Test Case 2: Single Column with All Preserved
TEST(RecoverForestTests, SingleColumnAllPreserved) {
std::vector<std::vector<int>> forest = {{2}, {2}, {2}, {2}};
std::vector<std::pair<int, int>> unrecovered;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'forest' of type 'std::vector<std::vector>' can be declared 'const' [misc-const-correctness]

Suggested change
std::vector<std::vector<int>> forest = {{2}, {2}, {2}, {2}};
std::vector<std::vector<int>> const forest = {{2}, {2}, {2}, {2}};

int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, 0);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'result' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int result = RecoverForest(forest, unrecovered);
int const result = RecoverForest(forest, unrecovered);

}

// Test Case 3: Large Grid with Multiple Isolated Parts
TEST(RecoverForestTests, LargeGridMultipleIsolatedParts) {
std::vector<std::vector<int>> forest = {{0, 0, 2, 0, 0},
{0, 1, 0, 1, 0},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'forest' of type 'std::vector<std::vector>' can be declared 'const' [misc-const-correctness]

Suggested change
std::vector<std::vector<int>> forest = {{0, 0, 2, 0, 0},
std::vector<std::vector<int>> const forest = {{0, 0, 2, 0, 0},

{0, 0, 0, 0, 0},
{2, 0, 0, 1, 0},
{0, 0, 0, 0, 2}};
std::vector<std::pair<int, int>> unrecovered;
int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, -1);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'result' of type 'int' can be declared 'const' [misc-const-correctness]

Suggested change
int result = RecoverForest(forest, unrecovered);
int const result = RecoverForest(forest, unrecovered);

EXPECT_EQ(unrecovered.size(), 3);
EXPECT_EQ(unrecovered[0], std::make_pair(1, 1));
EXPECT_EQ(unrecovered[1], std::make_pair(1, 3));
EXPECT_EQ(unrecovered[2], std::make_pair(3, 3));
}

// Test Case 4: All Burned Except One
TEST(RecoverForestTests, AllBurnedExceptOne) {
std::vector<std::vector<int>> forest = {{0, 0, 0}, {0, 2, 0}, {0, 0, 0}};
std::vector<std::pair<int, int>> unrecovered;
int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, 0);
EXPECT_EQ(unrecovered.size(), 0);
}

// Test Case 5: Large Grid with All Preserved and One Isolated Partially Burned
TEST(RecoverForestTests, LargeGridAllPreservedOneIsolated) {
std::vector<std::vector<int>> forest = {
{2, 2, 2, 2}, {2, 1, 2, 2}, {2, 2, 2, 2}};
std::vector<std::pair<int, int>> unrecovered;
int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, 1);
EXPECT_EQ(unrecovered.size(), 0);
}

// Test Case 6: Circular Recovery
TEST(RecoverForestTests, CircularRecovery) {
std::vector<std::vector<int>> forest = {{2, 1, 2}, {1, 0, 1}, {2, 1, 2}};
std::vector<std::pair<int, int>> unrecovered;
int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, 1);
}

// Test Case 7: Large Sparse Grid
TEST(RecoverForestTests, LargeSparseGrid) {
std::vector<std::vector<int>> forest = {{0, 0, 0, 0, 0, 0, 0},
{0, 2, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 2, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0}};
std::vector<std::pair<int, int>> unrecovered;
int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, -1);
EXPECT_EQ(unrecovered.size(), 2);
EXPECT_EQ(unrecovered[0], std::make_pair(1, 4));
EXPECT_EQ(unrecovered[1], std::make_pair(4, 2));
}

// Test Case 8: Edge Case with One Chunk
TEST(RecoverForestTests, EdgeCaseOneChunk) {
std::vector<std::vector<int>> forest = {{1}};
std::vector<std::pair<int, int>> unrecovered;
int result = RecoverForest(forest, unrecovered);
EXPECT_EQ(result, -1);
EXPECT_EQ(unrecovered.size(), 1);
EXPECT_EQ(unrecovered[0], std::make_pair(0, 0));
}
63 changes: 63 additions & 0 deletions additional_tasks/template_task/src/utils.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,64 @@
#include "utils.hpp"

int RecoverForest(const std::vector<std::vector<int>>& grid,
std::vector<std::pair<int, int>>& unrecovered) {
// Number of rows and columns in the grid
int n = grid.size();
int m = grid[0].size();

// Steps for rows & columns (up, right, down, left)
std::vector<int> row_steps = {-1, 0, 1, 0};
std::vector<int> col_steps = {0, 1, 0, -1};

// Visited matrix
std::vector<std::vector<bool>> visited(n, std::vector<bool>(m, false));

// Queue for BFS
std::queue<std::pair<std::pair<int, int>, int>> q;

// Counter of all partially burnt chunks
int part_burnt_count = 0;

// Push all salvaged chunks into the queue
// & count all partially burnt chunks
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (grid[i][j] == 2) {
q.push({{i, j}, 0});
visited[i][j] = true;
} else if (grid[i][j] == 1)
part_burnt_count++;

// BFS
int recovered_count = 0, time = 0;
while (!q.empty()) {
int row = q.front().first.first;
int col = q.front().first.second;
int chunk_time = q.front().second;
q.pop();

// Update time
time = time < chunk_time ? chunk_time : time;

// Try steping in all 4 directions
for (int i = 0; i < 4; i++) {
int nrow = row + row_steps[i];
int ncol = col + col_steps[i];

if (nrow >= 0 && nrow < n && ncol >= 0 && ncol < m &&
grid[nrow][ncol] == 1 && !visited[nrow][ncol]) {
visited[nrow][ncol] = true;
q.push({{nrow, ncol}, time + 1});
recovered_count++;
}
}
}

// Find and store unrecovered chunks
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (grid[i][j] == 1 && !visited[i][j]) unrecovered.push_back({i, j});

// Return time
return (recovered_count == part_burnt_count) ? time : -1;
}
7 changes: 7 additions & 0 deletions additional_tasks/template_task/src/utils.hpp
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
#pragma once

#include <iostream>
#include <queue>
#include <vector>

int RecoverForest(const std::vector<std::vector<int>>& grid,
std::vector<std::pair<int, int>>& unrecovered);
Loading
Loading