Dividing the alphabet into parties for elections - C language - c

I want to write a program that takes an input from the user of "leading camps", and divides 26 letters in alphabet into 3 parties. for example if I choose the leading camps to be A-E-H, the three parties will be: 1) A,B,C,D 2) E,F,G 3) H-Z, and they the next input will be the votes (which are announced online), for example, if I enter the series of votes "fDFFGCcdC", the leading party will be the one that includes letters A-D, because it got 5 votes, and the others took 4 and zero, and so on.
Here is what I wrote so far:
Notes: Lead* are the leading camps.
#include <stdio.h>
int main()
{
char Lead_1,Lead_2,Lead_3, vote;
int counter_1=0,counter_2=0,counter_3=0;
printf("Please enter the camps leaders:");
scanf("%c%c%c", &Lead_1,&Lead_2,&Lead_3);
printf("please enter the votes:");
scanf(" %c", &vote);
while(vote != '!')
{
scanf("%c", &vote);
if((vote >= Lead_1) && (vote < Lead_2) || (vote >= (Lead_1 + 32) && vote < (Lead_2 +32)))
counter_1++;
if((vote >= Lead_2) && (vote < Lead_3) || (vote >= (Lead_2 + 32) && vote < (Lead_3 +32)))
counter_2++;
if((vote >= Lead_3) || (vote >= (Lead_3 + 32)))
counter_3++;
if (counter_1 > counter_2 && counter_1 > counter_3)
printf("%c", Lead_1);
else if (counter_2 > counter_1 && counter_2 > counter_3)
printf("%c", Lead_2);
else if (counter_3 > counter_1 && counter_3 > counter_2)
printf("%c", Lead_3);
else
{
if((vote >= Lead_1) && (vote < Lead_2) || (vote >= (Lead_1 + 32) && vote < (Lead_2 + 32)))
printf("%c", vote);
if((vote >= Lead_2) && (vote < Lead_3) || (vote >= (Lead_2 + 32) && vote < (Lead_3 + 32)))
printf("%c", vote);
if((vote >= Lead_3) || (vote >= (Lead_3 + 32)))
printf("%c", vote);
}
}
return 0;
}
I'm having a problem with the output. for example if I enter the leading camps AEH, and enter the votes bAzz! the output is AzHH instead of AAAH.

I'm assuming that based on the votes "fDFFGCcdC", we have to come up with parties A-E-H. Besides, A is the leading party , E is the second leading party & H is the third party {based on number of votes they got}.
If my understanding is right, you can follow this:
Create a hash table for 26 letters and initialize it.
hash[26] = {0}
get the count of characters in votes.
hash[vote[i] - 'a'] ++
Now you got the array of count of votes. {which has max, second max, min}
Based on maximum, second maximum and minimum values, set the ranges and parties.

#include <stdio.h>
#include <ctype.h>
int main(void){
char party[4][2];
int votes[3] = {0};
int i;
char ch;
*party[3] = 'Z' + 1;//sentinel
//input format [alphabet for party1]-[alphabet for party2]-[[alphabet for party3]
puts("input devide party :");
if(3==scanf("%1[A-Z]-%1[A-Z]-%1[A-Z]", party[0], party[1], party[2])
&& *party[0] < *party[1] && *party[1] < *party[2] && *party[2] < *party[3]){
for(i = 0; i < 3; i++){
printf("party%d : ", i + 1);
for(ch = *party[i]; ch < *party[i+1]; ++ch){
if(ch != *party[i])
putchar(',');
putchar(ch);
}
puts("");
}
puts("input votes :");
ch = '_';
while(scanf(" %c", &ch) && ch != '!'){
if(isalpha(ch)){
ch = toupper(ch);
if(ch < *party[1])
++votes[0];
else if(ch < *party[2])
++votes[1];
else if(ch < *party[3])
++votes[2];
}
}
for(i = 0; i < 3; ++i){
printf("vote of party%d : %d\n", i+1, votes[i]);
}
} else {
puts("invalid input!");
}
return 0;
}

Related

CS50-pset2: Readability. Incorrect outcome

When I run my code, the outcome has failed to show the exact result based on the texts given in the problem set. Although, it showed the grade, the result is incorrect. The text is : "Would you like them here or there? I would not like them here or there. I would not like them anywhere."(Grade 2)
enter image description here
Supposedly, the result for the text is "Grade 2". However, it shows all grades instead.
enter code here
int main(void)
{
string s = get_string("Text: ");
printf("%s\n",s);
int count_letters = 0; //To count letters (uppercase & lowercase)
int count_words = 1; //To count words
int count_sentences = 0; //To count sentences
for (int i = 0; i < strlen(s); i++)
if (isalpha(s[i]))
{
if ((s[i] >= 'a' && s[i] <= 'z' )||( s[i] >= 'A' && s[i] <= 'Z'))
{
count_letters++;
}
if (s[i] == ' ')
{
count_words++;
}
if (s[i] == '.' || s[i] =='!' || s[i] == '?')
{
count_sentences++;
}
//printf("%i count_letter(s)\n", count_letters);
//printf("%i count_words(s)\n", count_words);
//printf("%i sentence(s)\n", count_sentences);
//Coleman-Liau index
float L = (count_letters / (float) count_words) * 100;
float S = (count_sentences / (float) count_words) * 100;
int grade = round (0.0588 * L - 0.296 * S -15.8);
if (grade < 1)
{
printf("Before Grade 1\n");
}
else if (grade >= 16)
{
printf("Grade 16+\n");
}
else
{
printf("Grade %.d\n", grade);
}
}
}
Is there any problem with my code? How can I fix my code in order to receive the exact outcome. I've been doing this problem set for almost 2 days :'/. Thanks in advance
Calculate the number of letters, sentences, and words inside of the loop and calculate Coleman-Liau's index outside of the loop.
Don't calculate something in a loop and try to get specific output from within it as well, it never ends well. So in conclusion, calculate your values in the loop and do everything else outside of it.
int count_letters = 0; //To count letters (uppercase & lowercase)
int count_words = 1; //To count words
int count_sentences = 0; //To count sentences
for (int i = 0; i < strlen(s); i++){
// get the amounts in the loop
if (isalpha(s[i]))
{
if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'))
{
count_letters++;
}
if (s[i] == ' ')
{
count_words++;
}
if (s[i] == '.' || s[i] == '!' || s[i] == '?')
{
count_sentences++;
}
}
}
//Calculate Coleman-Liau outside of it and get the correct grade from your if statements
Since you have three distinct categories to count, I would create a function for each of these.
For example, based on your code, you could create a function to count characters (you don't need isdigit function here, non-digit characters are already filtered out by the algorithm itself):
int get_letters_count(char *text_str)
{
int count_letters = 0;
int text_len = strlen(text_str);
for (int i = 0; i < text_len; i++) {
if ( (text_str[i] >= 'a' && text_str[i] <= 'z')
|| (text_str[i] >= 'A' && text_str[i] <= 'Z')
|| (text_str[i] >= '0' && text_str[i] <= '9')) {
count_letters++;
}
}
return count_letters;
}
This approach of breaking down your program will make it much easier to develop.
Here is a very crude implementation based on the Coleman–Liau index Wikipedia page:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int get_letters_count(char *text_str)
{
int count_letters = 0;
int text_len = strlen(text_str);
for (int i = 0; i < text_len; i++) {
if ( (text_str[i] >= 'a' && text_str[i] <= 'z')
|| (text_str[i] >= 'A' && text_str[i] <= 'Z')
|| (text_str[i] >= '0' && text_str[i] <= '9')) {
count_letters++;
}
}
return count_letters;
}
int get_words_count(char *text_str)
{
int count_words = 0;
int text_len = strlen(text_str);
for (int i = 0; i < text_len; i++) {
if (text_str[i] == ' ') {
count_words++;
}
}
if (count_words)
count_words++;
return count_words;
}
bool word_is_acronym(char *word)
{
bool ret = true;
for (; *word && *word != ' '; word++) {
if ( *word != '.'
&& *word < 'A' || *word > 'Z') {
ret = false;
}
}
return ret;
}
int get_sentences_count(char *text_str)
{
int count_sentences = 0;
int text_len = strlen(text_str);
char *last_word = &text_str[0];
for (int i = 0; i < text_len; i++) {
if ( text_str[i] == ' '
&& i < (text_len - 1)) {
last_word = &text_str[i + 1];
}
bool end_mark = text_str[i] == '.'
|| text_str[i] == '!'
|| text_str[i] == '?';
if ( end_mark
&& word_is_acronym(last_word) == false) {
count_sentences++;
}
}
return count_sentences;
}
int main(void)
{
char text_str[] = "Existing computer programs that measure readability are based "
"largely upon subroutines which estimate number of syllables, "
"usually by counting vowels. The shortcoming in estimating syllables "
"is that it necessitates keypunching the prose into the computer. "
"There is no need to estimate syllables since word length in letters "
"is a better predictor of readability than word length in syllables. "
"Therefore, a new readability formula was computed that has for its "
"predictors letters per 100 words and sentences per 100 words. "
"Both predictors can be counted by an optical scanning device, and "
"thus the formula makes it economically feasible for an organization "
"such as the U.S. Office of Education to calibrate the readability of "
"all textbooks for the public school system.";
int count_letters = get_letters_count(text_str);
int count_words = get_words_count(text_str);
int count_sentences = get_sentences_count(text_str);;
if ( count_letters > 0
&& count_words > 0
&& count_sentences > 0) {
float L = ((count_letters * 100) / count_words);
float S = ((count_sentences * 100) / count_words);
float grade = 0.0588 * L - 0.296 * S - 15.8;
printf("grade = %.01f\n", grade);
} else {
printf("bad input\n");
}
}
Ouput:
$ gcc main.c && ./a.out
grade = 14.5
Parsing text can be very trick, though.
Once you get a first version working with a known input such as this, try to expand your data set and keep improving your program.
This program is also far from being computationally efficient. If that becomes a bottleneck, you could optimize the functions or maybe reduce the number of loops grouping the functions in a single loop.
Certainly most times it's better to start with a crude working solution and improve from there instead of attempting a more sophisticated/complete solution right from the beginning.

Converting a base 20 number to decimal

I have been asked to convert a number in base 20 to decimal,
where the number in base 20 is entered by the user in reverse order.
For example if the original number is F1 the input is 1F.
I can only use the standard library <stdio.h>, loops and conditions.
This is what I have done so far that does not seem to work.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int sum = 0;
int exp = 1;
char reverse_char;
printf("Enter a reversed number in base 20:");
scanf(" %c", &reverse_char);
while (reverse_char != '\n') {
if ((reverse_char >= '0') && (reverse_char < '10') || ((reverse_char >= 'a') && (reverse_char < 'k')) || ((reverse_char >= 'A') && (reverse_char < 'k'))) {
if ((reverse_char >= '0') && (reverse_char < '10')) {
reverse_char = reverse_char - '0';
sum += (reverse_char * exp);
exp = exp * 20;
}
else if ((reverse_char >= 'a') && (reverse_char < 'k')) {
reverse_char = reverse_char - 'a';
sum += (reverse_char * exp);
exp = exp * 20;
}
else
{
reverse_char = reverse_char - 'A';
sum += (reverse_char * exp);
exp = exp * 20;
}
}
else {
printf("%c is not a number in base 20", reverse_char);
break;
}
scanf(" %c", &reverse_char);
}
if (reverse_char == '\n')
printf("%d", sum);
}
At least these problems:
" %c" consumes leading white-space like '\n'
With scanf(" %c", &reverse_char); while (reverse_char != '\n') , reverse_char != '\n' is always true. This certainly contributes to "does not seem to work." as loop does not end.
scanf("%c", &reverse_char); (no space before %c) in two lines of code may work here.
No character 10 #tkausl
Test against '9'.
// if ((reverse_char >= '0') && (reverse_char < '10')) {
if ((reverse_char >= '0') && (reverse_char <= '9')) {
This hints that OP is not enabling all compiler warnings. Best take-away here:
Enable all warnings to save time.
int overflow
exp = exp * 20; can readily overflow int math even if sum in range.
For those EBCDIC aficionados: Character encoding
Below fails as the letter A-J are not all sequentially encoded.
//if ((reverse_char >= 'a') && (reverse_char < 'k')) {
// reverse_char = reverse_char - 'a';
Recommend to use an array look-up.
Any base (limited by the digits string) reversed number converting function
static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
uint32_t toU32Reverse(const char *number, int base)
{
uint32_t result = 0;
const char *start = number;
if(number && *number && base < sizeof(digits))
{
while(*(number)) number++;
do
{
const char *pos;
number--;
if((pos = strchr(digits, toupper(*number))) && (pos - digits) < base)
{
result *= base;
result += pos - digits;
}
else
{
result = 0;
break;
}
}while(number > start);
}
return result;
}

Password checker in c language

I want to take input as a string and evaluate if it is a valid password. The password is valid if it has numbers, capital and small alphabets, and a length of at least 7 characters. Also, when all these requirements are satisfied, the output should be "Strong", else "Weak". Code:
#include<stdio.h>
#include<string.h>
#define N 20
int main()
{
char pass[N];
int i, x=0, p;
printf("Enter a password: ");
scanf("%s", &pass);
if(strlen(pass)>=7)
{
p=strlen(pass);
for (i = 0; i < p; i++)
{
if ((pass[i] >= 'a' && pass[i] <= 'z') || (pass[i] >= 'A' && pass[i <= 'Z') || (pass[i] >= '0' && pass[i] <= '9'))
printf("Sucess! ");
}
}
else
printf("Try Again..");
return 0;
}
Somethings are not working like: 1. After execution, it prints "Sucess!!" multiple times.. 2. In the inner if block, when i replace || with &&, it didn't print anything.
Please help.
You could change this section of code:
p=strlen(pass);
for (i = 0; i < p; i++)
{
if ((pass[i] >= 'a' && pass[i] <= 'z') || (pass[i] >= 'A' && pass[i <= 'Z') || (pass[i] >= '0' && pass[i] <= '9'))
printf("Sucess! ");
}
... to something like this:
int lower_case_count = 0;
int upper_case_count = 0;
int digit_count = 0;
p=strlen(pass);
for (i = 0; i < p; i++) {
if (pass[i] >= 'a' && pass[i] <= 'z') ++lower_case_count;
if (pass[i] >= 'A' && pass[i] <= 'Z') ++upper_case_count;
if (pass[i] >= '0' && pass[i] <= '9') ++digit_count;
}
if (lower_case_count > 0 && upper_case_count > 0 && digit_count > 0) {
printf("Strong\n");
}
In the loop you just want to count how many of each type of characters is present.
Once the loop is done, you can check whether all requirements are satisfied and take appropriate action.
You made me thinking and I came up with this rather simple solution - two series of ifs, one wrapped within a while loop. It checks for lower and uppercase, numbers and special characters, reporting the exact error a user had eventually made.
//A program for password validation
#include <stdio.h>
#include <ctype.h>//for islower(), isupper(), isdigit() and ispunct()
#include <string.h>//for strlen()
int main(void)
{
char pass[30];
printf("Enter your password: ");
scanf("%[^\n]s", pass);//so that password may contain space char
int i = 0,
lower_count = 0,
upper_count = 0,
digit_count = 0,
punct_count = 0;
int length = strlen(pass);
//loop goes through the password as array
while (pass[i]) {
if(islower(pass[i]))//if there is lowercase
lower_count++;
if(isupper(pass[i]))//if there is uppercase
upper_count++;
if (isdigit(pass[i]))//if there is a number
digit_count++;
if (ispunct(pass[i]))//if there is a special chars
punct_count++;
i++;
}
if(strlen(pass) < 8)
{
printf("The password must have at least 8 chars\n");
return 1;
}
if(lower_count == 0)
{
printf("You need lowercases\n");
}
if(upper_count == 0)
{
printf("You need an uppercase\n");
}
if(digit_count == 0)
{
printf("You need digits\n");
}
if(punct_count == 0)
{
printf("You need a special character\n");
}
if(upper_count != 0 && digit_count != 0 && punct_count != 0 &&
length > 12)
{
printf("Your password is strong!\n");
}
if(upper_count != 0 && digit_count != 0 && punct_count != 0 &&
length <= 12)
{
printf("Your password is OK\n");
}
return 0;
}

there is a test that stuck at infinity loop can you find it?

int main() {
int s, b;
int hist[26] = { 0 };
int hist2[26] = { 0 };
char char1, char2;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
scanf("%c", &char2);
while (char2 != '$') {
if (char2 >= 'A' && char2 <= 'Z')
char2 = char2 + 32;
int char3 = char2 - 'a';
hist2[char3]++;
scanf("%c", &char2);
if (char2 < 0)
break;
}
printf("How many times would you like to loop?\n");
if (!scanf("%d", &s))
return 0;
printf("Enter the string you would like to be checked ending with $:\n");
scanf("%c", &char1);
if (char1 >= 'A' && char1 <= 'Z')
char1 = char1 + 32;
while (char1 != '$' && char1 > 0) {
int char3 = char1 - 'a';
hist[char3]++;
scanf("%c", &char1);
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
b = 0;
break;
} else {
b = 1;
}
}
if (b)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}
//so basically this a homewrok in my university they asked us to do the program input is char and a loop and it compare it with one more input how many times you can loop each letter (no need to check that the input is true but the loop number int
Your program has many problems:
scanf() returns the number of successful conversions. Compare the return value to 1 in your program instead of testing 0, which would never happen for "%c" anyway. Furthermore, the char2 would not be modified if the stream is at end of file.
You must check of char2 is a letter before indexing into the array, otherwise you may access beyond the array boundaries and have undefined behavior.
presentation is important: use proper indentation and spacing for the program to be readable.
include the necessary headers such as <stdio.h>
Here is an improved version:
#include <stdio.h>
int main() {
int hist[26] = { 0 };
int hist2[26] = { 0 };
int s;
char c;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
while ((scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist2[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist2[c - 'a']++;
}
printf("How many times would you like to loop?\n");
if (scanf("%d", &s) != 1)
return 1;
printf("Enter the string you would like to be checked ending with $:\n");
while (scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist[c - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
break;
}
}
if (i == 26)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}

Comparing ASCII value of input (C Program)

For practice I am trying to create a program that counts the number of each digit, alphabetic character, and "whitespace" character in a line.
My program is printing fine however my counter is not correctly adding each character it reads. Below is the code for the program (I've only started learning about a week ago so please excuse any glaring issues).
I believe the my main issue rests in the if/else if statements where I compare the int c to a variety of ASCII values.
/* Print Count of Each Char, Spaces, and Digits */
int main(void) {
int c, i, CountWhitespace, count, Alpha;
int CountCharacter[26];
int CountDigits[10];
CountWhitespace = 0;
for (i = 0; i < 10; ++i) {
CountDigits[i] = 0; }
for (i = 0; i < 26; ++i) {
CountCharacter[i] = 0; }
while ((c = getchar()) != '\n') {
if (c >= '0' && c <= '9') {
++CountDigits[c]; }
else if (c == '\t' || c == ' ') {
++CountWhitespace; }
else if (c >= 'a' || c <= 'z') {
++CountCharacter[( c - 'a')]; }
else if (c >= 'A' && c <= 'Z') {
++CountCharacter[(c - 'A')]; }
}
printf("Whitespace Characters: %d\n", CountWhitespace);
for (i = 0; i < 10; i++) {
printf("%d appears %d times.\n", i, CountDigits[i]); }
for (Alpha = 'a', count = 0; count < 26; count++, Alpha++) {
printf("%c appears %d times.\n", Alpha, CountCharacter[count]); }
return EXIT_SUCCESS;
}
Below is an example of the output:
The green characters are the input, and as you may be able to tell, none of them are added to their corresponding variables.
You need to fix the digits counter:
if (c >= '0' && c <= '9') {
++CountDigits[c];
}
This will be increment CountDigits[48] (for '0'), etc. Not what you want. You've got it right for a..z; do the same here:
if (c >= '0' && c <= '9') {
++CountDigits[c - '0'];
}

Resources