I have an algorithm that is supposed to take a string called str and check it against a specific rule defined as:
NOTHING comes after IX or IV.
It will print legal if the rule is not broken, and Illegal if the rule IS broken.
Here is my code that I have created:
string str = "MXCIVXX";
int length = str.length();
bool legal = true;
for (int i = 0; i < length; i++) {
if ((str[i] == 'I' && str[i + 1] == 'X') && (str[i + 2] != '/0'))
legal = false;
if ((str[i] == 'I' && str[i + 1] == 'V') && (str[i + 2] != '/0'))
legal = false;
}
if (legal == true)
cout << "Legal" << endl;
else if (legal == false)
cout << "Illegal" << endl;
I have tested multiple roman numerals in the string but it prints out legal if IX is followed by another character in the string. How can I fix this to confirm that IX or IV is not followed by another character?
You meant the null character, so '\0' instead of '/0'
Also, your approach is not accurate(read the below comments and thanks to #NathanOliver). This approach should work better:
int main()
{
std::string str = "IX";
int size = str.size();
bool legal = true;
if (str[size - 2] == 'I') // the char before the last char
{
if (str[size - 1] == 'V' || str[size - 1] == 'X') // the last char
legal = true;
else
legal = false;
}
else
legal = false;
if (legal)
std::cout << "Legal" << std::endl;
else
std::cout << "Illegal" << std::endl;
getchar();
return 0;
}
To check if "IX" or "IV" exist and if it does it is at then end of the string you can use std::string::find and check that it returns a position that is at the end of the string. So if we have a string like
std::string bad_str = "MXCIVXX";
and we use find like
std::size_t pos = bad_str.find("IV");
Then pos will either be std::string::npos meaning nothing was found or it will be the position of where it found "IV". You can check that by using
if (pos == std::string::npos || pos == bad_str.size() - 2)
std::cout << "good\n";
else
std::cout << "bad\n";
Then you just need to do this for "IX" as well. This avoids all the pitfalls that you could forget to handle in the manual version like going past then end of the string.
You can try the following code which will handle cases like "MIXCIXXIV" :
String str = "MXCIVXX";
int length = str.length();
bool legal = true;
for (int i = 0; i < length - 2; i++) {
if ((str[i] == 'I' && str[i + 1] == 'X') && length > i + 2){
legal = false;
break;
}
if ((str[i] == 'I' && str[i + 1] == 'V') && length > i + 2){
legal = false;
break;
}
}
if (legal == true)
cout << "Legal" << endl;
else if (legal == false)
cout << "Illegal" << endl;
Related
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.
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 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 '?'
}
}
}
}
For example, how do you count the occurrence of "TJ" in OAEKOTJEOTJ?
if (s[i] == 'TJ') and (s[i] == 'T'+'J')
x += 1;
First one gives me an error, second one doesn't count. I need a beginner solution to this, I haven't learned very much about c++ commands yet. Thanks
int x = 0
string s;
cin >> s;
for (int i = 0; i < 100; i++)
if (s[i] == T || s[i] == t) && (s[i+1] == J || s[i+1] == j)
x += 1
cout << x << endl;
That's the excerpt from my code, it doesn't count any tj, tJ, Tj or TJ
Try using:
if(s[i] == 'T' && s[i+1] == 'J') // and make sure you do not run out of bounds of string with index i.
x += 1;
EDIT:
Based on your code:
int x = 0
string s;
cin >> s;
for (int i = 0; i < 100; i++)
if (s[i] == T || s[i] == t) && (s[i+1] == J || s[i+1] == j)
x += 1
cout << x << endl;
You should do it like following:
int x = 0
string s;
cin >> s;
for (int i = 0; i < s.length()-1; i++) // use size of string s.length()-1 to iterate the string instead of 100
if (s[i] == 'T' || s[i] == 't') && (s[i+1] == 'J' || s[i+1] == 'j') // compare the ascii values of characters like - 'T' 'J' etc.
x += 1
cout << x << endl;
std::string provides a function find which searches the string for substrings, including multi-character substrings (below, I am using C++11 syntax):
#include <iostream>
#include <string>
int main()
{
using namespace std;
string text { "OAEKOTJEOTJ" };
unsigned int occ { 0 };
size_t pos { 0 };
for (;;) {
pos = text.find("TJ",pos); // Search for the substring, start at pos
if (pos == string::npos) // Quit if nothing found
break;
++pos; // Continue from next position
++occ; // Count the occurrence
}
std::cout << "Found " << occ << " occurrences." << std::endl;
}
The way it's done above we advance by one character only after each match. Depending on whether/how we want to deal with overlapping matches, we might want to advance pos by the length of the search pattern. (See chris's comment as well.)
Try this:
#include <locale> // for tolower() function
string tolower(string s) {
tolower(s[0]);
tolower(s[1]);
return s;
}
...
int main() {
string s;
cin >> s;
int n = s.size(),cont = 0;
for(int i = 0; i < n ; ++i) {
if(tolower(s.substr(i,2)) == "tj") {
++cont;
}
}
cout << cont << endl;
return 0;
}
float Calculate(const string &query)
{
std::cout << "Query: " << query << "\n";
unsigned int size = query.length();
char stack[70];
float res;
int m = 0;
for (int i = 0; i < size; i++)
{
if (query[i] >= '0' && query[i] <= '9')
{
stack[m] = query[i] - '0';
m++;
continue;
}
switch (query[i])
{
case '+':
{
res = stack[m - 2] + stack[m - 1];
break;
}
case '-':
{
res = stack[m - 2] - stack[m - 1];
break;
}
case '*':
{
res = stack[m - 2] * stack[m - 1];
break;
}
case '/':
{
res = stack[m - 2] / stack[m - 1];
break;
}
}
stack[m - 2] = res;
m--;
cout << "RES: " << res << "\n";
}
return res;
}
It calculates reverse polish notation.
When I call something like: Calculate("11+") it returns right result: 2.
But, when I pass a variable after getting of RPN string:
string inputStr;
string outputStr;
cout << "Put exercise\n";
getline(std::cin, inputStr);
outputStr = GetRPN(inputStr);
cout << "Output str :" << outputStr << ":\n";
float res = Calculate(outputStr);
std::cout << res << "\n";
So, when I input string: 1+1, function GetRPN returns 11+ and I see that in second cout. But result is 0!
What could it be?
string GetRPN(string input)
{
vector <char> operation;
string outputStr; //output string, keep RPN
int stack_count = 0;
for(int i = 0; i < input.length(); i++)
{
if(input[i] >= '0' && input[i] <= '9')
{
outputStr += input[i];
}
else
{
if(operation.empty())
{
operation.push_back(input[i]);
stack_count++;
}
else if(operation[stack_count - 1] == '+' || operation[stack_count - 1] == '-')
{
operation.push_back(input[i]);
stack_count++;
}
else if ((operation[stack_count - 1] == '*' || operation[stack_count - 1] == '/') && (input[i] == '*' || input[i] == '/'))
{
outputStr += operation[stack_count - 1]; // move mark of operation to output str
operation.pop_back(); // delet last element from vector
operation.push_back(input[i]);// plus new operation mark to vector
stack_count++;
}
else if (operation[stack_count - 1] == '*' || operation[stack_count - 1] == '/')
{
outputStr += input[i];
}
}
}
for(int i = operation.size(); i >= 0; i--)
{
outputStr += operation[i]; // move all operation marks to otput str
}
return outputStr;
}
Your cycle here
for(int i = operation.size(); i >= 0; i--)
{
outputStr += operation[i]; // move all operation marks to otput str
}
does not make any sense. You are obviously attempting to access the vector at invalid index. It is illegal to access the element at operation[i] when i is equal operation.size(). The index is out of range.
Any self-respecting implementation would immediately report this problem with an assertion. In any case, as I said in the comment, the problems like that are resolved by debugging the code. Why are you asking other people to debug your code instead of doing it yourself?
If your string has any whitespace or unprintable characters in it, you'll end up storing into stack with a negative index, which will overwrite other stuff in your stack frame and could cause anything to happen.
You should add some error checking to Calculate -- the switch should have a default that prints a sensible error message, and you should check the value of m before accessing stack[m] or stack[m-2] to make sure the stack doesn't underflow or overflow (and you should print a sensible error if it does.) You should be able to pass ANY random string to Calculate and have it tell you why its not a valid RPN expression.