Reputation: 29
C - Void method count how many letters from the small matrix that also appear in the Big matrix WITHOUT using string.h
The Count()
Function needs to count the letters in the small matrix that appear in the large matrix by using POINTERS.
The result should be presented in a new Result matrix. The Result Matrix will have the same dimensions as the Small Matrix, but each cell will be an integer count representing the number of times that the letter from the Small Matrix appears in the Large Matrix.
I tried used pointer to a specific char in the small matrix.
void Count(char mat[ROWS][COLS], char smallMat[SIZE][SIZE]) {
int i, j;
int count = 0;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
const char stringptr = smallMat[i][j];
if (stringptr == mat[i][j])
count++;
}
}
return count;
}
The count should return main. This example of the 2 matrices and the new matrix should be
Big Matrix
P A D A Q E Q B G H R O P H C W S P B Q M B R P R N V S C H M U J P W C V M F D V W R K E V I Y K K Q Y N H N G V L B Z
Small Matrix
U N T E C P G X D L A B
Result Matrix
1 3 0 2 3 4 2 0 2 1 2 4
Upvotes: 2
Views: 471
Reputation: 2660
I would break it down into a count function that takes two args: the letter you are searching for and a pointer to the large matrix.
I would then create a result matrix with the same dimensions as the small matrix and call the count function for each cell of the result matrix, passing in the large matrix, and assigning the result for each count call to each successive cell of the result matrix.
Finally, to make the main() function clear, create a final function that will print a result matrix. Something like this:
Edited: I have editted the code according to the updates of the OP's question. This code creates the following output:
$> a.out
P A D A Q E Q B G H R O P H C W S P B Q
M B R P R N V S C H M U J P W C V M F D
V W R K E V I Y K K Q Y N H N G V L B Z
U N T E
C P G X
D L A B
1 3 0 2
3 5 2 0
2 1 2 4
The most repetitive char(s) occurred 5 time(s): P
The least repetitive char(s) occurred 1 time(s): U L
Process finished with exit code 0
The code prints all mins and all max chars for the highest and lowest frequency number. To do this, it keeps an array of max and mins. This array need be no longer than the product of the sides of the result matrix.
If no character occurs at least 1 time, then the max and min values will not be printed.
While the OP suggested that I update the Count() function to take care of searching for the most frequent letters, this really becomes complicated, particularly when you have more than one letter occurring the same number of times in the max slot of in the min slot.
So, I wrote a new function that utilizes the ResultMatrix. The ResultMatrix already contains the frequency counts. The Small Matrix tells us which letters are most frequent.
So, PrintMaxesAndMins()
uses the inputs from the ResultMatrix and the SmallMatrix (called Needlestack in my code).
The code could be optimized to find the min and max first before actually gathering the chars that correspond to the min and the chars that correspond to the min. Rather than do that, my code resets the string of max chars each time it realizes that a higher max has been found.
Here is the code:
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
const size_t ROWS = 3;
const size_t COLUMNS = 20;
const size_t SMALL_ROWS = 3;
const size_t SMALL_COLUMNS = 4;
const size_t SIZE = 4;
char LargeMatrix[ROWS][COLUMNS] =
{{'P', 'A', 'D', 'A', 'Q', 'E', 'Q', 'B', 'G', 'H', 'R', 'O', 'P', 'H', 'C',
'W', 'S', 'P', 'B', 'Q'},
{'M', 'B', 'R', 'P', 'R', 'N', 'V', 'S', 'C', 'H', 'M', 'U', 'J', 'P', 'W',
'C', 'V', 'M', 'F', 'D'},
{'V', 'W', 'R', 'K', 'E', 'V', 'I', 'Y', 'K', 'K', 'Q', 'Y', 'N', 'H', 'N',
'G', 'V', 'L', 'B', 'Z'},};
char SmallMatrix[SIZE][SIZE] =
{{'U', 'N', 'T', 'E'}, {'C', 'P', 'G', 'X'}, {'D', 'L', 'A', 'B'}};
void Count(char mat[ROWS][COLUMNS], char c, size_t *count)
{
size_t counter = 0; // Initialize the count answer cell
for (size_t i = 0; i < ROWS; i++) {
for (size_t j = 0; j < COLUMNS; j++) {
if (mat[i][j] == c)
counter++;
}
}
*count = counter;
}
// clear the char array
void zero_char_array(char *array, size_t len)
{
for (size_t i = 0; i < len; i++)
array[i] = 0;
}
//
//
void PrintMaxesAndMins(char haystack[ROWS][COLUMNS],
char needlestack[SMALL_ROWS][SMALL_COLUMNS],
size_t answerStack[SMALL_ROWS][SMALL_COLUMNS],
size_t result_rows,
size_t result_columns)
{
char max_char; // char that occurred the most
char min_char; // char that occurred the least
size_t max_char_count =
0; // best to use unsigned ints when a value should never go negative.
size_t min_char_count = UINT32_MAX; // Value should not go negative.
char max_chars[SMALL_COLUMNS * SMALL_ROWS]; // save all possible max chars
char *next_max_char;
char min_chars[SMALL_COLUMNS * SMALL_ROWS]; // sall all possible min chars
char *next_min_char;
size_t counter = 0; // Initialize the count answer cell
for (size_t i = 0; i < result_rows; i++) {
for (size_t j = 0; j < result_columns; j++) {
if (answerStack[i][j] > max_char_count) {
max_char_count = answerStack[i][j]; // we have a new max
zero_char_array(max_chars, SMALL_COLUMNS * SMALL_ROWS);
next_max_char =
max_chars; // We have a new max, reset result char array
*next_max_char = needlestack[i][j];// grab character from needle stack
++next_max_char; // increment. Could do in prior line, but try to be clear.
} else if (answerStack[i][j] >= max_char_count) {
// we are adding to an old max
*next_max_char = needlestack[i][j];// grab character from needle stack
++next_max_char; // increment. Could do in prior line, but try to be clear.
}
if (answerStack[i][j] > 0 && answerStack[i][j] < min_char_count) {
min_char_count = answerStack[i][j]; // we have a new min
zero_char_array(min_chars, SMALL_COLUMNS * SMALL_ROWS);
next_min_char =
min_chars; // We have a new min, reset result char array
*next_min_char = needlestack[i][j];// grab character from needle stack
++next_min_char; // increment. Could do in prior line, but try to be clear.
} else if (answerStack[i][j] > 0 && answerStack[i][j] <= min_char_count) {
// we are adding to an old max
*next_min_char = needlestack[i][j];// grab character from needle stack
++next_min_char; // increment. Could do in prior line, but try to be clear.
}
}
}
if (max_char_count > 0) {
printf("The most repetitive char(s) occurred %lu time(s): ", max_char_count);
next_max_char = max_chars;
while (*next_max_char)
printf(" %c", *next_max_char++);
}
printf("\n\n");
if (min_char_count > 0) {
printf("The least repetitive char(s) occurred %lu time(s): ", min_char_count);
next_min_char = min_chars;
while (*next_min_char) {
printf(" %c", *next_min_char++);
}
}
}
// BuildResultMatrix()
// haystack is a pointer to the large matrix.
// needlestack is a pointer to the small matrix.
// answerStack is the result matrix of size_t
void BuildResultMatrix(char haystack[ROWS][COLUMNS],
char needlestack[SMALL_ROWS][SMALL_COLUMNS],
size_t answerStack[SMALL_ROWS][SMALL_COLUMNS],
size_t result_rows,
size_t result_columns)
{
// Loop through the rows and columns of the small matrix
for (size_t i = 0; i < result_rows; i++) {
for (size_t j = 0; j < result_columns; j++) {
// Pass the current cell of the small matrix to Count()
// Count() will then loop through the large matrix, counting
// the number of cells with the current cell value from the small matrix.
// Count() will place the final count into the correpsonding cell of the
// answerStack matrix.
Count(LargeMatrix, needlestack[i][j], &answerStack[i][j]);
}
}
}
void PrintLargeCharMatrix(char (*matrix)[COLUMNS], size_t rows)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < COLUMNS; j++) {
printf("%c ", matrix[i][j]);
}
printf("\n");
}
printf("\n");
}
void PrintSmallCharMatrix(char (*matrix)[SMALL_COLUMNS], size_t rows)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < SMALL_COLUMNS; j++) {
printf("%c ", matrix[i][j]);
}
printf("\n");
}
printf("\n");
}
void PrintCountMatrix(size_t (*matrix)[SMALL_COLUMNS], size_t rows)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < SMALL_COLUMNS; j++) {
printf("%lu ", matrix[i][j]);
}
printf("\n");
}
printf("\n");
}
int main()
{
size_t ResultMatrix[SMALL_ROWS][SMALL_COLUMNS];
PrintLargeCharMatrix(LargeMatrix, ROWS);
PrintSmallCharMatrix(SmallMatrix, SMALL_ROWS);
BuildResultMatrix(LargeMatrix,
SmallMatrix,
ResultMatrix,
SMALL_ROWS,
SMALL_COLUMNS);
PrintCountMatrix(ResultMatrix, SMALL_ROWS);
PrintMaxesAndMins(LargeMatrix,
SmallMatrix,
ResultMatrix,
SMALL_ROWS,
SMALL_COLUMNS);
return 0;
}
Upvotes: 1
Reputation: 144790
There are 2 approaches to your problem:
SIZE*SIZE*ROWS*COLS
iterations, potentially a long time.int
and count the number of occurrences of each letter in the large matrix in ROWS*COLS
steps, then compute the result matrix counts by copying the appropriate count from the array for each cell in the small matrix in SIZE*SIZE
steps.Here is an example for the second approach:
// assuming 8-bit chars
void Count(char mat[ROWS][COLS], char smallMat[SIZE][SIZE], int result[SIZE][SIZE]) {
int count[256] = { 0 };
int i, j;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++)
count[mat[i][j] & 255]++;
}
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++)
result[i][j] = count[smallMat[i][j] & 255];
}
}
The requirement by using POINTERS is uncanny. The function does receive pointers to the argument arrays, I guess you could obfuscate the above code to use the pinter syntax *(p + i)
in place of the array syntax p[i]
to fulfil this requirement. Here is the ugly outcome:
// assuming 8-bit chars
void Count(char mat[ROWS][COLS], char smallMat[SIZE][SIZE], int result[SIZE][SIZE]) {
int count[256] = { 0 };
int i, j;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++)
*(count + (*(*(mat + i) + j) & 255) += 1;
}
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++)
*(*(result + i) + j) = *(count + (*(*(smallMat + i) + j) & 255));
}
}
Upvotes: 1
Reputation: 84569
If you are still struggling with which approach to take, a good benchmark to measure against is just the simple brute-force approach. While there are generally multiple ways to put things together, and generally some efficiency gains to be had, the brute-force approach is usually the easiest to understand. That being to simply loop over each char in small
and then loop over each char in your big
array and having zeroed result
simply increment the index in result
each time the character in small
matches big
.
The 4-loop approach takes nothing more than keeping track of which index is currently being compared and which is being incremented. In this case the indexes for small
and result
will correspond to one another and you simply use two additional indexes to iterate through big
, e.g.
/* fill result count from chars in arr matching small */
void count (char big[ROW][COL], int row, int col, char (*small)[SIZE],
int rowsm, int (*result)[SIZE])
{
for (int i = 0; i < rowsm; i++) /* for each row in small */
for (int j = 0; j < SIZE; j++) /* for each col in small */
for (int k = 0; k < row; k++) /* for each row in big */
for (int l = 0; l < col; l++) /* for each col in big */
if (small[i][j] == big[k][l]) /* does small == arr? */
result[i][j]++; /* increment result */
}
At that point, you have your result
matrix filled.
The remainder is fairly straight-forward. The only real task left is reading big
from your input file (or stdin
). The simple approach here, given the format of big
is to read each character of input as a character and simply test isalpha (c)
(or isupper (c)
if you like). Simply store the alpha-characters, ignoring the rest, but keeping track of the '\n'
and EOF
encountered to update/reset the needed counters. Your read could be:
int main (int argc, char **argv) {
char arr[ROW][COL] = {{0}}, /* big matrix */
small[][SIZE] = {{ 'U', 'N', 'T', 'E' }, /* small matrix */
{ 'C', 'P', 'G', 'X' },
{ 'D', 'L', 'A', 'B' }};
int c = 0, /* to read chars from file into big mtrx */
rdx = 0, /* row index */
cdx = 0, /* col index */
colmax = 0, /* max col found per-row */
rowsm = sizeof small / sizeof *small, /* rows in small */
result[rowsm][SIZE]; /* result matrix */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
zerovla (rowsm, result); /* zero elements in result */
while (c != EOF) { /* while not end of file */
/* while index < row and char not '\n' or EOF */
while (rdx < ROW && (c = fgetc (fp)) != '\n' && c != EOF)
if (isalpha (c)) /* if it's a letter */
arr[rdx][cdx++] = c; /* store it in big */
if (!cdx && (c == '\n' || c == EOF)) /* if end of line/file */
break; /* break */
if (!colmax) /* if colmax not set */
colmax = cdx; /* set with no. cols from 1st row */
if (cdx != colmax) { /* validate remaining rows have same cols */
fputs ("error: row with unuequal columns.\n", stderr);
return 1;
}
rdx++; /* increment row index */
cdx = 0; /* reset col index zero */
}
...
Putting it altogether you could do something similar to:
#include <stdio.h>
#include <ctype.h>
#define ROW 3
#define COL 20
#define SIZE 4
#define CHARSET 62
/* fill result count from chars in arr matching small */
void count (char big[ROW][COL], int row, int col, char (*small)[SIZE],
int rowsm, int (*result)[SIZE])
{
for (int i = 0; i < rowsm; i++) /* for each row in small */
for (int j = 0; j < SIZE; j++) /* for each col in small */
for (int k = 0; k < row; k++) /* for each row in big */
for (int l = 0; l < col; l++) /* for each col in big */
if (small[i][j] == big[k][l]) /* does small == arr? */
result[i][j]++; /* increment result */
}
/* simple zero VLA */
void zerovla (int rowsm, int (*result)[SIZE])
{
for (int i = 0; i < rowsm; i++)
for (int j = 0; j < SIZE; j++)
result[i][j] = 0;
}
/* print char array */
void prncharray (int row, int col, char (*arr)[col])
{
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
putchar (' ');
putchar (arr[i][j]);
}
putchar ('\n');
}
}
/* print int array */
void prniarray (int row, int col, int (*arr)[col])
{
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++)
printf (" %d", arr[i][j]);
putchar ('\n');
}
}
int main (int argc, char **argv) {
char arr[ROW][COL] = {{0}}, /* big matrix */
small[][SIZE] = {{ 'U', 'N', 'T', 'E' }, /* small matrix */
{ 'C', 'P', 'G', 'X' },
{ 'D', 'L', 'A', 'B' }};
int c = 0, /* to read chars from file into big mtrx */
rdx = 0, /* row index */
cdx = 0, /* col index */
colmax = 0, /* max col found per-row */
rowsm = sizeof small / sizeof *small, /* rows in small */
result[rowsm][SIZE]; /* result matrix */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
zerovla (rowsm, result); /* zero elements in result */
while (c != EOF) { /* while not end of file */
/* while index < row and char not '\n' or EOF */
while (rdx < ROW && (c = fgetc (fp)) != '\n' && c != EOF)
if (isalpha (c)) /* if it's a letter */
arr[rdx][cdx++] = c; /* store it in big */
if (!cdx && (c == '\n' || c == EOF)) /* if end of line/file */
break; /* break */
if (!colmax) /* if colmax not set */
colmax = cdx; /* set with no. cols from 1st row */
if (cdx != colmax) { /* validate remaining rows have same cols */
fputs ("error: row with unuequal columns.\n", stderr);
return 1;
}
rdx++; /* increment row index */
cdx = 0; /* reset col index zero */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
count (arr, rdx, colmax, small, rowsm, result); /* count/fill result */
puts ("Big Matrix\n"); /* output all matricies */
prncharray (rdx, colmax, arr);
puts ("\nSmall Matrix\n");
prncharray (rowsm, SIZE, small);
puts ("\nResult Matrix\n");
prniarray (rowsm, SIZE, result);
return 0;
}
Example Use/Output
$ ./bin/bigsmallfreq <dat/bigmtrxltrs.txt
Big Matrix
P A D A Q E Q B G H R O P H C W S P B Q
M B R P R N V S C H M U J P W C V M F D
V W R K E V I Y K K Q Y N H N G V L B Z
Small Matrix
U N T E
C P G X
D L A B
Result Matrix
1 3 0 2
3 5 2 0
2 1 2 4
Look things over and let me know if you have more questions.
Upvotes: 1
Reputation: 29
i want ADD the VOID function *to show user which char in appear the MOST and which appear 0 times ** /:
void Count(const char mat[ROWS][COLS], char c, int *count)
{
int i, j;
int counter = 0;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
if (mat[i][j] == c)
counter++;
}
*count = counter;
if(counter>max)
counter=max;
else
counter=min;
}
if(count==max)
printf("Most repetitive: %c %d times", c,counter);
if(count==min)
printf("Most repetitive: NO COMMON LETTERS (max = 0)");
}
It should look like this: Most repetitive: NO COMMON LETTERS (max = 0) Result matrix: 1 3 0 2 3 4 2 0 2 1 2 4 1 0 3 3 Most repetitive: P... 4 times
Upvotes: 0