Advertisement
Guest User

Untitled

a guest
Jun 27th, 2016
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.97 KB | None | 0 0
  1. /*Find the determinant of any matrix of any size
  2. -Split every matrix to a lower-in-size ones and so on until reach the 2x2 matrices
  3. then find the determinant of each 2x2 matrix, multiply them by the required elements from higher-in-size matrices,
  4. add them according to a special algorithm that obeys the proper signs of each.
  5.  
  6. -pros: very smart and special way to develop programmatically, it may be used as a part of other analysis/hacking purposes for matrices components
  7. -Two big cons: it consumes a lot of time and memory for matrices of size higher than 8x8.
  8.  
  9. Author: @Yahya Almardeny
  10. 21/06/2016
  11. */
  12.  
  13. #include<stdio.h>
  14. #include<string.h>
  15. #include<stdlib.h>
  16.  
  17.  
  18.  
  19.  
  20.  
  21. int COL; // the size of the matrix inserted by the user
  22.  
  23. void split_matrix(int *matrix[COL]);
  24. void create_array(int dimension);
  25. void free_array(int *input_matrix[COL]);
  26. void remove_unwanted_elements(int number_of_elements);
  27. void copy_container_to_input_matrix(int size_of_matrix );
  28. void receive_input_for_first_time();
  29. void number_of_matrices_to_split_fun();
  30. void pick_up_required_elements();
  31. void change_container_to_2in2_determinants();
  32. void process_determinant();
  33. void find_2in2_determinant(); // if the user chose 2in2 matrix from the beginning!
  34. int receive_and_validate_input ();
  35.  
  36. int **input_matrix; // 2D Dynamic array which receives the user input then will be used for splitting
  37. int *container; // dynamic array which will contain all results before it changes to determinants of 2in2 matrices
  38. int *pick_up_array; // dynamic array to pick up required elements for calculating the determinant
  39.  
  40. int copy_variable; // to copy from container to input_matrix
  41. int container_index; // index for the current position & size of the array "container"
  42. int print_var; // for printing purpose , for the container
  43. int number_of_matrices_to_split; // specifies how many matrices will be split
  44. int COL_value; // because COL is changing , this is to be used as the original value of COL in later functions
  45. int number_of_2in2_elements; // will be used to estimate the maximum size of the container to be created
  46. int pick_up_index; // determines the index in the pick_up_array while picking up the required elements
  47. int determinant; // the final answer: the determinant
  48.  
  49. typedef enum{// create boolean type
  50. TRUE,
  51. FALSE
  52. }boolean;
  53. boolean start_from_index_zero; // to inform that the splitter should copy itself into index zero in the destination container
  54. boolean first_time_to_copy; // to start from index 0 when the copy_container_to_input_matrix() function executes
  55. boolean first_split; // global boolean variable to control the first time of thee function number_of_matrices_to_split()
  56. boolean first_pick_up; // global boolean variable to control first pick up
  57.  
  58. int main(){
  59.  
  60. //take the input
  61. printf("Please Insert the Size of the Matrix (e.g insert 3 for 3x3 matrix) : "); COL = receive_and_validate_input(1); // passing 1 in the receive_and_validate_input() activates rejecting the negative values
  62. /*if user wants to know the determinant of 2in2 matrix, no need for all of this hard work, it can be calculated easily!*/
  63. if (COL ==2 ){find_2in2_determinant();
  64. printf("**************************\n");
  65. printf("The determinant is: %d\n" , determinant);
  66. printf("**************************\n");
  67. }
  68.  
  69. /*if user chose a matrix of size greater than 2 then do the hard work*/
  70. else{
  71.  
  72. int x, y ,start_var = 3; //start from the 3*3 matrices
  73. long elements =4; // the size of 2*2 matrices inside every 3*3 matrix
  74. pick_up_index = 0;
  75.  
  76. /*estimate how many elements inside the entire-produced 2in2 matrices to be used to determine the size of the container*/
  77. while (start_var<=COL){
  78. elements = elements * start_var;
  79. start_var++;
  80. }
  81. number_of_2in2_elements = elements-1; // we subtract 1 because container starts from index 0 and "number_of_2in2_elements" will be used in such calculations later
  82. elements = elements + (elements*0.75); //to include the 2*2 matrices & the 3*3 matrices
  83.  
  84. container = calloc((elements) , sizeof(int)); // create the array "container" of size elements
  85. if (container == NULL || container == 0){printf("***Failure, Either you chose a high matrix size that your computer cannot provide\
  86. enough memory for or There is no enough memory to execute****\n"); exit(0);}
  87.  
  88. COL_value =COL;// because COL is changing , this is to be used as the original value of COL in later functions
  89. int move_to_next_dimenssion = (COL-3); // because there is no splitting from level 2 to 1 and from 1 to 0! thus subtract 3
  90.  
  91.  
  92. first_split = TRUE; // for number_of_matrices_to_split_fun() , to inform that it is the first time/round
  93. number_of_matrices_to_split_fun();
  94. first_time_to_copy = TRUE;
  95. receive_input_for_first_time();
  96.  
  97. /*the main work and flow in high level of details*/
  98. for(x = 0 ; x < move_to_next_dimenssion; x++ ){
  99.  
  100. printf("***************\n");
  101. printf ("%din%d Matrices:\n" , COL-1, COL-1);
  102. printf("***************\n");
  103.  
  104. for (y= 0 ; y < number_of_matrices_to_split; y++){
  105. create_array(COL);
  106. copy_container_to_input_matrix(COL);
  107. pick_up_required_elements();
  108. split_matrix(input_matrix);
  109. free_array(input_matrix);
  110. }
  111.  
  112. number_of_matrices_to_split_fun(); //function to determine how many matrices to be split then used in this loop (i.e. number_of_matrices_to_split)
  113. COL--;
  114. remove_unwanted_elements(copy_variable); // just to save memory, thus we do not need to create a bigger container in the beginning of this program
  115.  
  116. }
  117.  
  118. change_container_to_2in2_determinants();
  119. process_determinant();
  120. printf("**************************\n");
  121. printf("The determinant is: %d\n" , determinant);
  122. printf("**************************\n");
  123.  
  124. /*free arrays container and pick_up_array*/
  125. free(container);
  126. free(pick_up_array);
  127. }
  128.  
  129. getchar();
  130.  
  131. return 0;}
  132.  
  133.  
  134.  
  135. void split_matrix(int *matrix[COL]){ // this function to split the passed matrix into a lower one in size and print it out in like-look matrix appearance
  136.  
  137. int break_line = 1, newline_reference , newline_index =1;
  138. int row1, col1 , row , col , x ,y, unwanted_col;
  139. int ***splitter; // 3D array to be used in splitting the received matrix
  140. splitter = calloc(COL , sizeof(int**)); // the first dimension will guide how to split the matrix
  141. for (x=0 ; x <(COL); x++){splitter[x] = calloc((COL-1) , sizeof(int *)); // the second & third dimensions should be of the same size of the matrix will be produced
  142. for (y=0 ; y <(COL-1) ; y++){splitter[x][y] = calloc((COL-1) , sizeof(int));}} //this is why it's COL-1 , to be smaller in on level
  143.  
  144. if (splitter == NULL){printf("Failed To Split"); exit(0);} // inform failure to create the splitter
  145. /*even it contains 3 for loops but it finishes a group of matrices in every big round*/
  146. for (x =0, unwanted_col = 0 ; x < COL ; x++ , unwanted_col++){ // loop according to the first dimension of the splitter which is the same of the original(passed) matrix, with every loop there is unwanted column should be ignored( i.e. first loop is the first m second loop is the second and so on)
  147. for (row = 0 , row1=0; row1 < COL ; row1++ ){// will loop the matrix row /*here we finish all the columns in every row i.e. row row*/
  148. for (col=0, col1 =0; col1 < COL; col1++){ // will loop the matrix column /* here we move from column to another in every loop, once we finish them all , we move to the next row
  149. if (row1!=0 && col1 !=unwanted_col){ // we always don't want the first row of the passed matrix , but the column should follow the unwanted_col which changes in every big loop for the entire matrix
  150. splitter[x][row][col]= matrix[row1][col1]; // if it is not the first row and not the unwanted column then assign it to splitter
  151. col++; // after receiving the first col from the matrix, move to the next col in the splitter to receive the next column
  152. if (col == (COL-1)){row++;}// as we should move to next row in the splitter after we go through all the required column, we now this because the split matrix is of size (COL-1inCOL-1)
  153.  
  154. }
  155. }
  156. }
  157. }
  158.  
  159.  
  160.  
  161. // copy to the container
  162. if (start_from_index_zero == TRUE) // this is true if the "receive_input_for_first_time()" function is executed
  163. {container_index =0; print_var = 0;
  164. newline_reference = COL-1; /*this will determine when to make a new line, it will be a reference to the newline_index*/
  165. }
  166. for (x = 0 ; x <COL ; x++ ){
  167. for (row = 0 ; row <COL-1 ; row++ ){
  168. for (col = 0 ; col <COL-1 ; col++, container_index++){
  169. container[container_index] = splitter[x][row][col];// container_index will accumulate after this round i.e. when start_from_index_zero becomes false
  170. }
  171. }
  172. }
  173.  
  174. newline_reference = COL-1; // because we moved to a lower dimension, the matrix to be printed is smaller now, this executes before the COL-- in the main function!
  175. while (print_var != container_index){ // this while loop just for printing purpose , it will print out all non-printed elements, the reference is container_index
  176. printf("%d ", container[print_var]); //print the element
  177. print_var++; // then increment print_var to print the next element in the second round/loop
  178. if (newline_index == newline_reference){ // newline_reference is the column size of the matrix, it is fixed in every round but changes when the matrix changes its size in the main function
  179. printf("\n"); newline_index =0; // break the line and recount again
  180. }
  181. if(break_line == (newline_reference*newline_reference)) {printf("\n"); break_line=0;} // this determines when the the entire matrix has been printed start to start a new one
  182. break_line++; newline_index++; }
  183.  
  184.  
  185.  
  186. /*free the array "Splitter"*/
  187. for (x=0 ; x <(COL); x++){
  188. for (y=0 ; y <(COL-1) ; y++){free(splitter[x][y]);} free(splitter[x]);}
  189. free(splitter);
  190. }
  191.  
  192.  
  193.  
  194. void create_array(int dimension){ // create 2D dynamic array based on the dimension of the required input_matrix
  195. int row_input, col_input;
  196. input_matrix = (int**) calloc(dimension, sizeof(int*));
  197. for(col_input = 0 ; col_input<dimension ; col_input++){input_matrix[col_input] = (int*)calloc(dimension, sizeof(int));}
  198. if (input_matrix == NULL){printf("Failed To Create Input_Matrix\n");}
  199. }
  200.  
  201.  
  202.  
  203.  
  204. void free_array(int *input_matrix[COL]){//simply free the input_matrix after each use, that will be controlled by in the main function
  205. int x;
  206. for (x=0 ; x<(COL-1) ; x++){free(input_matrix[x]);}
  207. free(input_matrix);
  208. }
  209.  
  210.  
  211.  
  212.  
  213. void receive_input_for_first_time(){
  214.  
  215. start_from_index_zero = TRUE; // to make the splitter start copying itself to the container into the index zero
  216. create_array(COL); // create an array of size "COL" (i.e. column specified by the user)
  217. printf("\nNow Please Insert the Elements of the Matrix , Row by Row\n");
  218. int row_input, col_input; // variables to loop through while receiving the matrix
  219. for (row_input = 0; row_input<COL ; row_input++){
  220. for (col_input=0; col_input<COL; col_input++){
  221. printf("Row %d Column %d: ",row_input+1 ,col_input+1);
  222. input_matrix[row_input][col_input]=receive_and_validate_input (2);// this function receive input and validate it then return the validated integer/input
  223. // passing two activates accepting negative values/integers
  224. printf("-------------------\n");
  225. }
  226. }
  227. printf("\n***************\n");
  228. printf ("%din%d Matrices:\n" , COL-1, COL-1);
  229. printf("***************\n");
  230. split_matrix(input_matrix);//split the matrix already received for the first time
  231. first_pick_up = TRUE; // change it to true to activate the first option of pick_up_required_elements();
  232. pick_up_required_elements(); // to collect the first row of the original matrix/input
  233. free_array(input_matrix); // free it to use it again in later functions
  234. COL--; // decrement the col because we move now to the next-lower dimension/size of the matrix
  235. start_from_index_zero = FALSE; //inform the container to accumulate the container_index , it won't start from zero again.
  236. first_time_to_copy = FALSE; // to inform copy_container_to_input_matrix() in the main function to accumulate the copy_variable, it won't start from zero again.
  237.  
  238. }
  239.  
  240.  
  241.  
  242.  
  243.  
  244. void copy_container_to_input_matrix(int size_of_matrix ){ //determined by the size of the matrix according to the column size
  245.  
  246. if ((first_time_to_copy == TRUE)){copy_variable =0;} // if it is first time to copy , it should start form index zero
  247. // otherwise it will continue to accumulate copy_variable
  248. int row_input , col_input;
  249. for (row_input = 0; row_input<size_of_matrix ; row_input++){
  250. for (col_input=0; col_input<size_of_matrix; col_input++, copy_variable++ ){
  251. input_matrix[row_input][col_input] = container[copy_variable]; // copy the container to the input_matrix every time based on the size
  252.  
  253. }
  254. }
  255.  
  256. }
  257.  
  258.  
  259.  
  260.  
  261. void number_of_matrices_to_split_fun(){// determines number of matrices to split
  262. if (first_split == TRUE){
  263. number_of_matrices_to_split = COL; // first time it is the column size for sure , it is controlled by a boolean variable to execute only once
  264. first_split = FALSE;
  265. }
  266. else{number_of_matrices_to_split = number_of_matrices_to_split * COL;} //then it increments according to the new Column value (i.e. new matrix size)
  267. // e.g 5in5 matrix has 5 4in4 matrices and then each 4in4 has 4 3in3 matrices , totally: 5*4 = 20 3in3 matrices
  268. }
  269.  
  270.  
  271.  
  272.  
  273. void remove_unwanted_elements(int number_of_elements){
  274. int x, y=0 ;
  275. x = number_of_elements;
  276. while (x!=container_index){// index represent the current size of the array "container"
  277. container[y]=container[x]; // this way only copies the required elements over th unwanted elements
  278. x++;
  279. y++;
  280. }
  281.  
  282. container_index = (container_index - copy_variable); //subtract the current size of the container from the current index value of the copy_container_to_input_matrix represented by copy_variable
  283. // the container_index will have a value of the real-current size of the new container
  284. copy_variable = 0;// make it zero because it will start over form the index zero while copying from container to input_matrix
  285. print_var = container_index;//just for printing purpose, change print_var to size of container as it represents the upper limit for printing out the container content
  286.  
  287. }
  288.  
  289.  
  290. void pick_up_required_elements(){
  291. int i = 3 ,x , no_of_elements_to_save = 1, change_sign = 1;// change_sign variable to control the sings of the elements, it always starts as positive
  292.  
  293. if (first_pick_up == TRUE){ // boolean variable to create dynamic array for the first time only, it will be activated in receive_input_for_first_time();
  294. if (COL_value ==3){no_of_elements_to_save=3;}
  295. else {
  296. while (i<COL_value){// a way to know how many elements will be saved in the pick_up_array
  297. if (i==3){no_of_elements_to_save = (no_of_elements_to_save * (i * (i+1)));}
  298.  
  299. else{no_of_elements_to_save = (no_of_elements_to_save * (i+1));}
  300.  
  301. no_of_elements_to_save = no_of_elements_to_save + (i+1);
  302. i++;
  303. }
  304. }
  305.  
  306. pick_up_array = (int*) calloc(no_of_elements_to_save , sizeof(int));
  307. if (pick_up_array == NULL) {printf("fail"); exit(0);}
  308.  
  309. first_pick_up = FALSE;}
  310.  
  311.  
  312. for (x = 0 ; x < COL ; x++, pick_up_index++ ){ // we need to pick up only the first row of every matrix, that can be controlled by the COL value which changes in the main function loop
  313. pick_up_array[pick_up_index] = (input_matrix[0][x] * change_sign); // pick up required elements and change the signs properly, first row only
  314. change_sign = change_sign * (-1);
  315. }
  316. }
  317.  
  318.  
  319.  
  320.  
  321.  
  322. void change_container_to_2in2_determinants(){
  323. int x, y;
  324. for (x=0 ,y =0; x<=number_of_2in2_elements; x=x+4 , y++){// jump over every 4 elements in every loop because the 2in2 matrix size 4 elements(i.e. to move to next 2in2 matrix)
  325. container[y] = ((container[x]*container[x+3])-(container[x+1]*container[x+2])); // y controls the index of the container to make them followed right after each other
  326. }
  327. number_of_2in2_elements = y; // change the number_of_2in2_elements to the real new one because it has become smaller
  328. }
  329.  
  330.  
  331.  
  332. void process_determinant(){ // a way to multiply the elements in each level by the elements in the next lower level
  333. int z =0, x , i=COL_value , y=0 , j =0, limit, col_size = (COL_value-1); // limit starts with the size of the first row of the main matrix
  334. for (y = 0 ,limit = COL_value; y <(COL_value-3) ; y++){
  335. while (j!=limit){
  336. for(x =0 ; x <col_size ; x++ , i++){
  337. pick_up_array[i] = pick_up_array[i] * pick_up_array[z]; //multiply the first row in the main matrix with the first row in the next lower level
  338.  
  339. }
  340. j++;// j here to stop while loop when it equals to the limit
  341. z++;
  342. }
  343.  
  344. limit = limit * col_size ; // then limit increases according to the size of the new matrix e.g. 4in4 matrix has 4 3in3 matrices (12 elements to cycle through)
  345. col_size--; // decrement the size of the col for the next-lower level
  346. j=0;//start while loop again from zero to count how many loop to do
  347. }
  348.  
  349. i--; // decrement i because the array in general start with index 0 , and i here should represent the final index
  350.  
  351. for (x =(number_of_2in2_elements-1); x >=0 ; x-- , i--){
  352. container[x] = (container[x]) * (pick_up_array[i]); //multiply the 2in2_determinants in the container by the pick_up_elements
  353. }
  354.  
  355.  
  356. for (x =0 ; x <number_of_2in2_elements ; x++ ){
  357. determinant = determinant + container[x]; // add all the elements to find the determinant
  358. }
  359. }
  360.  
  361.  
  362. int receive_and_validate_input (int x){ // function that receives and validates the user input and returns the validated user input to pass it to the input_matrix
  363.  
  364.  
  365. int validated_input; // the value to be returned
  366. int y=0; //loop variable
  367. while (y<5){
  368. boolean reject_input= FALSE; // to determine if the user inserted a negative value to be a size of the matrix
  369. int returned_value =-1;
  370. char line[256];
  371. char *line_pointer = &line[0];
  372. char *p_new = &line[0];
  373. char *p_old = &line[0];
  374. if (fgets(line, sizeof(line), stdin)){//return 0 if not execute
  375. /*first remove spaces from the entire string*/
  376. while (*p_old != '\0'){// loop as long as has not reached the end of string
  377. *p_new = *p_old; // assign the current value the *line is pointing at to p
  378. if (*p_new != ' '){p_new++;} // check if it is not a space , if so , increment p
  379. p_old++;// increment p_old in every loop
  380. }
  381. *p_new = '\0'; // add terminator
  382.  
  383. /* check if the first char is (-) or (+) sign to point to next place*/
  384. if (x==1){
  385. if (*line_pointer== '+'){line_pointer++;}
  386. if (*line_pointer == '-'){reject_input = TRUE; returned_value = 2;} // because it is a negative number and the size of matrix must be positive
  387. }
  388. if (x==2){
  389. if (*line_pointer== '+' || *line_pointer == '-'){line_pointer++;}
  390. }
  391.  
  392. while (*line_pointer != '\n' && reject_input == FALSE){
  393. if (!(isdigit(*line_pointer))) {returned_value = 0; break;} // Illegal char found , will return 0 and stop because isdigit() returns 0 if the it finds non-digit
  394. else if (isdigit(*line_pointer)){line_pointer++; returned_value=1;}//check next place and increment returned_value for the final result and judgment next.
  395. /*it will return -1 if there is no input at all because while loop has not executed, will return >0 if successful, 0 if invalid input , 2 if negative number inserted*/
  396. }
  397.  
  398.  
  399.  
  400. if (returned_value==1){ // check if the string contains only numbers
  401. validated_input =strtol(line, NULL, 10); // change the authentic string to long and assign it
  402. if (x==1){
  403. if (validated_input == 0 || validated_input ==1){printf("Invalid Input, Insert 2 or greater!\n");}
  404. else {break;}
  405. }
  406. else if (x==2){
  407. {break;}
  408. }
  409. }
  410. else if (returned_value==0){printf("Invalid Input, Insert Integers Only!\n");}
  411. else if (returned_value==2){printf("Insert Positive Integers Only!\n");}
  412. else if (returned_value==-1){printf("Empty Input!\n ");}
  413.  
  414. }
  415.  
  416. y++;
  417. if (y==5){printf("****Failure to receive any valid input, No More Retries****\n"); getchar(); exit(0);}
  418. }
  419. return validated_input;
  420.  
  421.  
  422. }
  423.  
  424.  
  425.  
  426. void find_2in2_determinant(){
  427. create_array(COL); // create an array of size "COL" (i.e. column specified by the user)
  428. printf("\nNow Please Insert the Elements of the Matrix , Row by Row\n");
  429. int row_input, col_input; // variables to loop through while receiving the matrix
  430. for (row_input = 0; row_input<COL ; row_input++){
  431. for (col_input=0; col_input<COL; col_input++){
  432. printf("Row %d Column %d: ",row_input+1 ,col_input+1);
  433. input_matrix[row_input][col_input]=receive_and_validate_input (2);// this function receive input and validate it then return the validated integer/input
  434. // passing two activates accepting negative values/integers
  435. printf("-------------------\n");
  436. }
  437. }
  438. determinant = ((input_matrix[0][0]*input_matrix[1][1]) - (input_matrix[0][1]*input_matrix[1][0]));
  439. free_array(input_matrix);
  440. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement