Basically I have to encode a name into a Soundex Code. The helper functions I implemented do the following:
Discard all non-letter characters from the surname: dashes, spaces, apostrophes, and so on.
Encode each letter as a digit
Coalesce adjacent duplicate digits from the code (e.g. 222025 becomes 2025).
Replace the first digit of the code with the first letter of the original name, converting to uppercase.
Remove all zeros from the code.
Make the code exactly length 4 by padding with zeros or truncating the excess.
Excuse the implementation of the helper functions, I know they could be implemented better. But when I manually pass the output from one function to another I see that the result is what I want. It's only when I combine them all into one function that I see that the output I pass is as if I didn't modify the input I passed at all. I believe my issue might have to do with passing by reference but doing that for all my functions made no difference or gave an incorrect output.
#include <iostream>
#include <string>
string removeNonLetters(string s) {
string result = "";
for (int i = 0; i < s.length(); i++) {
if (isalpha(s[i])) {
result += s[i];
}
}
return result;
}
string encode(string name) {
std::transform(name.begin(), name.end(), name.begin(), ::toupper);
string encoded = "";
for (int i = 0; i < name.size(); ++i) {
if (name[i] == 'A' || name[i] == 'E' || name[i] == 'I' || name[i] == 'O' || name[i] == 'U' || name[i] == 'H' || name[i] == 'W' || name[i] == 'Y')
encoded += '0';
else if (name[i] == 'B' || name[i] == 'F' || name[i] == 'P' || name[i] == 'V')
encoded += '1';
else if (name[i] == 'C' || name[i] == 'G' || name[i] == 'J' || name[i] == 'K' || name[i] == 'Q' || name[i] == 'S' || name[i] == 'X' || name[i] == 'Z')
encoded += '2';
else if (name[i] == 'D' || name[i] == 'T')
encoded += '3';
else if (name[i] == 'L')
encoded += '4';
else if (name[i] == 'M' || name[i] == 'N')
encoded += '5';
else if (name[i] == 'R')
encoded += '6';
}
return encoded;
}
string removeDuplicate(string encoded) {
for (int i = 0; i < encoded.size(); ++i) {
if (encoded[i] == encoded[i+1])
encoded[i] = '\0';
}
return encoded;
}
string removeZeros(string digits) {
for (int i = 0; i < digits.size(); ++i) {
if (digits[i] == '0')
digits[i] = '\0';
}
return digits;
}
string padding(string output) {
int size = output.size();
if (size < 4) {
for (int i = size; i < 4; ++i)
output += '0';
}
else if (size > 4) {
for (int j = size; j > 3; --j)
output[j] = '\0';
}
return output;
}
/* TODO: Replace this comment with a descriptive function
* header comment.
*/
string soundex(string s) {
/* TODO: Fill in this function. */
string copy = s;
removeNonLetters(s);
encode(s);
removeDuplicate(s);
s[0]= copy[0];
removeZeros(s);
padding(s);
return s;
}
int main() {
string s = "Curie";
cout << soundex(s) << '\n';
// Output should be C600 but I keep getting "Curie."
}
Your functions return the adjusted strings, that's good. But your calling code doesn't use the returned values!
Something like this is what you want.
string soundex(string s) {
/* TODO: Fill in this function. */
string copy = s;
s = removeNonLetters(s);
s = encode(s);
s = removeDuplicate(s);
s[0] = copy[0];
s = removeZeros(s);
s = padding(s);
return s;
}
If you want to change the value of a variable you normally use =. I'm sure you know that but for some reason you forgot because functions are involved.
Related
So i wanted to count all the characters in a string and categorized them in vowels, consonants, and specials character. For example;
Enter string: sentence example ..
Vowels: e(5) a(1)
Consonants: s(1) n(1) t(1) c(1) x(1) m(1) p(1) l(1)
Specials: blank space .(2)
Here's coding:
void characterType(string input)
{
int vowel = 0;
int consonant = 0;
int special = 0;
int n = input.size();
int freq[26];
memset(freq, 0, sizeof(freq));
for (int i = 0; i < n; i++)
{
freq[input[i] - 'a']++;
}
cout<<"Vowels: ";
for (int i = 0; i < n; i++)
{
char character = input[i];
if(isalpha(character))
{
character = tolower(character);
if (character == 'a' || character == 'e' || character == 'i' || character == 'o' || character == 'u')
{
cout<<input[i]<<freq[input[i] - 'a']<<" ";
}
}
}
cout<<endl;
cout<<"Consonants: ";
for (int i = 0; i < n; i++)
{
char character = input[i];
if(isalpha(character))
{
character = tolower(character);
if (character != 'a' || character != 'e' || character != 'i' || character != 'o' || character != 'u')
{
cout<<input[i]<<freq[input[i] - 'a']<<" ";
}
}
}
cout<<endl;
cout<<"Specials: ";
for (int i = 0; i < n; i++)
{
char character = input[i];
if(!isalpha(character))
{
if(character == ' ')
{
cout<<"[black space]"<<freq[input[i] - 'a']<<" ";
}
else
cout<<input[i]<<freq[input[i] - 'a']<<" ";
}
}
}
And heres what ive got so far:
How do i make it not repeat the same character and why does special characters is not counting?
Since you want to do this and it's not some type of assignment, here's how I would approach the problem, using modern C++ features:
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main() {
std::map<char, std::size_t> occurrance;
std::string input{"This is A long string with lots of characters in it. AAA$#!#$!^^! "};
auto is_vowel = [] (char c) -> bool
{
auto lc = std::tolower(c);
return
c == 'a' ||
c == 'e' ||
c == 'i' ||
c == 'o' ||
c == 'u';
};
auto is_special = [] (char c) -> bool
{
// use ascii table to find only "non-special characters"
if(c < '0') return true;
if(c > '9' && c < 'A') return true;
if(c > 'Z' && c < 'a') return true;
if(c > 'z') return true;
return false;
};
auto vowels = std::count_if(
input.begin(),
input.end(),
is_vowel);
auto special = std::count_if(
input.begin(),
input.end(),
is_special);
for(auto c : input)
{
occurrance[c] += 1;
}
std::cout << "Vowels: " << vowels << '\n';
std::cout << "Special: " << special << '\n';
for(auto [c, count] : occurrance)
{
std::cout << c << " -> " << count << '\n';
}
return 0;
}
https://ideone.com/YVaDiI
This does the job, although you can make the output prettier... and take the uppercase letters into account.
void printCharWithFreq(string str)
{
int v=0, c=0, s=0;
// size of the string 'str'
int n = str.size();
// 'freq[]' implemented as hash table
int freq[SIZE];
// initialize all elements of freq[] to 0
memset(freq, 0, sizeof(freq));
// accumulate freqeuncy of each character in 'str'
for (int i = 0; i < n; i++)
freq[str[i] - 'a']++;
// traverse 'str' from left to right
for (int i = 0; i < n; i++) {
// if frequency of character str[i] is not
// equal to 0
if (freq[str[i] - 'a'] != 0) {
// print the character along with its
// frequency
if(str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U')
{ cout<<"Vowel: " << str[i] << freq[str[i] - 'a'] << " "<<endl; v+=freq[str[i] - 'a']; }
else if(str[i] == ' ' || str[i] == '.')
{ cout<<"Specials"<<endl; s++; }
else
{ cout<<"Consonant: " << str[i] << freq[str[i] - 'a'] << " "<<endl; c+=freq[str[i] - 'a']; }
// update frequency of str[i] to 0 so
// that the same character is not printed
// again
freq[str[i] - 'a'] = 0;
}
}
cout<<"Number of vowels: "<<v<<endl;
cout<<"Number of consonants: "<<c<<endl;
cout<<"Number of specials "<<s<<endl;
}
Then test it in the main function like
int main() {
string str = "some text . .";
printCharWithFreq(str);
return 0;
}
Basically, frequency is updated so it doesn't print the same character again, as it says in the comments. You also made a mistake in your code where you wrote:
character != 'a' || character != 'e' || character != 'i' || character != 'o' || character != 'u'
It is a consonant only if the input is different than ALL of the vowels, meaning you have to put &&, not ||.
As for the special characters, they can be counted with a simple counter.
The rest, I think, is clear from the comments in the code.
I adapted the code from the following source:
https://www.geeksforgeeks.org/print-characters-frequencies-order-occurrence/
I'm trying to solve a problem on a competitive programming book where the output only appears after entering in the last input. I seem to have gotten the logic down but I'm still confuse as to how to do the input/output portion.
Here is the code:
#include <bits/stdc++.h>
int main()
{
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
std::vector<int>soundex;
std::string word;
for(int i = 0; i < word.length(); i++)
{
if (word[i] == 'B'|| word[i] == 'F' || word[i] == 'P' || word[i] == 'V')
{
soundex.push_back(1);
}
if (word[i] == 'C' || word[i] == 'G' || word[i] == 'J' || word[i] == 'K' || word[i] == 'Q' || word[i] == 'S' || word[i] == 'X' || word[i] == 'Z')
{
soundex.push_back(2);
}
if (word[i] == 'D' || word[i] == 'T')
{
soundex.push_back(3);
}
if (word[i] == 'L')
{
soundex.push_back(4);
}
if (word[i] == 'M' || word[i] == 'N')
{
soundex.push_back(5);
}
if (word[i] == 'R')
{
soundex.push_back(6);
}
}
for (int j = 0; j < soundex.size(); j++)
{
if (soundex[j] == soundex[j+1])
{
soundex.erase(soundex.begin() + 1);
}
std::cout << soundex[j];
}
std::cout << "\n";
return 0;
}
It behaves like this:
Input:
KHAWN
Output:
25
Input:
PFISTER
Output:
1236
Input:
BOBBY
Output:
11
But I need it to behave like this, per the instructions of the problem:
Input:
KHAWN
PFISTER
BOBBY
Output:
25
1236
11
Use while(cin >> word){ ... your code ... } to read until EOF (End Of File) in case every line only contains a word (no spaces allowed). You can keep the output as it is.
I am solving a question which states: to change every '?' with 'a' in a string if doesn't contain if won't form consecutive 'a' else substitute with 'b', eg. a?b will be abb and not aab because here 2 a's are consecutive.
My problem is for i = 3 my string should be over- written with 'b ' according to my code it is entering into the desired block but the string does n't gets written with b, but in all the other case where it should be witten with 'a' it get's written .Help me out with these.
You can refer the problem statement from here to for better understanding my problem :https://www.hackerearth.com/practice/algorithms/greedy/basics-of-greedy-algorithms/practice-problems/algorithm/exploring-ruins/
#include <iostream>
using namespace std;
int main() {
string str;
cin >> str;
int n = str.size();
for(int i = 0; i < str.size(); i++) {
if(str[i] == '?') {
if(i == 0) {
if(str[i + 1] == 'a')
str[i] = 'b';
else
str[i] = 'a';
cout << "I am in if" << endl;
} else if(i == n - 1) {
if(str[i - 1] == 'a')
str[i] == 'b';
else
str[i] == 'a';
cout << "I am in if of else if " << endl;
} else {
if(str[i + 1] == 'a' || str[i - 1] == 'a') {
str[i] == 'b';
cout << "I am in if of else " << endl;
} else {
str[i] = 'a';
cout << "I am in else of else " << endl;
}
}
cout << str[i] << endl;
} else
continue;
}
cout << str << endl;
return 0;
}
Given string : ?ba??b
desired output : ababab
my output : aba?ab
It will be a lot easier for you if you would use functions to solve this problem.
bool check_neighbors_for_a(const string &str, size_t place) {
bool result = false;
if (place > 0) { // If there is a char before the current char
result = str[place - 1] == 'a'; // If the previous char is 'a' result become true
}
if (place < str.size() - 1) { // If there is a char after the current char
result = result || str[place + 1] == 'a'; // If the result has become true before this line, result will stay true. Else, result will be true if the next char is equal to 'a'.
// For example: b?a => result = (false || 'a' == 'a')
// For example: a?b => result = (true || 'b' == 'a')
// For example: a?a => result = (true || 'a' == 'a')
}
return result;
}
void replace_questions_by_a(string &str) {
for (size_t i = 0; i < str.size(); i++) {
if (str[i] == '?') {
if (check_neighbors_for_a(str, i)) { // If one of the neighbors is equal to 'a'
str[i] = 'b'; // Place 'b' instead of '?'
} else {
str[i] = 'a'; // Place 'a' instead of '?'
}
}
}
}
I have seen many good code to do this problem. I am new to coding. My question is where my logic went wrong. I think that problem is with second string str1. I din't initialize it. even when I am printing element by element withing if , it is working. but it is not working, when I am trying to print whole string str1.
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str = "Hello, have a good day", str1;
for (int i = 0, j =0; i < str.length(); ++i)
{
if((str[i]>='a'&& str[i]<='z') || (str[i]>='A'&& str[i]<='Z'))
if (str[i] == 'I' || str[i] == 'i' || str[i] == 'U' || str[i] == 'u' || str[i] == 'O' || str[i] == 'o' ||
str[i] == 'A' || str[i] == 'a' || str[i] == 'E' || str[i] == 'e' )
{
str1[j] = str[i];
//std::cout << str1[j] ;
j++;
}
else
{
str1[j] = str[i];
j++;
}
}
cout << str1 <<'\n';
}
output is just blank.
The first thing to do is to write a function that determines whether a character is a consonant:
bool is_not_consonant(char ch) {
static char consonants[] = "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ";
return std::find(std::begin(consonants), std::end(consonants), ch) == std::end(consonants);
}
Then use that function as a predicate to std::copy_if:
std::string result;
std::string input = whatever;
std::copy_if(std::begin(input), std::end(input),
std::back_inserter(result),
is_not_consonant);
Explanation
The problem is that you don't need the else condition. All you need to do is check for a vowel, and print if found which is rightly covered in your if condition.
Code
Try this:
#include<string>
using namespace std;
int main()
{
string str = "Hello, have a good day", str1;
for (int i = 0; i < str.length(); ++i)
{
if((str[i]>='a'&& str[i]<='z') || (str[i]>='A'&& str[i]<='Z'))
if (str[i] == 'I' || str[i] == 'i' || str[i] == 'U' || str[i] == 'u' || str[i] == 'O' || str[i] == 'o' || str[i] == 'A' || str[i] == 'a' || str[i] == 'E' || str[i] == 'e' )
{
str1 += str[i];
}
}
cout << str1 <<'\n';
}
Using the C++ language, the function LetterChanges(str) takes the str parameter being passed and modifies it using the following algorithm.
Replace every letter in the string with the letter following it in the
alphabet (ie. c becomes d, z becomes a). Then capitalize every vowel
in this new string (a, e, i, o, u) and finally return this modified
string.
#include <iostream>
using namespace std;
string LetterChanges(string str) {
// code goes here
string str2 = "abcdefghijklmnopqrstuvwxyz";
int j;
for (int i = 0; str[i] != '\0'; i++) {
for (j = 0; str2[j] != '\0'; j++) {
if (str[i] == str2[j]) {
str[i] = str2[j + 1];
}
}
}
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == 'a') {
str[i] = 'A';
}
else if (str[i] == 'e') {
str[i] = 'E';
}
else if (str[i] == 'i') {
str[i] = 'I';
}
else if (str[i] == 'o') {
str[i] = 'O';
}
else if (str[i] == 'u') {
str[i] = 'U';
}
}
return str;
}
int main() {
// keep this function call here
cout << LetterChanges(gets(stdin));
return 0;
}
I am trying to run this code but it is not giving the desire output please help..
The Function
Let's start with your first loop:
for (int i = 0; str[i] != '\0'; i++) {
for (j = 0; str2[j] != '\0'; j++) {
if (str[i] == str2[j]) {
str[i] = str2[j + 1];
}
}
}
There are a couple things here. Firstly, we don't even need to deal with str2. Characters in C++ use ASCII encoding, meaning we can actually do something like str[i]++ to change an 'a' to a 'b' or an 'e' to an 'f', etc...
Also, I'd advise against using str[i] != '\0'. We're using the standard library strings instead of c-strings for a reason, so we might as well make our lives easier and use str.size(). Along these same lines, I'd suggest str.at(i) as opposed to str[i] as the former will do bounds checking for us.
Lastly, if you include cctype, then we can use the isalpha function to make sure we're only modifying alphabetic characters (no numbers or spaces, etc..).
Thus your first loop can become:
for (int i = 0; i < str.size(); i++) {
if(isalpha(str.at(i)){
if(str.at(i) == 'z') str.at(i) = 'a'; //special case
else str.at(i)++;
}
}
As far as your second loop, you don't even need it! We can actually incorporate everything straight into the first one. As long as we make sure to do the vowel modification after we've changed the individual letters.
A conversion from lowercase to uppercase can be done with some ASCII math as well. The difference between the lowercase and uppercase letters is 'A'-'a', so if we add that to any lowercase letter, it'll give us its uppercase version!
With all of this, we can modify your code to:
for (int i = 0; i < str.size(); i++) {
if(isalpha(str.at(i)){ //Make sure it's a letter!
if(str.at(i) == 'z') str.at(i) = 'a'; //special case
else str.at(i)++;
if(str.at(i) == 'a' | str.at(i) == 'e' | str.at(i) == 'i'
| str.at(i) == 'o' | str.at(i) == 'u') {
str.at(i) += 'A' - 'a';
}
}
Your Main
There's only one thing to fix here. Don't use gets for input. If you're looking for a single word, use the extraction operator, >>, or if you want a whole line, use getline.
string word, line;
getline(cin, line);
cin >> word;
cout << LetterChanges(line) << endl;
cout << LetterChanges(word) << endl;