From 072eaf227624e35e21b6a688d69478cc4af6feae Mon Sep 17 00:00:00 2001 From: Syndamia Date: Fri, 12 Nov 2021 09:54:38 +0200 Subject: Added matrix calculator --- C/MatrixCalculator.c | 349 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 C/MatrixCalculator.c (limited to 'C') diff --git a/C/MatrixCalculator.c b/C/MatrixCalculator.c new file mode 100644 index 0000000..ecd9370 --- /dev/null +++ b/C/MatrixCalculator.c @@ -0,0 +1,349 @@ +/* + * SCROLL TO BOTTOM FOR DOCUMENTATION + */ + +#include // printf, scanf +#include // strcspn, strtok +#include // atoi, atof + +#define MAX_LINE_WIDTH 1024 +#define MATRIX_NUMBER_DELIMITER " " + +#define CMND_END "end" +#define CMND_PRINT_MATRIX "print" +#define CMND_PRINT_VARS "printv" +#define CMND_SWAP_ROWS "swap" +#define CMND_MULT_ROW "mult" +#define CMND_DIV_ROW "div" +#define CMND_SUM_ROW "sum" + +/* Matrix commands */ +void sumRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int swapVars, double vars[][matrixCols]); +void multRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int swapVars, double vars[][matrixCols]); +void divRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int swapVars, double vars[][matrixCols]); +void swapRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int swapVars, double vars[][matrixCols]); + +/* Arrays */ +void assignArrValues(int cols, double arrDest[], double arrSrc[]); +void multArrValues(int len, double arr[], double value); + +/* IO */ +void printMatrix(int mr, int mc, double matrix[][mc]); +void inputToMatrix(char inputBuffer[], int matrixRows, int matrixCols, double matrix[][matrixCols]); +void getInput(char inputBuffer[MAX_LINE_WIDTH]); + + +int main() { + /* + * Get matricies + */ + + int rows, cols, hasVars; + scanf("%d %d %d\n", &rows, &cols, &hasVars); + + double matrix[rows][cols]; + double vars[rows][cols]; + + char inputBuffer[MAX_LINE_WIDTH]; + + inputToMatrix(inputBuffer, rows, cols, matrix); + + if (hasVars) + inputToMatrix(inputBuffer, rows, cols, vars); + + /* + * Modify matricies + */ + + printf("Commands:\n"); + + char *command; + do { + getInput(inputBuffer); + command = strtok(inputBuffer, MATRIX_NUMBER_DELIMITER); + + if (!strcmp(inputBuffer, CMND_SWAP_ROWS)) + swapRows(command, rows, cols, matrix, hasVars, vars); + + else if (!strcmp(inputBuffer, CMND_MULT_ROW)) + multRows(command, rows, cols, matrix, hasVars, vars); + + else if (!strcmp(inputBuffer, CMND_DIV_ROW)) + divRows(command, rows, cols, matrix, hasVars, vars); + + else if (!strcmp(inputBuffer, CMND_SUM_ROW)) + sumRows(command, rows, cols, matrix, hasVars, vars); + + else if (!strcmp(inputBuffer, CMND_PRINT_MATRIX)) + printMatrix(rows, cols, matrix); + + else if (!strcmp(inputBuffer, CMND_PRINT_VARS)) + printMatrix(rows, cols, vars); + + } while (strcmp(inputBuffer, CMND_END) != 0); + + /* + * End print + */ + + printMatrix(rows, cols, matrix); + if (hasVars) + printMatrix(rows, cols, vars); +} + +/* + * Matrix commands + */ + +void sumRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int sumVars, double vars[][matrixCols]) { + /* Get input */ + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + int rowSrc = atoi(command) - 1; + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + int rowDst = atoi(command) - 1; + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + double mult = atof(command); + + double tmp[matrixCols]; + + /* Sum matrix rows */ + + assignArrValues(matrixCols, tmp, matrix[rowSrc]); + multArrValues(matrixCols, tmp, mult); + + for (int i = 0; i < matrixCols; i++) + matrix[rowDst][i] += tmp[i]; + + /* Sum var rows */ + + if (sumVars) { + assignArrValues(matrixCols, tmp, vars[rowSrc]); + multArrValues(matrixCols, tmp, mult); + + for (int i = 0; i < matrixCols; i++) + vars[rowDst][i] += tmp[i]; + } +} + +void multRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int multVars, double vars[][matrixCols]) { + /* Get input */ + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + int row = atoi(command) - 1; + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + double amount = atof(command); + + /* Multiply matrix row */ + + multArrValues(matrixCols, matrix[row], amount); + + /* Multiply var row */ + + if (multVars) + multArrValues(matrixCols, vars[row], amount); +} + +void divRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int divVars, double vars[][matrixCols]) { + /* Get input */ + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + int row = atoi(command) - 1; + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + double amount = atof(command); + + /* Divide matrix row */ + + multArrValues(matrixCols, matrix[row], 1.0/amount); + + /* Divide var row */ + + if (divVars) + multArrValues(matrixCols, vars[row], 1.0/amount); +} + +void swapRows(char *command, int matrixRows, int matrixCols, double matrix[][matrixCols], int swapVars, double vars[][matrixCols]) { + /* Get input */ + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + int row1 = atoi(command) - 1; + + command = strtok(NULL, MATRIX_NUMBER_DELIMITER); + int row2 = atoi(command) - 1; + + double tmp[matrixCols]; + + /* Swap matrix rows */ + + assignArrValues(matrixCols, tmp, matrix[row1]); + assignArrValues(matrixCols, matrix[row1], matrix[row2]); + assignArrValues(matrixCols, matrix[row2], tmp); + + /* Swap var rows */ + + if (swapVars) { + assignArrValues(matrixCols, tmp, vars[row1]); + assignArrValues(matrixCols, vars[row1], vars[row2]); + assignArrValues(matrixCols, vars[row2], tmp); + } +} + +/* + * Arrays + */ + +void assignArrValues(int len, double arrDest[], double arrSrc[]) { + for (int i = 0; i < len; i++) + arrDest[i] = arrSrc[i]; +} + +void multArrValues(int len, double arr[], double value) { + for (int i = 0; i < len; i++) + arr[i] *= value; +} + +/* + * IO + */ + +void printMatrix(int mr, int mc, double matrix[][mc]) { + for (int r = 0; r < mr; r++) { + /* Left bracket */ + + if (r == 0) printf("/"); + else if (r == mr - 1) printf("\\"); + else printf("|"); + + /* Middle values */ + + for (int c = 0; c < mc; c++) + printf(" %.3g ", matrix[r][c]); + + /* Right bracket */ + + if (r == 0) printf("\\"); + else if (r == mr - 1) printf("/"); + else printf("|"); + printf("\n"); + } +} + +void inputToMatrix(char inputBuffer[], int matrixRows, int matrixCols, double matrix[][matrixCols]) { + char *singleVal; + for (int r = 0; r < matrixRows; r++) { + /* Get input */ + + getInput(inputBuffer); + singleVal = strtok(inputBuffer, MATRIX_NUMBER_DELIMITER); + + /* Assign input to matrix */ + + for (int c = 0; c < matrixCols; c++) { + matrix[r][c] = atof(singleVal); + + singleVal = strtok(NULL, MATRIX_NUMBER_DELIMITER); + } + } +} + +void getInput(char inputBuffer[MAX_LINE_WIDTH]) { + fgets(inputBuffer, MAX_LINE_WIDTH, stdin); + inputBuffer[strcspn(inputBuffer, "\n")] = 0; // Removes trailing \n +} + +/* This is a small "calculator" for matricies. You type in the values of your matricies, then what actions to do with the rows and finally you'll get your calculated result. + * If your matrix uses variables alongside numbers, you can use the "var" matrix, which will calculate the result for each variable separately + * + * All inputs must be separated by spaces! + * First input should be three numbers: amount of rows, amount of columns and whether to use the var matrix (0 for "don't use it", anything else for "use it"). + * After that you type in the values of your matricies, each number separated by a space and each line separated by a newline. + * + * All rows are indexed from 1! So, if you have 3 rows, the first one is at "index" 1 (index when typing in command) + * + * Then you can do the commands. There are 7 different ones in total: + * - end : ends the app (and prints the matricies) + * - print : prints the normal matrix + * - printv : prints the var matrix + * - swap : swaps the values between two rows + * - mult : multiplies a row by a given number (and saves that to the row) + * - div divisor : divides a row by a given number (and saves that to the row) + * - sum : multiplies a row by a given number (without modifying it) and adds it to another row (sample usage: multiply first row by 1 and sum that to the 3rd row: sum 1 2 1) + + * Sample usage (what gets typed and what gets outputted): + * (Stuff that are typed in by the use start with ** in the examples) + * + * I. No vars + * + * Matrix in task looks like: + * / 1 -1 0 -1 \ + * | 2 -4 2 10 | + * \ -1 1 1 5 / + * +** 3 4 0 +** 1 -1 0 -1 +** 2 -4 2 10 +** -1 1 1 5 + * Commands: +** div 2 2 +** swap 1 2 +** sum 1 2 -1 +** print + * / 1 -2 1 5 \ + * | 0 1 -1 -6 | + * \ -1 1 1 5 / +** sum 1 3 1 +** sum 2 3 1 +** end + * / 1 -2 1 5 \ + * | 0 1 -1 -6 | + * \ 0 0 1 4 / + * + * (I'm too lazy to implement a system for aligning the numbers properly) + * + * I. With vars + * + * Matrix in task looks like: + * / 1 -1 0 -1 \ + * | 2 -4 2*p 10*q | + * \ -1 1 1 5 / + * +** 3 4 1 +** 1 -1 0 -1 +** 2 -4 2 10 +** -1 1 1 5 +** 0 0 0 0 +** 0 0 1 1 +** 0 0 0 0 + * Commands: +** div 2 2 +** swap 1 2 +** sum 1 2 -1 +** print + * / 1 -2 1 5 \ + * | 0 1 -1 -6 | + * \ -1 1 1 5 / +** printv + * / 0 0 0.5 0.5 \ + * | 0 0 -0.5 -0.5 | + * \ 0 0 0 0 / +** sum 1 3 1 +** sum 2 3 1 +** end + * / 1 -2 1 5 \ + * | 0 1 -1 -6 | + * \ 0 0 1 4 / + * / 0 0 0.5 0.5 \ + * | 0 0 -0.5 -0.5 | + * \ 0 0 0 0 / + * + * You'll have to add the first value from normal matrix to the value of var matrix * variable + * So, the proper result looks something like: + * / 1 -2 1+0.5*p 5+0.5*q \ + * | 0 1 -1-0.5*p -6-0.5*q | + * \ 0 0 1 4 / + * (I'm too lazy to implement this type of printing) + */ -- cgit v1.2.3