Program that detects which letter is the most common - c

I am a beginner in C, I am trying to make a program which detects which letter is the most common of max 10 letters.
Here is what I've got so far:
char one = 'a'; //0110 0001
char check[10];
scanf("%s", &check);
char *ptr;
int a = 0;int b = 0;int c = 0;int d = 0;int e = 0;int f = 0;int g = 0;int h = 0;int i = 0;int j = 0;int k = 0;int l = 0;int m = 0;int n = 0;int o = 0;int p = 0;int q = 0;int r = 0;int s = 0;int t = 0;int u = 0;int v = 0;int w = 0;int x = 0;int y = 0;int z = 0;
if (check[0]=='a'){
a += 1;
if (a> b && a> c && a> d && a> e && a> f && a> g && a> h && a> i && a> j && a> k && a> l && a> m && a> n && a> o && a> p && a> q && a> r && a> s && a> t && a> u && a> v && a> x && a> y ){
printf("A is the most common letter);
}
}
The 'if' statement is only for the first letter that is entered and it is only checking the letter a.
Here is where I need help, how do I optimize that? How can I make a loop instead of having all that a>b && a>c ... etc. Also if it is possible to declare a lot of similar variables in a shorter way? Just generally how do I keep short and am I doing something wrong?
Thank you.

Yes you are doing a lot of things wrong.
this part of code
int a = 0;int b = 0;int c = 0;int d = 0;int e = 0;int f = 0;int g = 0;int h = 0;int i = 0;int j = 0;int k = 0;int l = 0;int m = 0;int n = 0;int o = 0;int p = 0;int q = 0;int r = 0;int s = 0;int t = 0;int u = 0;int v = 0;int w = 0;int x = 0;int y = 0;int z = 0;
is something horrific.
Use an array, like that:
int letter[25];
letter[0] will be your a, letter[1] will be your b ... letter[49] will be your z.
this part of code
if (check[0]=='a'){
a += 1;
is a bad way to do what you want.
you should do it like this:
int i;
for(i = 0; i < 10; ++i)
{
if(check[i] >= 'A' && check[i] <= 'Z') // Check if letter is uppercase.
++letter[check[i] - 'A']; // 'A' == 65, But our array is from 0 to 49.
if(check[i] >= 'a' && check[i] <= 'z') // Check if letter is lowercase.
++letter[check[i] - 'a']; // 'a' == 97. Note that 'A' is not 'a'.
}
This will check which character is most common, and stores it in the letter array.

You can certainly do it your way and compare every letter with every other. But usually you do this in two phases
count how often the letters occur
int letters[26];
int i, n = strlen(check), max;
memset(letters, 0, sizeof(letters));
for (i = 0; i < n; ++i) {
char c = tolower(check[i]);
letters[c - 'a']++;
}
pick the highest one
max = 0;
for (i = 1; i < 26; ++i)
if (letters[i] > letters[max])
max = i;
printf("%c is the most common letter\n", max + 'a');

Impressive work :)
int counts[26]; // We are expecting 26 letters
char check[10];
char *ptr;
scanf("%s", check);
memset(counts, 0, sizeof(counts)); // zero all array values
for (ptr = check; *ptr; ptr++)
{
char ch = *ptr;
if (isalpha(ch)) // ignore non-alphas
{
ch = tolower(ch);
counts[ch - 'a']++;
}
}
You can add best index lookup code from dreamzor answer

You need to use loops and arrays. Just store the amount of letters you've got in an array and then compare current the letter amount to best amount:
char check[10];
scanf("%s", &check);
const int checkSize = strlen(check);
int numberOfLetters[26];
for(int i = 0; i < 26; ++i)
numberOfLetters[i] = 0;
int bestLetterIndex = -1;
for(int i = 0; i < checkSize; ++i) {
int letterIndex = check[i] - 'a'; // getting index from ASCII code
numberOfLetters[letterIndex]++;
if(i == 0 || // first letter, index not found yet
numberOfLetters[letterIndex] > numberOfLetters[bestLetterIndex]) {
bestLetterIndex = letterIndex;
}
}
printf("Most common letter is %c", (char)(bestLetterIndex + 'a'));

Related

What exactly qualifies as a declaration of an identifier?

I am trying to construct some code such that it takes a user's input, runs one loop, takes the end value of that loop, and then runs that value through a second loop (I am also adding to a counter each time a loop runs and printfing it at the end), this was my attempt at coding this:
{
float input = get_float("%s", "Input: ");
float w = input * 100;
{
int c = 0;
for (int q = w; q > 24; q = q - 25)
{
c++;
}
for (int d = q; d > 9; d = d - 10)
{
c++;
}
printf("%i", c);
}
}
The error I receive is error: use of undeclared identifier 'q'. I thought that, since it was used earlier in the code, it wouldn't be a problem to identify it later on, though obviously that's not true. Any advice on either now to properly declare 'q' would be appreciated- or perhaps my entire approach is simply misguided?
The q declared in the loop is only available in the loop. You should declare it before the loop to make it available after the loop.
{
float input = get_float("%s", "Input: ");
float w = input * 100;
{
int c = 0;
int q; // declare q before the loop
for (q = w; q > 24; q = q - 25) // no declaration of q here
{
c++;
}
for (int d = q; d > 9; d = d - 10)
{
c++;
}
printf("%i", c);
}
}
When you declare q in the first loop it exists only inside this one loop as a local variable
Declaring the variable outside the for scope will leave it accessible on the second loop
{
float input = get_float("%s", "Input: ");
float w = input * 100;
{
int c = 0;
int q;
for (q = w; q > 24; q = q - 25)
{
c++;
}
for (int d = q; d > 9; d = d - 10)
{
c++;
}
printf("%i", c);
}
}```
for (int q = w; q > 24; q = q - 25) <- q is ok in this block
for (int d = q; d > 9; d = d - 10) <- q doesn't exist within this block
Add int q; below int c = 0; and modify for (int q = w; q > 24; q = q - 25) to for (q = w; q > 24; q = q - 25)

Searching for a substring in 2d array in C

This is something for searching a substring In a 2d array
int left_to_rigth(char matrix[ROW][COLUNM], char str1[])
{
int i = 0, j, counting = 0, wordcnt;
int length = computeLength(str1); //returns legth of string
int index = -1;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COLUNM; j += 1)
{
if (matrix[i][j] == str1[0])
{
for (wordcnt = 0; wordcnt < length; wordcnt++)
{
if (matrix[i][j + wordcnt] == str1[wordcnt])
{
counting++;
}
}
if (counting == length)
{
index = (i *12) + j;
}
}
}
}
return index;
}
The output:
Enter the string to be searched in the puzzle:
SHOUT
position in the puzzle: 12
PUZZLE(MATRIX)
X T Z M Q Y K C E C F H -->0 1 2 3 4 5 6 7 8 9 10 11
*S H O U T* E X O E A P I -->12 13 14 ------------23
X G T L Q B E L T N F K
A I R I D Z A L L I O D
M E I E T Y S E H R T I
A W B R N E T C W O H X
N O U I R U Z T S C C T
U D T P E C J I E H R U
A L E M C S Y O N I U R
L V *K E R E M* N I P H E
E A N B U R E J O N C Y
A W I I I J N J R U Y F
D W T N T H E N P J Y T
E Q L Z D I L E M M A B
R C I T E N G A M T P C
So the function returns the starting point of SHOUT which is 12 but when I try to search for the word KEREM it should give me 110 but instead it return -1 which says that the word doesnt exist.
It seems like the code only searches for the first 3 lines every input I enter after that returns -1. Could you please help I am a beginner
This is just the first part I need to make it so that it searches in every direction I can either write 4 seperate functions and call them if they dont return -1 but I need to get this working first
Okay, I've done a few speedups and simplifications.
No need for a separate counting [for left-to-right and right-to-left, at least] as you can use wordidx
Also, once you find a match on the inner loop, there is no need to continue with it. And, you can stop the outer loop early
It's faster to calculate the length of str1 outside of the call and pass length as an argument. Also, strlen should work just fine.
On left-to-right, there is no need for j to go all the way to COLUMN - 1 as the last N slots can not match if there isn't enough room on the matrix line to fulfill the remaining string length.
Also, it's undefined behavior because you'll spill over into the next row. This would be harmless [but wrong result] except for the last row, where you'll go beyond the end of the entire matrix.
So, I added a jmax value of COLUMN - length
The right-to-left is slightly trickier. The jmax trick is critical.
So, here are the two functions [they compile cleanly, but I've not tested them]:
#include <string.h>
#define ROW 10
#define COLUMN 10
int
left_to_right(char matrix[ROW][COLUMN], const char *str1, int length)
{
char *matcur;
int i;
int j;
int wordidx;
int jmax = COLUMN - length;
int index = -1;
jmax += 1;
for (i = 0; i < ROW; ++i) {
for (j = 0; j < jmax; ++j, ++matcur) {
matcur = &matrix[i][0];
if (matcur[0] != str1[0])
continue;
for (wordidx = 1; wordidx < length; ++wordidx) {
if (matcur[wordidx] != str1[wordidx])
break;
}
if (wordidx == length) {
index = (i * COLUMN) + j;
break;
}
}
if (index >= 0)
break;
}
return index;
}
int
right_to_left(char matrix[ROW][COLUMN], const char *str1, int length)
{
const char *matcur;
int i;
int j;
int wordidx;
int jmax = COLUMN - length;
int index = -1;
for (i = 0; i < ROW; ++i) {
matcur = &matrix[i][jmax];
for (j = jmax; j >= 0; --j, --matcur) {
if (matcur[0] != str1[0])
continue;
for (wordidx = 0; wordidx < length; ++wordidx) {
if (matcur[wordidx] != str1[wordidx])
break;
}
if (wordidx == length) {
index = (i * COLUMN) + j;
break;
}
}
if (index >= 0)
break;
}
return index;
}

fgets is reading in too late

Okay. After having completely rewritten this program over in favor of fgets, it mostly reads in the words.
This comes in two pieces, compiled upon a gcc linux machine. However, a redirect statement is required for this.
So once compiled it must be run like this:
./a.out < data1
So here's "data1":
S T E L B M T F E Y D E E P S R T C I A E E
N N E L I T R L B D E T A R E M U N E T Y L
N O I T A N I M I R C N I F L E S S E N T A
A U I D E W A R R A N T N U P R U S S E R P
P G S G E A L P A P B A N P S A S S N M E A
C O N S I T U T I O N D E E C W S O O H P D
S V W D E L A N E E J A M E S M A D I S O N
A E D E S N E G R J C U L T N O H L T I R A
A R C E R R T R E E S B O N E E I D N N P R
S N J U D I C I A L A S S E C O R P E U D I
S M R A R A E B W B E S S M E O A U V P E M
O E O I A I L N O U C D O D S S E N N I G R
L N I D G Y T R C O M P E N S A T I O N N D
D T O Z E H P Y N D R L E E A O H S C O I B
I T P S U E T G O L U Z M M R B E H P I R T
E O I E A R R S U U I B H A Y L L M S T F A
R I N R E E E F U T L V Q U A R T E R I N G
S I D B S R R D I Y E N I G M I A N A T I R
S Q I S E B S C N S P E E C H R O T A E Y N
D L C M I L I T I A F L R N C A T S S P S E
R U T E D Y L E B I L C O H M L E T E S Y Y
L S T R T E W Z L I O S A E N S A E I Y A L
AMENDMENT
ASSEMBLY
BAIL
BEARARMS
CITIZEN
CIVIL
COMPENSATION
CONGRESS
CONSITUTION
CONVENTIONS
DELEGATED
DOUBLEJEOPARDY
DUEPROCESS
ENUMERATED
FREEDOM
GOVERNMENT
ILLEGAL
INDICT
INFRINGED
JAMESMADISON
JUDICIAL
LAWSUIT
LIBEL
LIBERTY
LIFE
MILITIA
MIRANDA
NECESSARY
PEACEABLY
PEERS
PETITION
POWER
PRESS
PROBABLECAUSE
PROPERTY
PUNISHMENTS
QUARTERING
RELIGION
RIGHTS
SEARCH
SECURITY
SEIZURE
SELFINCRIMINATION
SLANDER
SOLDIERS
SPEECH
SPEEDY
TRIAL
UNREASONABLE
WARRANT
WITNESS
Here's the program itself:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 50
#define COLUMNS 50
#define TR 100
#define TC 100
int main( )
{
int s1 = 0, s2 = 0;
int sizeOfGrid = 0;
int wordCount = 0;
int rowNumber = 0;
int colNumber = 0;
/* */
char tempLetters[ROWS][COLUMNS];
char letters[ROWS][COLUMNS];
char words[ROWS][COLUMNS];
char wordTemp[50];
char firstRow[100], nextRow[100];
/* fgets(stdin); */
char firstRowTemp[100], nextRowTemp[100];
/* output input */
setbuf(stdout, NULL);
for (s2 = 0; s2 < 100; s2++)
{
firstRowTemp[s2] = ' ';
nextRowTemp[s2] = ' ';
if (s2 < 50)
{
wordTemp[s2] = ' ';
for (s1 = 0; s1 < 50; s1++)
{
words[s2][s1] = ' ';
}
}
}
/* Let's attempt to despace the first line, and then count the chars. */
fgets(firstRow,100,stdin);
s1 = 0;
s2 = 0;
for (colNumber = 0; colNumber < strlen(firstRow); colNumber++)
{
if ((firstRow[colNumber] != ' ') && (firstRow[colNumber] != '\n'))
{
firstRowTemp[s1] = firstRow[colNumber];
letters[rowNumber][s2++] = firstRowTemp[s1++];
sizeOfGrid++;
}
}
/* We have now successfully gotten the size of the grid, so lets
* put it to good use within our next loops to read in the rest
* of the lines.
* We take it in a for loop up to sizeOfGrid*2 because right now,
* we still have spaces. Once we get rid of those, it'll be able to utilize
* normal sizeOfGrid count.*/
for (rowNumber = 1; rowNumber < sizeOfGrid*2; rowNumber++)
{
fgets(nextRow, 100, stdin);
s1 = 0;
s2 = 0;
for (colNumber = 0; colNumber < sizeOfGrid*2; colNumber++)
{
if ((nextRow[colNumber] != ' ') && (tempLetters[rowNumber][colNumber] != '\n'))
{
nextRowTemp[s1] = nextRow[colNumber];
letters[rowNumber][s2++] = nextRowTemp[s1++];
}
}
}
/* Next up, it's time to store the words. Scan the rest of the file for words
* and store them as chars. */
rowNumber = 0;
colNumber = 0;
while(fgets(wordTemp,50,stdin) != NULL)
{
for (s1 = 0; s1 < strlen(wordTemp); s1++)
{
if (wordTemp[s1] != '\n')
{
words[rowNumber][colNumber++] = wordTemp[s1];
}
}
colNumber = 0;
wordCount++;
rowNumber++;
}
/* For testing purposes and making sure it receives the grid entirely.*/
for (s2 = 0; s2 < sizeOfGrid; s2++)
{
printf("%c",firstRowTemp[s2]);
}
printf("\nSize of grid is %d\n",sizeOfGrid);
printf("\n");
for (rowNumber = 0; rowNumber < sizeOfGrid; rowNumber++)
{
for (colNumber = 0; colNumber < sizeOfGrid; colNumber++)
{
printf("%c", letters[rowNumber][colNumber]);
}
printf("\n");
}
for (rowNumber = 0; rowNumber < ROWS; rowNumber++)
{
for (colNumber = 0; colNumber < COLUMNS; colNumber++)
{
if ((words[rowNumber][colNumber] != ' ') && (words[rowNumber][colNumber] != '\n'))
printf("%c", words[rowNumber][colNumber]);
else
break;
}
if (colNumber > 1)
printf("\n");
}
/* End print debugging here.*/
return 0;
}
And now for my question itself...
It appears fgets is skipping over a large number of words, starting only at LIBEL instead of running through the top of the list (AMENDMENTS in this case). Where is it going wrong?
In the grid you've shown us, there are spaces between letters horizontally, but no blank lines between the lines of letters, so you need to use sizeOfGrid*2 to loop over the columns, but not the rows.

Donald Knuth algorithm for Mastermind

I'm working onto the Donald Knuth 1977 algorithm for Mastermind (here). I've implemented some steps, but I don't know how to calculate the number of possibilites that would be eliminated for each possible score.
Integer Bulls <- 0
WHILE Bulls <= 4
Integer Cows <- 0
WHILE Cows <= 4
Integer CurrentSetSize <- 0
WHILE CurrentSetSize <= Set.size
// Now, I should know if this possibility can be eliminated. But how ?
END WHILE
END WHILE
END WHILE
Do you have any way to do this ?
Thanks.
Edit : I did it with C. It isn't Mastermind in reality but Bulls & Cows, but it's the same.
// ASCII-compatible
#define POSSIBILITIES 6720
struct Guess {
int i[5];
};
struct Answer {
int bulls;
int cows;
};
static struct Set {
struct Guess value;
int score;
} *CurrentSet;
void
initSet(void)
{
for (int i = 'a'; i <= 'h'; ++i) {
for (int j = 'a'; j <= 'h'; ++j) {
if (j == i) continue;
for (int k = 'a'; k <= 'h'; ++k) {
if (k == j || k == i) continue;
for (int l = 'a'; l <= 'h'; ++l) {
if (l == k || l == j || l == i) continue;
for (int m = 'a'; m <= 'h'; ++m) {
if (m == l || m == k || m == j || m == i) continue;
CurrentSet->value.i[0] = i;
CurrentSet->value.i[1] = j;
CurrentSet->value.i[2] = k;
CurrentSet->value.i[3] = l;
CurrentSet->value.i[4] = m;
CurrentSet->score = 0;
}
}
}
}
}
}
void
computeScore(int index)
{
struct answer p;
for (p.bulls = 0; p.bulls <= 4; ++p.bulls) {
for (p.cows = 0; p.cows <= 4; ++p.cows) {
for (int i = 0; i < POSSIBILITIES; ++i) {
}
}
}
}
void
updateSet(void)
{
for (int i = 0; i < POSSIBILITIES; ++i)
computeScore(i);
}

Diff algorithm, i.e. shortest edit-graph path

I am trying to understand the algorithm from the famous 'diff' paper here, running on characters in the two command-line arguments. However, my code does not produce the results I expect. I've written the algorithm to match their variables to the extent possible:
$ ./diff abbcabba cbabac #Hmm.. I think it should be 5
SES: 10
$ ./diff abcdefg abcdefg #0! Great!
SES: 0
$ ./diff abcXefg abcYefg # 2 seems reasonable
SES: 2
$ ./diff abcXefg abcefg # clearly wrong
SES: 7
Here is my code (Sorry about the wall of code):
a = argv[1];
b = argv[2];
alen = strlen(a);
blen = strlen(b);
tlen = alen + blen;
maxd = tlen;
vp = (int *)calloc(2 * maxd + 1, sizeof(int));
// How I'm thinking about pointer arithmetic:
// vp in [0, 2*maxd + 1) == [0, 2*maxd]
// v in [-maxd, maxd + 1) == [-maxd, maxd]
v = vp + maxd;
v[1] = 0;
for (D = 0; D <= maxd; D++) {
for (k = -D; k <= D; k += 2) {
if (k == -D || (k != D && v[k-1] < v[k+1])) {
x = v[k + 1];
} else {
x = v[k - 1] + 1;
}
y = x - k;
while (x < alen && y < blen && a[x] == b[x]) {
x++;
y++;
}
v[k] = x;
if (x >= alen && y >= blen) {
printf("SES: %d\n", D);
goto out;
}
}
}
printf("Nothing found. SES > %d\n", maxd);
Any idea where the flaw is here? I've been finding it incredibly hard to search online for this problem...
It seems that the problem is in this line:
while (x < alen && y < blen && a[x] == b[x]) {
Here b[x] should be b[y], which gives:
while (x < alen && y < blen && a[x] == b[y]) {
With this change the results for your examples are 6, 0, 2 and 1. This seems to be accurate.

Resources