How to use enqueu, dequeue, push, and peek in a Palindrome? - c++

I'm writing a program to see if a string is a palindrome. I'm having trouble with the implementing the queue.enqueue(nextCharacter), stack.push(nextCharacter), queueFront = queue.peekFront(), stackTop = stack.peek(), queue.dequeu(). I tried looking at examples online of implementations of peek(), deque, push, and enqueue. Could not find any that worked correctly. I have to follow this exact format of this program.
// Start of Pseudcode given:
isPalindrome(someString: string): boolean
{
// Create an empty queue and stack
aQueue = new empty queue
aStack = new empty stack
// Add each character of string to both queue and stack
length = length of someString
for (i= 1 throught length)
{
nextChar = ith character of someString
aQueue.enqueue(nextChar)
aStack.push(nextChar)
}
charactersAreEqual=true
// Compare queue characters with stack characters
while (aQueue is not empty and charactersAreEqual)
{
queueFront = aQueue.peekFront();
stackTop = aStack.peek()
if(queueFront equals stackTop)
{
aQueue.dequeue();
aStack.pop()
}
else {
charactersAreEqual = false
}
#include <string>
#include <queue>
#include <stack>
#include <iostream>
bool isPalindrome(std::string str) {
// Declare variables
int length;
char nextCharacter;
bool charactersEqual;
char queueFront;
char stackTop;
// Create an empty queue and stack
std::queue<char> queue;
std::stack<char> stack;
// Set lenth to length of string
length = str.length();
// Add each character of string to both queue and stack
for (int i = 0; i < length; i++) {
nextCharacter = str.at(i);
queue.enqueue(nextCharacter); // ??????
stack.push(nextCharacter); // ?????
}
// Set characters to true
charactersEqual = true;
// Compare queue characters with stack characters
while (!queue.empty() && charactersEqual) {
queueFront = queue.peekFront(); // ?????
stackTop = stack.peek(); // ?????
if (queueFront == stackTop) {
queue.dequeu(); // ?????
stack.pop();
}
else {
charactersEqual = false;
}
}
return charactersEqual; // return characters that are equal
}

For an ASCII string, you can:
bool result = std::equal(str.begin(), str.end(), str.rbegin(), str.rend());
If you are using Unicode then you should probably reverse the whole string then use the equality operator:
bool isPalindrome(std::u8string str)
{
// Less efficient
std::u8string rstr{str};
std::reverse(rstr.begin(), rstr.end());
return (str == str2);
}
For instance, is 'é' and 'e' the same letter? In Dutch, "één hond" and "een hond" are the same because the first means "one dog" and the second can mean either "one dog" or "a dog" depending on the context. Therefore, you need to be careful if you need internationalization.

Here's a snippet from a program I wrote a while ago that checks if a word is a palindrome. I know it's not what you're asking for, but I figured I'd put it out there.
bool isPalindrome(const string word)
{
for (int i = 0, j = word.length() - 1; i < j; i++, j--)
{
if (word[i] != word[j]) //If any comparison fails, return false
return false;
}
//If all the checks passed, return true
return true
}

Related

I am Not able to find out where this code went wrong

This code is supposed to convert a given postfix expression to a prefix expression,i was experimenting with the string object in c++ but I don't have enough experience to figure out the problem
I think there's an issue in the push() function
Note:I haven't used the stack header file and implemented the stack using array
here's the code
#include <bits/stdc++.h>
#include <iostream>
#define MAX 5
using namespace std;
class stack1
{
private:
int stackTop,expTop;
string stack[MAX],expression;
public:
stack1()
{
stackTop = -1;
for (int i = 0; i < MAX; i++)
{
stack[i] = " ";
}
getexp();
check(expression);
display();
}
string pop();
void push(string expr);
void display();
bool isempty();
bool isfull();
string combo(string optr1,string optr2,string opr);
void getexp();
void check(string expre);
bool isOperator(string ch);
};
//-----------Gets Expression From User------------------------------------------
void stack1::getexp()
{
cout<<"Enter the Postfix Expression"<<endl;
cin>>expression;
expTop=expression.length()-1;
}
void stack1::check(string expre)
{
string ch;
int i=0;
while(expre[i]!=(expre.length()-1))
{
ch=expre[i];
if(isOperator(ch))
{
push(combo(pop(),ch,pop()));
}
else
{
push(ch);
}
}
}
/*
-------------------------------------------------------------------
Inputs:
takes 2 values from the stack which will be operands
either as single characters or whole strings,these
values will be passed as optr1 and opttr2,it will
also take operators such as +,-,* etc.. as char.
these will be passed in place of opr.
working:
combines all the passed values into a single string
into the following format
( optr1 opr optr2 )
and finaly returns this string
----------------------------------------------------------------------
*/
string stack1::combo(string optr1, string optr2, string opr)
{
string expr;
expr="("+optr1+opr+optr2+")";
return expr;
}
/*
------------------------------------------------------------------------
Working:
pops the top value from the stack
and returns it.
decrements the top pointer
and initializes the poped element to " "
-------------------------------------------------------------------------
*/
string stack1 ::pop()
{
string x;
if (isempty())
{
cout << endl
<< "The stack1 is empty" << endl;
}
x=stack [stackTop];
stack [stackTop] = " ";
stackTop--;
return x;
}
void stack1 ::push(string expr)
{
stackTop++;
stack [stackTop] = expr;
}
bool stack1 ::isempty()
{
if (stackTop == -1)
return true;
else
return false;
}
bool stack1 ::isfull()
{
if (stackTop == MAX - 1)
return true;
else
return false;
}
bool stack1::isOperator(string ch)
{
if (ch[0] == '*' || ch[0] == '/' || ch[0] == '+' || ch[0] == '-' || ch[0] == '^')
return true;
else return false;
}
void stack1::display()
{
cout<<"Infix:\t"<<stack[0]<<endl;
}
int main()
{
stack1 obj;
return 0;
}
Besided the obvious hard bug with #include <bits/stdc++.h> which is not part of C++ (and does not even compile on my machine), you have 2 semantic bugs in your code, which lead to a problem.
Additionally you have a design problem leading to an only partially solution.
And, maybe a misunderstanding of the terms and meaning of "string" and "character"
Example: The string "hello" consists of 5 characters: 'h', 'e', 'l', 'l', 'o'
If you use a std::string and initialize it with "hello" (which is of type const char[6]), the the constructor of the std::string will convert your character array to a std::string, containing the following characters at indices:
index character
0 'h'
1 'e'
2 'l'
3 'l'
4 'o'
5 '\0'
In your "check" function in line while(expre[i]!=(expre.length()-1)) you access expre[i] which is a character (for example an 'a') and compare it to the length of the std::string "expre". This can of course not work.
The while loop will never terminate. "i" is always the same and you will push always the first character of the input string onto the stack, unti it is full and you get an exception. You should add an overflow-check in your push function.
Additionally, you use a wrong parameter sequence in/with your "combo" function.
If you modify the while loop like the below, then at least this part will work.
string ch;
int i = 0;
//while (expre[i] != (expre.length() - 1))
while (i != (expre.length()))
{
ch = expre[i];
if (isOperator(ch))
{
push(combo(pop(), pop(),ch));
}
else
{
push(ch);
}
++i;
}
Now you can successfully convert "abcd+^" to "(a^(b(c+d)))".
But still, it will not work fully.
Additionally:
You should use your constructor only to initialize your class.
Please use characters where appropriate and not full std::strings
The whole design needs to be reworked.
Because: basically you are creating an infix and not a prefix expression.
Hence, for learning purposes look at here

Check if every string in a set contains equal number of 'a' and 'b' okay I tried again will some one work something out now?

Will some one explain or make a program in c++ of this for me? Got assignment but don't know how to do it.
Question: You are given a set of strings which contain only as and bs, your program should be able to check whether each string has the same number of as and bs in it or not.
e.g. The program will respond true if it get {ab, aabb, aaabbbb, bbbaaa} and say false when it gets {aab, bbba, aaabbbb}
Solve it using stack
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
int count1 = 0;
int count2 = 0;
bool isInLanguageL (string w);
int main()
{
string input;
cout << "Input any string; ";
getline(cin,input);
if (input.length() % 2 != 0)
cout <<"Pattern entered does not match the language ";
else
isInLanguageL(input);
return 0;
}
bool isInLanguageL (string w)
{
stack<string> word1, word2;
string a, b;
for (unsigned i = 0; i < w.length()/2; i++)
{
a = w.at(i);
word1.push(a);
}
reverse(w.begin(), w.end());
for (unsigned i = 0; i < w.length()/2; i++)
{
b = w.at(i);
word2.push(b);
}
while(!word1.empty() && !word2.empty())
{
word1.pop();
count1 = count1++;
word2.pop();
count2 = count2++;
}
if(count1 == count2)
return true;
else
return false;
}
This solution is using stack, please refer to the comments written in the code. If you have any doubt you can comment them.
Code:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
void checkString(string s) {
if (s.size() % 2 != 0) {
cout << "Doesn't satisfy the conditon\n";
return;
}
stack<char> st;
int n = s.size();
for (int i = 0; i < n; ++i) {
/*
case - 1 : If the stack is empty you can directly push the current character into the stack
case - 2 : If there are elements present in the stack, then if the current character is equal to the top character on the stack then we can push the current character
beacuse we didn't find any new character to match them.
*/
if (st.empty() || (st.top() == s[i])) {
st.push(s[i]);
}
/*
case-3 : If the stack is not emtpy and current character is different from the top character on the stack then we found a match like a-b (OR) b-a, so then we will
remove the top element from the stack and move to next character of the string
*/
else if (st.top() != s[i]) {
st.pop();
}
}
/*
case - 1 : After iterating through all the characters in the string, if we find the stack is emtpy then we can say all characters are not matched
case - 2 : If stack is emtpy, then that means all the characters are matched.
*/
(st.empty()) ? (cout << "Yes, satisfies the conditon\n") : (cout << "Doesn't satisfy the conditon\n");
}
int main() {
string s = "";
cin >> s;
checkString(s);
return 0;
}
Your solution has a number of mistakes that you should probably solve by using a debugger. Here's a reference.
This solution doesn't use a stack as you asked for, but you can write this function that uses algorithms to solve your problem:
namespace rs = std::ranges;
bool all_equal_as_and_bs(auto const & strings)
{
return rs::all_of(strings, [](auto const & string)
{
return rs::count(string, 'a') == rs::count(string, 'b');
});
}
And use it like this:
all_equal_as_and_bs(std::vector<std::string>{"ab", "aabb", "aaabbb", "bbbaaa"}); // true
all_equal_as_and_bs(std::vector<std::string>{"aab", "bba", "aaabbbb", "bbbaaa"}); // false

Trie find/add function not working properly

I am trying to implement a search function for my trie tree data structure. I am confused on how to properly implement this, as I assume my logic seems correct right now...although I am still a beginner in this. If someone can take a look at my function, and suggest where to improve, that would be greatly appreciated. The main takes in large word files and then searches for words in it to test the function basically. Right now it returns false for a word that should be in the trie object.
example error message
Error: jean-pierre is not in the spellcheck and it should have been
search function:
//looks up the word in the SpellCheck object. If it is in the SpellCheck object,true is returned.
//You can assume that the word will be all lower case.
bool lookup(const string& word) const {
if (!root_) {
return false;
}
Node* curr = root_;
if (word[0] == '\0') {
return curr->isTerminal_ == true;
}
for (int i = 0; i < word.length(); i++)
{
int idx = curr->getIndex(word[i]);
if (idx < 0 || idx >= 26){
return false;
}
// Search top level for node that
// matches first character in key
if (curr->children_[idx] == nullptr) {
return false;
}
curr = curr->children_[idx];
}
return curr->isTerminal_ == true;
}
Node struct:
struct Node {
bool isTerminal_;
char ch_;
Node* children_[26];
Node(char c = '\0') {
isTerminal_ = false;
ch_ = c;
for (int i = 0; i < 26; i++) {
children_[i] = nullptr;
}
}
//given lower case alphabetic charachters ch, returns
//the associated index 'a' --> 0, 'b' --> 1...'z' --> 25
int getIndex(char ch) {
return ch - 'a';
}
};
Node* root_;
You have multiple bugs in your implementation.
Your addWord function isn't correct.
This one should be better:
void addWord(const string& newWord, int currChar, Node* rt)
{
//check if currChar index is still in newWord
if (currChar < newWord.length()) {
//find index of currChar
char currLetter = newWord[currChar];
int idx = rt->getIndex(currLetter);
//if no letter at that index create a new node
if (!rt->children_[idx])
//make a new node
rt->children_[idx] = new Node(currLetter);
//continue to add
addWord(newWord, currChar + 1, rt->children_[idx]);
}
else
rt->isTerminal_ = true; //last char
}
The other bug you totally missed: "jean-pierre" contains non a-z characters :) and your getIndex will fail for any char that's not within [a-z] range.
The other points:
do not hardcode values like 26, because if you need to update your
range from [a-z] code elsewhere will silently fail.
use assert to check input assumptions.
Something like this:
int getIndex(char ch)
{
assert(ch >= 'a' && ch <= 'z');
return ch == '-' ? 26 : ch - 'a';
}

Code checking the result of std::unordered_set::find won't compile

I am writing a program to determine whether all characters in a string are unique or not. I am trying to do this using an unordered_set. Here is my code:
#include <iostream>
#include <unordered_set>
#include <string>
using namespace std;
bool uniqueChars(string word) {
unordered_set<char> set;
for (int i = 0; i < word.length(); i++) {
auto character = set.find(word[i]);
// if word[i] is found in set then not all chars are unique
if (character == word[i]) {
return false;
}
//else add word[i] to set
else {
set.insert(word[i]);
}
}
return true;
}
int main() {
string word;
getline(cin, word);
bool result = uniqueChars(word);
return 0;
}
It is giving me this error:
|15|error: no match for 'operator==' (operand types are 'std::__detail::_Node_iterator' and 'char')|
I believe that means that character is not comparable to word[i], but I'm not sure.
How do I make this work?
Note that std::unordered_set::find returns an iterator, not the element. It can't be compared to the element directly.
You could check whether the element was found or not by comparing the iterator with std::unordered_set::end. e.g.
auto character = set.find(word[i]);
// if word[i] is found in set then not all chars are unique
if (character != set.end()) {
return false;
}
//else add word[i] to set
else {
set.insert(word[i]);
}
BTW: Better not to use set as the name of variable, which is the name of another STL container.
Take advantage of the return value of insert. It tells you whether a duplicate was found during insertion (in which case nothing is inserted).
bool uniqueChars(string word) {
unordered_set<char> set;
for ( char c : word ) {
if ( ! set.insert( c ).second ) {
return false; // set didn't insert c because of a duplicate.
}
}
return true; // No duplicates.
}
However, this isn't as efficient as it might look. unordered_set is a heap-based hash table and its implementation is fairly heavyweight. A lightweight bit-vector works well for classifying characters.
#include <bitset>
constexpr int char_values = numeric_limits< char >::max()
- numeric_limits< char >::min() + 1;
bool uniqueChars(string word) {
bitset< char_values > set;
for ( char c : word ) {
int value_index = c - numeric_limits< char >::min();
if ( set[ value_index ] ) {
return false;
} else {
set[ value_index ] = true;
}
}
return true; // No duplicates.
}
*character == word[i]
( This is the way to access the characters but it is not needed and it
should be guided by a check whether it points to the past to the last
element)
The *charcater is basically referencing the already inserted charcater.
if(character != set1.end() )
return false; // as we are sure that it is not unique character string
You have to dereference it. but in that case you also need to do the whether it return iterator pointing to `set::end``.
By the way there is a really a simple way to do what you are trying to do.
bool uniqueChars(string word) {
unordered_set<char> set1;
for (int i = 0; i < word.length(); i++)
auto character = set1.insert(word[i]);
return set1.size()==word.length();
}
"set" is a key word in c++

C++, count repeated words in the string and display

I have string say "walk talk, can't won't Won't woN'T talk." I want to count the reapeated words and display.
Note: it is not case sensitive.
I have used delimeter
strtok(string, ",.;:\"!? -_\n\t*()##=+");
and saved it in
char *temp[100];
Now how can I check for repeatation of words? And display as below
3 won't
2 talk
1 can't
1 walk
it should display from highest repeat to lowest. And if the repeatation is same then display alphabetic order.
Sorry for my bad english.
Use a std::string to hold the result of the strtok(). Then create a std::map<string, int> to hold the count of the times the string (the key) has occurred.
You can populate the map with:
std::map<string, int> myMap;
myMap[tokenizedWord]++; //Increase count of word.
You can then cycle through the map content and print out wherever the integer value is greater than 2.
for (std::map<string, int>::iterator iter = myMap.begin(); iter != myMap.end(); ++iter)
{
if (iter->second > 1)
std::cout << "Duplicated word: " << iter->first << " count = " << iter->second;
}
I'll let you figure out how to traverse it in order. You can put the values in a vector or something and use std::sort before printing or whatever else you like. Maps, unfortunately, are associative containers and you can't sort them as it breaks their internal ordering.
Background Info on std::map
A map is an associative array meaning that every key maps to a specific value, and keys are unique. You can actually create a multimap where keys are not unique, so that's why this is important.
Basically, since keys are unique, you can access or create an element just by using the key as the array index.
For example:
//Create a map and insert a couple things into it - prices of meat?
std::map<string, float> myMap;
myMap["Chicken"] = 4.99;
myMap["Turkey"] = 6.99;
//Retrieve the price of something using the key.
std::cout << "Chicken costs " << myMap["Chicken"] << std::end;
You can do standard insertion and location operations on a map too, but the associative array syntax is just simpler, so why bother? :)
PS: To fully answer your comment, just in case, the ++ at the end of myMap[tokenizedWord]++ is just saying to increment the value of the integer value stored for that key by 1. You could just as well do myMap[tokenizedWord] = myMap[tokenizedWord] + 1 OR you could also do myMap[tokenizedWord] += 1.
a complete implementation of your problem (Let me know if you want a sample code for sorting):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define ARRAY_ELEMS_COUNT(A) sizeof(A)/sizeof(*A)
typedef struct _word_t
{
char *word;
int occurr_count;
struct _word_t *next;
} word_t;
typedef struct _word_list_t
{
struct _word_t *head;
struct _word_t *tail;
int elems_count;
} word_list_t;
/* Creation of the words list */
word_list_t *make_list(void)
{
word_list_t *w_list = (word_list_t *)malloc(sizeof (struct _word_list_t));
if (w_list == NULL)
{
fprintf(stderr, "malloc faild --> %s\n", strerror(errno));
return NULL;
}
w_list->head = w_list->tail = NULL;
w_list->elems_count = 0;
return w_list;
}
int list_word_lookup(word_list_t *w_list, char *word)
{
word_t *temp_word = w_list->head;
while(temp_word)
{
if (strcmp(temp_word->word, word) == 0)
{
/* We got it before, increment the count */
temp_word->occurr_count++;
return 1;
}
else
{
temp_word = temp_word->next;
}
}
return 0;
}
/* Adding new words to the list of words if they are not present, otherwise increment their occurrence count */
/* TODO : Sort the list using Merge sort for performance */
int adding_to_list(word_list_t *w_list, char *word)
{
int return_status = 0;
char *tmp_word = (char *)malloc(sizeof(char)*(strlen(word) + 1));
word_t *new_word = (word_t *)malloc(sizeof(struct _word_t));
/* Empty list */
if (w_list->head == NULL)
{
strcpy(tmp_word, word);
new_word->word = tmp_word;
new_word->occurr_count = 1;
w_list->head = w_list->tail = new_word;
w_list->head->next = NULL;
w_list->elems_count++;
}
else
{
/* The list is not empty */
/* Checking if the word exist in the list */
return_status = list_word_lookup(w_list, word);
if (return_status == 1)
{
fprintf(stdout, "WE got this word before --> increment count\n");
}
else
{
strcpy(tmp_word, word);
new_word->word = tmp_word;
new_word->occurr_count = 1;
w_list->tail->next = new_word;
w_list->tail = new_word;
w_list->tail->next = NULL;
}
}
return 0;
}
void words_list_dump(word_list_t *w_list)
{
word_t *temp;
for (temp = w_list->head; temp; temp = temp->next) {
fprintf(stdout, "Word : %s -- Count = %d\n", temp->word, temp->occurr_count);
}
}
/* Destroying all words */
void free_words(word_list_t *w_list)
{
word_t *temp;
for (temp = w_list->head; temp; temp = temp->next) {
/* Freeing the word string */
free(temp->word);
/* Freeing the word */
free(temp);
}
w_list->head = NULL;
w_list->tail = NULL;
}
/* Destroying the words list */
void free_words_list(word_list_t *w_list)
{
if (!w_list)
{
return;
}
free_words(w_list);
free(w_list);
}
/* TODO : create a function that converts your input text to a char ** array, so you can pass it to adding_to_list */
/* For testing */
int main(int argc, char **argv)
{
const char *string[] = {"Hello", "World", "Stackoverflow", "C", "Hello", "C", "WORDS", "words", "List", "list", "Hello", "World", "Count"};
word_list_t *my_list = make_list();
int i;
for (i = 0; i < ARRAY_ELEMS_COUNT(string); i++)
adding_to_list(my_list, string[i]);
words_list_dump(my_list);
free_words_list(my_list);
return 0;
}
Here is an answer using strtok but without std::map. In one pass of string, every word in is checked against previous words and repeats are counted.
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <cstring>
using std::tolower;
int main()
{
char *strin;
string inputstr;
vector<string> svec;
vector<int> cvec;
char *pch;
int unique_word_count=0;
while(getline(cin,inputstr))
{
//token-ize the string
//First string
strin = &inputstr[0];
pch = std::strtok(strin," ,-");
bool unique_word_found = true;
//subsequent words
while (pch != NULL)
{
string word(pch);
for(string::size_type i=0; i < word.size(); i++)
word[i]=tolower(word[i]);
//first word
//just add to svec and no comparisons
if(unique_word_count==0)
{
svec.push_back(word);
cvec.push_back(1);
cvec[unique_word_count++]=1; //init count of first word
//next word
pch = std::strtok(NULL, " ,-");
unique_word_found = true; //reset flag
continue;
}
//start comparing with other words currently in string vector
//do not do this if only 1 word present
vector<string>::iterator iter=svec.begin();
while(iter < svec.end())
{
if(word == *iter)
{
//match found
cvec[iter-svec.begin()]++; //increment count of that word
unique_word_found = false;
}
iter++;
}
if(unique_word_found)
{
//add to unique word list and increment count
svec.push_back(word);
cvec.push_back(1);
cvec[unique_word_count++]=1;
}
//next word
pch = std::strtok(NULL, " ,-");
unique_word_found = true; //reset flag
}
}
cout << "Word" << " ---> " << "Occurences" << endl;
for(vector<string>::size_type i=0; i < svec.size(); i++)
{
cout << svec[i] << " ---> " << cvec[i] << endl;
}
return 0;
}
The general strategy can be as follows:
Sanitize the input (convert all characters to lower case, remove unwanted punctuation, etc.)
Walk through the input
Add each character to a string, finalizing when a space is encountered
Add the string to a key-value structure. The string is the key. If this is a new entry not already contained in the structure, set the value 1. Otherwise set it to the current value + 1 (so as to count the number of times encountered so far).
Repeat for each word
Walk through the key-value structure and print each entry.