Reputation: 23
I am making an interesting task with the matrix. But now I'm stuck with the code below. I want to make different behavior depending on the enum type.
My types:
using Matrix = std::vector<std::vector<int>>;
using Row = std::vector<int>;
enum class Diagonal {MAIN, ANTI};
First behavior.
This portion of code runs when diagonal == Diagonal::MAIN
:
size_t diagonalSum(const Matrix& matrix, Diagonal diagonal) {
assert(isSquare(matrix));
size_t sum = 0;
auto startRow = matrix.cbegin();
for(auto row = startRow; row != matrix.end(); ++row) {
for(auto column = row->cbegin(); column != row->end(); ++column) {
if(std::distance(firstRow, row) == std::distance(row->cbegin(), column)) {
sum += *column;
}
}
}
return sum;
}
Second behavior.
This portion of code runs when diagonal == Diagonal::ANTI
:
size_t diagonalSum(const Matrix& matrix, Diagonal diagonal) {
assert(isSquare(matrix));
size_t sum1 = 0;
auto startRow = matrix.cbegin();
for(auto row = startRow; row != matrix.cend(); ++row) {
for(auto column = row->crbegin(); column != row->crend(); ++column) {
if(std::distance(startRow, row) == std::distance(row->crbegin(), column)) {
sum1 += *column;
}
}
}
return sum;
}
The only difference in the code snippets shown above is that they use different iterators to traverse the columns.
I thought such a small difference between calculating the sum of the main diagonal and the antidiagonal will help me write neat code, to customise the behavior of the function diagonalSum
easily.
After reading about templates, I understood that it cannot help me. So the only way is to overload the function. Am I right?
But how to do it with the one enum? Should I make more types to perform overloading but unfortunately this is not so neat.
Upvotes: 0
Views: 125
Reputation: 23
I decided to genearilze the idea of doing some kind of computation with the matrix.
So there are functions that you can easily added. They are packed in the finction store. You can unpack them using enum
.
Defining functions for packing into the function store.
enum class ComputationMode {MAIN_DIAGONAL_SUM, ANTI_DIAGONAL_SUM};
std::size_t calculateMainDiagonalSum(const Matrix& matrix) {
auto firstRow = matrix.cbegin();
auto lastRow = matrix.cend();
std::size_t sum = 0;
for(auto row = firstRow; row != lastRow; ++row) {
auto firstColumn = row->cbegin();
auto lastColumn = row->cend();
for(auto column = firstColumn; column != lastColumn; ++column) {
if(std::distance(firstRow, row) == std::distance(firstColumn, column)) {
sum += *column;
}
}
}
return sum;
}
std::size_t calculateAntiDiagonalSum(const Matrix& matrix) {
auto firstRow = matrix.cbegin();
auto lastRow = matrix.cend();
std::size_t sum = 0;
for(auto row = firstRow; row != lastRow; ++row) {
auto firstColumn = row->crbegin();
auto lastColumn = row->crend();
for(auto column = firstColumn; column != lastColumn; ++column) {
if(std::distance(firstRow, row) == std::distance(firstColumn, column)) {
sum += *column;
}
}
}
return sum;
}
Packing into the function store.
static std::map<ComputationMode, std::function<int(const Matrix&)>> functionStore = {
{ComputationMode::MAIN_DIAGONAL_SUM, &calculateMainDiagonalSum},
{ComputationMode::ANTI_DIAGONAL_SUM, &calculateAntiDiagonalSum}
};
Base function for using the code above.
size_t computeMatrix(const Matrix& matrix, ComputationMode mode) {
size_t result = 0;
if(functionStore.find(mode) != functionStore.end()) {
result = functionStore[mode](matrix);
} else {
std::cerr << "Computation error. No proper computation function with this mode" << std::endl;
assert(false);
}
return result;
}
Example of the usage.
auto mainDiagonalSum = computeMatrix(matrix, ComputationMode::MAIN_DIAGONAL_SUM);
auto antiDiagonalSum = computeMatrix(matrix, ComputationMode::ANTI_DIAGONAL_SUM);
Full code is here.
Upvotes: 0
Reputation: 217283
There is already algorithm to accumulate, so you might do something like:
size_t diagonalSum(const Matrix& matrix, Diagonal diagonal) {
assert(isSquare(matrix));
std::size_t i = 0;
switch (diagonal) {
case Diagonal::MAIN:
return std::accumulate(matrix.cbegin(), matrix.cend(), 0u,
[&](std::size_t acc, const auto& row) {
return acc + row[i++];
});
case Diagonal::ANTI:
return std::accumulate(matrix.cbegin(), matrix.cend(), 0u,
[&](std::size_t acc, const auto& row) {
return acc + row[row.size() - i++];
});
}
}
Upvotes: 3