diff options
feat(Week08): Add solutions
16 files changed, 622 insertions, 0 deletions
| -rw-r--r-- | Week08/Exercise01.cpp | 29 | ||||
| -rw-r--r-- | Week08/Exercise02.cpp | 28 | ||||
| -rw-r--r-- | Week08/Exercise03.cpp | 48 | ||||
| -rw-r--r-- | Week08/Exercise04.cpp | 56 | ||||
| -rw-r--r-- | Week08/Exercise05.cpp | 53 | ||||
| -rw-r--r-- | Week08/Exercise06.cpp | 40 | ||||
| -rw-r--r-- | Week08/Exercise07.cpp | 45 | ||||
| -rw-r--r-- | Week08/Exercise08.cpp | 39 | ||||
| -rw-r--r-- | Week08/Exercise09.cpp | 36 | ||||
| -rw-r--r-- | Week08/Exercise10.cpp | 23 | ||||
| -rw-r--r-- | Week08/Exercise11.cpp | 65 | ||||
| -rw-r--r-- | Week08/Exercise12.cpp | 53 | ||||
| -rw-r--r-- | Week08/Exercise13.cpp | 31 | ||||
| -rw-r--r-- | Week08/Exercise14.cpp | 25 | ||||
| -rw-r--r-- | Week08/Exercise15.cpp | 48 | ||||
| -rw-r--r-- | Week08/README.md | 3 |
diff --git a/Week08/Exercise01.cpp b/Week08/Exercise01.cpp new file mode 100644 index 0000000..3052799 --- /dev/null +++ b/Week08/Exercise01.cpp @@ -0,0 +1,29 @@ +#include <iostream> + +/* Тази задача може да се реши без матрици. + * Все пак идеята е да упражним точно тях. + */ + +int main() { + const unsigned int SIZE = 5; + int mat[SIZE][SIZE]; + + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + std::cin >> mat[i][j]; + + unsigned int countZeroes = 0; + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + countZeroes += mat[i][j] == 0; + + /* Бройката нули е повече от бройката на всички елементи които не са нули. + * Алтернативно, може и да се пази втори брояч за ненулеви елементи. + */ + if (countZeroes > SIZE * SIZE - countZeroes) + std::cout << "Sparse" << std::endl; + else + std::cout << "Not sparse" << std::endl; + + return 0; +} diff --git a/Week08/Exercise02.cpp b/Week08/Exercise02.cpp new file mode 100644 index 0000000..34752c5 --- /dev/null +++ b/Week08/Exercise02.cpp @@ -0,0 +1,28 @@ +#include <iostream> + +void rowSum(const unsigned int* matrix, unsigned int rows, unsigned int cols, unsigned int* sum) { + for (unsigned int row = 0; row < rows; row++) + for (unsigned int col = 0; col < cols; col++) + /* За повече информация защо така индексираме в matrix, вижте + * https://syndamia.com/teaching/upp-2025/cpp-pitfalls/#-int73-vs-int3-vs-int + */ + sum[col] += matrix[row * cols + col]; +} + +int main() { + const unsigned int ROWS = 7, COLS = 3; + unsigned int mat[ROWS][COLS]; + + for (unsigned int i = 0; i < ROWS; i++) + for (unsigned int j = 0; j < COLS; j++) + std::cin >> mat[i][j]; + + unsigned int sum[COLS] = { 0 }; + rowSum((const unsigned int*)mat, ROWS, COLS, sum); + + for (unsigned int col = 0; col < COLS; col++) + std::cout << sum[col] << ' '; + std::cout << std::endl; + + return 0; +} diff --git a/Week08/Exercise03.cpp b/Week08/Exercise03.cpp new file mode 100644 index 0000000..7badee5 --- /dev/null +++ b/Week08/Exercise03.cpp @@ -0,0 +1,48 @@ +#include <iostream> + +void subMatrix(const double* inmat, unsigned int inRows, unsigned int inCols, + double* outmat, unsigned int outRows, unsigned int outCols) +{ + for (unsigned int row = 0; row < outRows; row++) + for (unsigned int col = 0; col < outCols; col++) + /* За повече информация защо така индексираме в матриците, вижте + * https://syndamia.com/teaching/upp-2025/cpp-pitfalls/#-int73-vs-int3-vs-int + */ + outmat[row * inCols + col] = inmat[row * inCols + col]; +} + +int main() { + const unsigned int ROWS = 6, COLS = 6; + double mat[ROWS][COLS]; + + for (unsigned int i = 0; i < ROWS; i++) + for (unsigned int j = 0; j < COLS; j++) + std::cin >> mat[i][j]; + + unsigned int startRow, startCol, rows, cols; + std::cin >> startCol >> startRow >> cols >> rows; + + double submat[ROWS][COLS] = { 0 }; + /* По условие се иска функцията да попълва елементите от горния ляв ъгъл на матрицата. + * Това означава, че трябва да променим горния ляв ъгъл къде е (т.е. да съответства + * на елемента на началните позиции). + * + * Един лош ефект от това е, че подадените размери (особено броя колони) на входната + * матрица са спрямо цялата матрица, не подматрицата която искаме. + * Тоест, на теория, функцията може да излезе извън паметта на матрицата, заради + * начина по който индексираме. + * + * Интересното е, че ако матрицата беше динамично заделена, това нямаше да е проблем. + * По тази тема ще говорим в бъдеще. + */ + subMatrix((const double*)mat + startRow * COLS + startCol, ROWS, COLS, + (double*)submat, rows, cols); + + for (unsigned int row = 0; row < rows; row++) { + for (unsigned int col = 0; col < cols; col++) + std::cout << submat[row][col] << ' '; + std::cout << std::endl; + } + + return 0; +} diff --git a/Week08/Exercise04.cpp b/Week08/Exercise04.cpp new file mode 100644 index 0000000..d779cd4 --- /dev/null +++ b/Week08/Exercise04.cpp @@ -0,0 +1,56 @@ +#include <iostream> + +const unsigned int SIZE = 5; + +/* counts масива съдържа бройката на всеки тип сграда в околност/съседство на тази на подадените индекси. + * counts[0] - бройка жилищни + * counts[1] - бройка търговски + * counts[2] - бройка офисни + * counts[3] - бройка луксозни + */ +void surroundingBuildings(const unsigned short mat[SIZE][SIZE], unsigned int row, unsigned int col, unsigned short counts[4]) { + for (unsigned int type = 0; type < 4; type++) + counts[type] = 0; + + /* Възползваме се от факта, че сградите ни се представят като числата от 1 до 4 вкл. + * Намаляйки с единица, те се превръщат в 0 до 3 вкл. и стават валидни индекси в counts. + */ + if (0 < row) counts[mat[row - 1][col] - 1]++; + if (row < SIZE - 1) counts[mat[row + 1][col] - 1]++; + if (0 < col) counts[mat[row][col - 1] - 1]++; + if (col < SIZE - 1) counts[mat[row][col + 1] - 1]++; +} + +int main() { + /* Изкушаващо е да спестим малко памет и да използваме unsigned char, обаче + * тогава std::cin ще вкарва стойностите като букви, не като числа. + * Реално, винаги можем да ги превърнем обратно в числовите им стойности, но + * така е по-лесно. + */ + unsigned short city[SIZE][SIZE]; + + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + std::cin >> city[i][j]; + + unsigned short surroundings[4] = { 0 }; + + bool valid = true; + for (unsigned int i = 0; i < SIZE && valid; i++) { + for (unsigned int j = 0; j < SIZE && valid; j++) { + surroundingBuildings(city, i, j, surroundings); + + valid = (city[i][j] == 1) || + (city[i][j] == 2 && surroundings[0] >= 1) || + (city[i][j] == 3 && surroundings[0] >= 1 && surroundings[1] >= 1) || + (city[i][j] == 4 && surroundings[0] >= 1 && surroundings[1] >= 1 && surroundings[2] >= 1); + } + } + + if (valid) + std::cout << "Valid" << std::endl; + else + std::cout << "Invalid" << std::endl; + + return 0; +} diff --git a/Week08/Exercise05.cpp b/Week08/Exercise05.cpp new file mode 100644 index 0000000..d046ee8 --- /dev/null +++ b/Week08/Exercise05.cpp @@ -0,0 +1,53 @@ +#include <iostream> + +const unsigned int SIZE = 3; + +void swap(int &a, int &b) { + int temp = a; + a = b; + b = temp; +} + +void transpose(int mat[SIZE][SIZE]) { + /* Има по-проста имплементация за матрица 3x3, но тази работи за всякакъв размер матрица. + * Каква е идеята: движим се по диагоналите над главния и разменяме елементите със съответния + * диагонал под главния. + * + * Ето така обикаляме, като числото показва използваната diagDist и плюсовете маркират главния диагонал: + * +1234 + * 1+123 + * 21+12 + * 321+1 + * 4321+ + * + * Би трябвало да е очевидно, че първия ред ще участва във всеки диагонал. + * Затова, почваме от елемента на първия ред, който участва в текущия диагонал, и от там + * увеличаваме реда и колоната на всяка итерация. + * + * Когато имаме позиция над главния диагонал, стигаме до тази под главния като просто + * разменим реда и колоната. + * + * Ако не разбирате някои от тези сметки/индексирания, просто си разпишете някой по-голям пример. + */ + for (unsigned int diagDist = 1; diagDist < SIZE; diagDist++) + for (unsigned int diagElem = 0; diagElem + diagDist < SIZE; diagElem++) + swap(mat[diagElem][diagElem + diagDist], mat[diagElem + diagDist][diagElem]); +} + +int main() { + int mat[SIZE][SIZE]; + + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + std::cin >> mat[i][j]; + + transpose(mat); + + for (unsigned int i = 0; i < SIZE; i++) { + for (unsigned int j = 0; j < SIZE; j++) + std::cout << mat[i][j] << ' '; + std::cout << std::endl; + } + + return 0; +} diff --git a/Week08/Exercise06.cpp b/Week08/Exercise06.cpp new file mode 100644 index 0000000..30ef172 --- /dev/null +++ b/Week08/Exercise06.cpp @@ -0,0 +1,40 @@ +#include <iostream> + +void swap(double &a, double &b) { + double temp = a; + a = b; + b = temp; +} + +void swapColumns(double* mat, unsigned int rows, unsigned int cols, unsigned int column1, unsigned int column2) { + if (column1 >= cols || column2 >= cols) + return; + + for (unsigned int row = 0; row < rows; row++) + /* За повече информация защо така индексираме в матриците, вижте + * https://syndamia.com/teaching/upp-2025/cpp-pitfalls/#-int73-vs-int3-vs-int + */ + swap(mat[row * cols + column1], mat[row * cols + column2]); +} + +int main() { + const unsigned int ROWS = 3, COLS = 5; + double mat[ROWS][COLS]; + + for (unsigned int i = 0; i < ROWS; i++) + for (unsigned int j = 0; j < COLS; j++) + std::cin >> mat[i][j]; + + unsigned int col1, col2; + std::cin >> col1 >> col2; + + swapColumns((double*)mat, ROWS, COLS, col1, col2); + + for (unsigned int row = 0; row < ROWS; row++) { + for (unsigned int col = 0; col < COLS; col++) + std::cout << mat[row][col] << ' '; + std::cout << std::endl; + } + + return 0; +} diff --git a/Week08/Exercise07.cpp b/Week08/Exercise07.cpp new file mode 100644 index 0000000..470b53e --- /dev/null +++ b/Week08/Exercise07.cpp @@ -0,0 +1,45 @@ +#include <iostream> + +const unsigned int SIZE_PAT = 3; + +bool matchesPattern(const char pattern[SIZE_PAT][SIZE_PAT], const char* input, unsigned int inputRows, unsigned int inputCols) { + for (unsigned int i = 0; i < SIZE_PAT; i++) { + for (unsigned int j = 0; j < SIZE_PAT; j++) { + /* За повече информация защо така индексираме в input, вижте + * https://syndamia.com/teaching/upp-2025/cpp-pitfalls/#-int73-vs-int3-vs-int + */ + if (pattern[i][j] != '*' && pattern[i][j] != input[i * inputRows + j]) + return false; + } + } + return true; +} + +int main() { + char pattern[SIZE_PAT][SIZE_PAT]; + + for (unsigned int i = 0; i < SIZE_PAT; i++) + for (unsigned int j = 0; j < SIZE_PAT; j++) + std::cin >> pattern[i][j]; + + const unsigned int SIZE = 6; + char inp[SIZE][SIZE]; + + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + std::cin >> inp[i][j]; + + unsigned int matches = 0; + for (unsigned int i = 0; i <= SIZE - SIZE_PAT; i++) { + for (unsigned int j = 0; j <= SIZE - SIZE_PAT; j++) { + /* За повече информация защо подаваме такива стойности на функцията, + * вижте решението на 3та задача. + */ + matches += matchesPattern(pattern, (const char*)inp + i * SIZE + j, SIZE, SIZE); + } + } + + std::cout << matches << std::endl; + + return 0; +} diff --git a/Week08/Exercise08.cpp b/Week08/Exercise08.cpp new file mode 100644 index 0000000..1baef7c --- /dev/null +++ b/Week08/Exercise08.cpp @@ -0,0 +1,39 @@ +#include <iostream> + +const unsigned int SIZE = 3; + +void inputMatrix(unsigned int mat[SIZE][SIZE]) { + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + std::cin >> mat[i][j]; +} + +unsigned int multiplyRowCol(const unsigned int matA[SIZE][SIZE], const unsigned int matB[SIZE][SIZE], unsigned int rowA, unsigned int colB) { + unsigned int result = 0; + for (unsigned int i = 0; i < SIZE; i++) + result += matA[rowA][i] * matB[i][colB]; + return result; +} + +void multiplyMatrices(const unsigned int matA[SIZE][SIZE], const unsigned int matB[SIZE][SIZE], unsigned int out[SIZE][SIZE]) { + for (unsigned int row = 0; row < SIZE; row++) + for (unsigned int col = 0; col < SIZE; col++) + out[row][col] = multiplyRowCol(matA, matB, row, col); +} + +int main() { + unsigned int matA[SIZE][SIZE], matB[SIZE][SIZE]; + inputMatrix(matA); + inputMatrix(matB); + + unsigned int mult[SIZE][SIZE]; + multiplyMatrices(matA, matB, mult); + + for (unsigned int row = 0; row < SIZE; row++) { + for (unsigned int col = 0; col < SIZE; col++) + std::cout << mult[row][col] << ' '; + std::cout << std::endl; + } + + return 0; +} diff --git a/Week08/Exercise09.cpp b/Week08/Exercise09.cpp new file mode 100644 index 0000000..4753903 --- /dev/null +++ b/Week08/Exercise09.cpp @@ -0,0 +1,36 @@ +#include <iostream> + +int main() { + const unsigned int ROWS = 4, COLS = 3; + char keypad[ROWS][COLS] = { + '1', '2', '3', + '4', '5', '6', + '7', '8', '9', + '*', '0', '#', + }; + + bool rowOn[ROWS]; + for (unsigned int i = 0; i < ROWS; i++) + std::cin >> rowOn[i]; + + bool colOn[COLS]; + for (unsigned int i = 0; i < COLS; i++) + std::cin >> colOn[i]; + + bool somethingPressed = false; + for (unsigned int row = 0; row < ROWS; row++) { + for (unsigned int col = 0; col < COLS; col++) { + if (rowOn[row] && colOn[col]) { + std::cout << keypad[row][col] << ' '; + somethingPressed = true; + } + } + } + + if (!somethingPressed) + std::cout << "Nothing pressed"; + + std::cout << std::endl; + + return 0; +} diff --git a/Week08/Exercise10.cpp b/Week08/Exercise10.cpp new file mode 100644 index 0000000..024d4c8 --- /dev/null +++ b/Week08/Exercise10.cpp @@ -0,0 +1,23 @@ +#include <iostream> + +int main() { + const unsigned int SIZE = 11; + unsigned int pascal[SIZE][SIZE] = { 0 }; + + for (unsigned int i = 0; i < SIZE; i++) + pascal[i][0] = pascal[i][i] = 1; + + for (unsigned int row = 2; row < SIZE; row++) + for (unsigned int col = 1; col < row; col++) + /* Елемента над и в ляво на текущия, сумирано с елемента над текущия. + */ + pascal[row][col] = pascal[row - 1][col - 1] + pascal[row - 1][col]; + + for (unsigned int row = 0; row < SIZE; row++) { + for (unsigned int col = 0; col < SIZE; col++) + std::cout << pascal[row][col] << ' '; + std::cout << std::endl; + } + + return 0; +} diff --git a/Week08/Exercise11.cpp b/Week08/Exercise11.cpp new file mode 100644 index 0000000..a2922bb --- /dev/null +++ b/Week08/Exercise11.cpp @@ -0,0 +1,65 @@ +#include <iostream> + +/* В това решение използваме int за размери, вместо unsigned int, защото + * правим изваждания, които се обработват по-лесно като можеш да имаш отрицателни числа. + * Може да се преработи с unsigned int (и окуражавам да го направите), но кода става + * по-досаден и грозен. + */ +const int SIZE = 10; + +int clamp(int value, int min, int max) { + if (value < min) return min; + if (value > max) return max; + return value; +} + +void sumCells(const unsigned int mat[SIZE][SIZE], + int startRow, int endRow, + int startCol, int endCol, + unsigned int &sum, unsigned int &count) +{ + startRow = clamp(startRow, 0, SIZE - 1); + endRow = clamp(endRow, 0, SIZE - 1); + startCol = clamp(startCol, 0, SIZE - 1); + endCol = clamp(endCol, 0, SIZE - 1); + + for (int row = startRow; row <= endRow; row++) { + for (int col = startCol; col <= endCol; col++) { + sum += mat[row][col]; + count++; + } + } +} + +double averageCells(const unsigned int mat[SIZE][SIZE], int row, int col, unsigned int radius) { + unsigned int sum = 0, sumCount = 0; + + sumCells(mat, row - radius, row + radius, col - radius, col + radius, sum, sumCount); + + return (double)sum / sumCount; +} + +int main() { + unsigned int mat[SIZE][SIZE]; + + for (int i = 0; i < SIZE; i++) + for (int j = 0; j < SIZE; j++) + std::cin >> mat[i][j]; + + unsigned int radius; + std::cin >> radius; + + double blurred[SIZE][SIZE] = { 0 }; + + for (int i = 0; i < SIZE; i++) + for (int j = 0; j < SIZE; j++) + blurred[i][j] = averageCells(mat, i, j, radius); + + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) + std::cout << blurred[i][j] << ' '; + std::cout << std::endl; + } + + return 0; +} diff --git a/Week08/Exercise12.cpp b/Week08/Exercise12.cpp new file mode 100644 index 0000000..acdc848 --- /dev/null +++ b/Week08/Exercise12.cpp @@ -0,0 +1,53 @@ +#include <iostream> + +const unsigned int SIZE = 10; +const double STEP = 0.001; + +void swap(double& a, double& b) { + double temp = a; + a = b; + b = temp; +} + +void fill(char mat[SIZE][SIZE], char filler) { + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + mat[i][j] = filler; +} + +int main() { + double startX, startY, endX, endY; + std::cin >> startX >> startY >> endX >> endY; + + char mat[SIZE][SIZE]; + fill(mat, ' '); + + /* Преместваме началната точка към крайната точка, следвайки отсечката. + * Все едно една мравка е започнала в началната точка и се движи върху правата, + * докато стигне крайната точка. + * + * Разменяме двете точки, защото правим изчислението все едно началната точка е + * в ляво от крайната. + */ + + if (startX > endX) { + swap(startX, endX); + swap(startY, endY); + } + + double dx = (endX - startX) * STEP, dy = (endY - startY) * STEP; + + while (startX < endX) { + mat[(int)startY][(int)startX] = 'x'; + startX += dx; + startY += dy; + } + + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) + std::cout << mat[i][j]; + std::cout << std::endl; + } + + return 0; +} diff --git a/Week08/Exercise13.cpp b/Week08/Exercise13.cpp new file mode 100644 index 0000000..71b530c --- /dev/null +++ b/Week08/Exercise13.cpp @@ -0,0 +1,31 @@ +#include <iostream> + +int main() { + const unsigned int SIZE = 8; + char mat[SIZE][SIZE]; + + for (unsigned int i = 0; i < SIZE; i++) + for (unsigned int j = 0; j < SIZE; j++) + std::cin >> mat[i][j]; + + int minRow = SIZE, maxRow = 0, minCol = SIZE, maxCol = 0; + for (unsigned int i = 0; i < SIZE; i++) { + for (unsigned int j = 0; j < SIZE; j++) { + if (mat[i][j] == '+') { + if (i < minCol) minCol = i; + if (i > maxCol) maxCol = i; + if (j < minRow) minRow = j; + if (j > maxRow) maxRow = j; + } + } + } + + if (minRow == SIZE) { + minRow = 1; + minCol = 1; + } + + std::cout << (maxCol - minCol + 1) << ' ' << (maxRow - minRow + 1) << std::endl; + + return 0; +} diff --git a/Week08/Exercise14.cpp b/Week08/Exercise14.cpp new file mode 100644 index 0000000..c224948 --- /dev/null +++ b/Week08/Exercise14.cpp @@ -0,0 +1,25 @@ +#include <iostream> + +int main() { + const unsigned int ROWS = 6, COLS = 3; + + double vec[ROWS]; + for (unsigned int i = 0; i < ROWS; i++) + std::cin >> vec[i]; + + double mat[ROWS][COLS]; + for (unsigned int i = 0; i < ROWS; i++) + for (unsigned int j = 0; j < COLS; j++) + std::cin >> mat[i][j]; + + double mult[COLS] = { 0.0 }; + for (unsigned int col = 0; col < COLS; col++) + for (unsigned int row = 0; row < ROWS; row++) + mult[col] += vec[row] * mat[row][col]; + + for (unsigned int i = 0; i < COLS; i++) + std::cout << mult[i] << ' '; + std::cout << std::endl; + + return 0; +} diff --git a/Week08/Exercise15.cpp b/Week08/Exercise15.cpp new file mode 100644 index 0000000..fba54ff --- /dev/null +++ b/Week08/Exercise15.cpp @@ -0,0 +1,48 @@ +#include <iostream> + +const int ROWS = 9, COLS = 7; + +int max(int a, int b) { + return a > b ? a : b; +} + +int min(int a, int b) { + return a < b ? a : b; +} + +double abs(double x) { + return x < 0 ? -x : x; +} + +bool checkSurroundingCells(const double mat[ROWS][COLS], int row, int col, double maxDiff) +{ + for (int r = max(0, row - 1); r <= min(ROWS - 1, row + 1); r++) { + for (int c = max(0, col - 1); c <= min(COLS - 1, col + 1); c++) { + if (abs(mat[r][c] - mat[row][col]) >= maxDiff) + return false; + } + } + return true; +} + +int main() { + double mat[ROWS][COLS]; + for (int i = 0; i < ROWS; i++) + for (int j = 0; j < COLS; j++) + std::cin >> mat[i][j]; + + double maxDiff; + std::cin >> maxDiff; + + bool smooth = true; + for (int i = 0; i < ROWS && smooth; i++) + for (int j = 0; j < COLS && smooth; j++) + smooth = checkSurroundingCells(mat, i, j, maxDiff); + + if (smooth) + std::cout << "Smooth" << std::endl; + else + std::cout << "Not smooth" << std::endl; + + return 0; +} diff --git a/Week08/README.md b/Week08/README.md new file mode 100644 index 0000000..c3816ec --- /dev/null +++ b/Week08/README.md @@ -0,0 +1,3 @@ +# Задачи + +<https://syndamia.com/teaching/upp-2025/week08/> |
