Why I am not getting desired output for my c++ problem - c++

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 '?'
}
}
}
}

Related

How do I modify an input through multiple functions in C++?

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.

Change a bunch of numbers into corresponding alphabets

There are five types of bit encoding: 11, 10, 01, 001, 000.The corresponding message for each bit encoding is
11 -> A
10 -> B
01 -> C
001 -> D
000 -> E
The compile result will look like this:
Enter a sequence of bits: 01100001100110
CBEADB
I've wrote this but it can't work.
#include<iostream>
#include<string>
using namespace std;
int main()
{
int A, B, C, D, E ;
string code;
cout << "Enter a sequence of bits: ";
cin >> code;
int i = 0;
while (i < code.length())
{
if( code[i]== 1 && code[i + 1]== 1 )
{
cout << 'A';
i += 2;
}
else if ( code[i]== 1 && code[i + 1]== 0)
{
cout << 'B';
i += 2;
}
else if ( code[i]== 0 && code[i + 1]== 1)
{
cout << 'C';
i += 2;
}
else if ( code[i]== 0 && code[i + 1]== 0 && code[ i + 2]== 1)
{
cout << 'D';
i += 3;
}
else if ( code[i]== 0 && code[i + 1]== 0 && code[ i + 2]== 0)
{
cout << 'E';
i += 3;
}
}
cout << endl;
return 0;
}
Your input is a String not numbers, therefore you have to check for characters. Instead of using something like == 0, you should be using something like == '0'. Also, you may want to make sure that the input has the right format and you don't run into an infinite loop (by running the while forever without updating i) or buffer overflow (aka. index out of range, by checking code[i] with i >= code.length()). You can do something like:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int A, B, C, D, E ;
string code;
cout << "Enter a sequence of bits: ";
cin >> code;
int i = 0;
while (i+1 < code.length())
{
if( code[i]== '1' && code[i + 1]== '1' )
{
cout << 'A';
i += 2;
}
else if ( code[i]== '1' && code[i + 1]== '0')
{
cout << 'B';
i += 2;
}
else if ( code[i]== '0' && code[i + 1]== '1')
{
cout << 'C';
i += 2;
}
else if (i+2 < code.length())
{
if (code[i]== '0' && code[i + 1]== '0' && code[ i + 2]== '1')
{
cout << 'D';
i += 3;
}
else if ( code[i]== '0' && code[i + 1]== '0' && code[ i + 2]== '0')
{
cout << 'E';
i += 3;
}
else
{
return 1;
}
}
else
{
return 1;
}
}
if (i < code.length()) {
return 1;
}
cout << endl;
return 0;
}
You can try it out here.
You code is correct, you simply need to use character literals instead of int literals, for example:
if (code[i] == '1' && code[i + 1] == '1')
Digits, in strings, have codes that don't match their integral value. '0' is not 0. As such, you must use '0' and '1'.

Counting occurrence of each character in string C++

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/

Checking if IX or IV are followed by another character

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;

Post fix calculator, returns wrong value

I'm Writing a program to implement postfix calculator, its giving me completely wrong answers.
Really appreciate the help
class stacks {
public:
typedef int List;
static const int size = 100;
stacks() {
use = 0;
}
void push(List entry) {
data[use] = entry;
++use;
}
List pop() {
if(!empty()) {
--use;
return data[use];
}
}
bool empty() const {
return use == 0;
}
int Size() const {
return use;
}
private:
List data[size];
int use;
};
int main() {
stacks s;
string input;
int final;
ifstream infile("foo.txt",ios::in);
while (getline(infile, input))
cout << "Expression: ";
for (int i = 0; i<input.length(); i++) {
cout << input[i];
auto oper1 = s.pop();
auto oper2 = s.pop();
if(input[i] == '1' || input[i] == '2' || input[i] == '3' || input[i] == '4' || nput[i] == '5' || input[i] == '6' || input[i] == '7' || input[i] == '8' || input[i] == '9')
s.push(input[i] - '0');
if(input[i] == '+')
s.push(oper1 + oper2);
if(input[i] == '-')
s.push(oper1 - oper2);
if(input[i] == '*')
s.push(oper1 * oper2);
if(input[i] == '/')
s.push(oper1 / oper2);
}
final = s.pop();
cout << endl << "Value = " << final << "." << endl << endl;
}
What do you recommend?
Thanks
You need to wait to pop() until you know you have an operator. You're popping stuff off the stack when you shouldn't be.