Related
I have a function that takes in two vectors of strings and compares each element to see if they are anagrams of one another.
Vector #1: "bat", "add", "zyz", "aaa"
Vector #2: "tab", "dad", "xyx", "bbb"
Restrictions and other things to clarify: The function is supposed to loop through both vectors and compare the strings. I am only supposed to compare based on the index of each vector; meaning I only compare the strings which are in the first index, then the strings which are in the second index, and so on. It's safe to assume that the vectors passed in as parameters will always be the same size.
If the compared strings are anagrams, "Match" is printed on the screen. If they aren't, "No Match" is printed.
Output: Match Match No Match No Match
I'm getting ridiculously stuck on this problem, I know how to reverse strings but when it gets to this I'm getting a bit clueless.
I understand that I would need to iterate through each vector, and then compare. But how would I be able to compare each letter within the string? Also, I'm not allowed to include anything else like algorithm, sort, or set. I've tried digging through a lot of questions but most answers utilized this.
If there are any tips on how to solve this, that would be great. I'll be posting what I find shortly.
Here's what I got so far:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void anagrams(const vector<string>& vOne, const vector<string>& vTwo){
for(int i=0; i< vOne.size(); i++){
for(int j=0; j< vTwo.size(); j++){
if(vOne[i].size() != vTwo[j].size()){
cout << 0 << endl;
}
else {
cout << 1 << endl;
}
}
}
}
void quicksort(vector<int>& a, int low, int high){
if(low < high)
{
int mid = (low + high)/2;
int pivot = a[mid];
swap(a[high], a[mid]);
int i, j;
for(i=low, j=high-1; ;){
while(a[i]<pivot) ++i;
while(j>i && pivot < a[j]) --j;
if (i < j)
swap(a[i++], a[j--]);
else
break;
}
swap(a[i], a[high]);
}
quicksort(a, low, i - 1);
quicksort(a, i + 1, high);
}
Thanks in advance!
Though you are not able to use sort, you should still sort the the words you are checking against, to see if they are anagrams. You will just have to sort the char[] manually, which is unfortunate, yet a good exercise. I would make a predicate, a function that compares the 2 strings and return true or false, and use that to check if they are anagrams. Also, it seems as though you don't need to print out both words that actually match, if that is true, then you can sort the words in the vectors when you first read them in, then just run them through your predicate function.
// Predicate
bool isMatch(const string &lhs, const string &rhs)
{
...sort and return lhs == rhs;
}
If you write the function, as I have above, you are passing in the parameters by const reference, which then you can copy (not using strcpy() due to vulnerabilities) the parameters into char[] and sort the words. I would recommend writing your sort as its own function.
Another hint, remember that things are much faster, and stl uses smart ptrs to do sorting. Anyway, I hope this helps even a little bit, I didn't want to give you the answer.
A solution that is fairly quick as long as the strings only contain characters between a-z and A-Z would be
bool is_anagram( const string& s1, const string& s2 ) {
if( s1.size() != s2.size() ) {
return false;
}
size_t count[ 26 * 2 ] = { 0 };
for( size_t i = 0; i < s1.size(); i++ ) {
char c1 = s1[ i ];
char c2 = s2[ i ];
if( c1 >= 'a' ) {
count[ c1 - 'a' ]++;
}
else {
count[ c1 - 'A' + 26 ]++;
}
if( c2 >= 'a' ) {
count[ c2 - 'a' ]--;
}
else {
count[ c2 - 'A' + 26 ]--;
}
}
for( size_t i = 0; i < 26 * 2; i++ ) {
if( count[ i ] != 0 ) {
return false;
}
}
return true;
}
If you're willing to use C++11, here is some rather inefficient code for seeing if two strings are anagrams. I'll leave it up to you to loop through the list of words.
#include <iostream>
#include <vector>
using namespace std;
int count_occurrences(string& word, char search) {
int count = 0;
for (char s : word) {
if (s == search) {
count++;
}
}
return count;
}
bool compare_strings(string word1, string v2) {
if (word1.size() != v2.size())
{
return false;
}
for (char s: word1) //In case v1 contains letters that are not in v2
{
if (count_occurrences(word1, s) != count_occurrences(v2, s))
{
return false;
}
}
return true;
}
int main() {
string s1 = "bat";
string s2 = "atb";
bool result = compare_strings(s1, s2);
if (result)
{
cout << "Match" << endl;
}
else
{
cout << "No match" << endl;
}
}
This works by simply counting the number of times a given letter occurs in a string. A better way to do this would be to sort the characters in the string alphabetically, and then compare the sorted strings to see if they are equal. I'll leave it up to you to improve this.
Best wishes.
Another solution, since I'm sufficiently bored:
#include <iostream>
#include <vector>
#include <string>
int equiv_class(char c) {
if ((c>='A')&&(c<='Z')) return c-'A';
if ((c>='a')&&(c<='z')) return c-'a';
return 27;
}
bool is_anagram(const std::string& a, const std::string& b)
{
if (a.size()!=b.size()) return false;
int hist[26]={};
int nz=0; // Non-zero histogram sum tally
for (int i=0, e=a.size() ; i!=e ; ++i)
{
int aclass = equiv_class(a[i]);
int bclass = equiv_class(b[i]);
if (aclass<27) {
switch (++hist[aclass]) {
case 1: ++nz; break; // We were 0, now we're not--add
case 0: --nz; break; // We were't, now we are--subtract
// otherwise no change in nonzero count
}
}
if (bclass<27) {
switch (--hist[bclass]) {
case -1: ++nz; break; // We were 0, now we're not--add
case 0: --nz; break; // We weren't, now we are--subtract
// otherwise no change in nonzero count
}
}
}
return 0==nz;
}
int main()
{
std::vector<std::string> v1{"elvis","coagulate","intoxicate","a frontal lobotomy"};
std::vector<std::string> v2{"lives","catalogue","excitation","bottlein frontofme"};
for (int i=0, e=(v1.size()==v2.size()?v1.size():0); i!=e; ++i) {
if (is_anagram(v1[i],v2[i])) {
std::cout << " Match";
} else {
std::cout << " No Match";
}
}
}
I need to find the Lexicographically largest string out of the given input string.
So if the input is
enjoy
the o/p should be
yenjo
The code i tried was....
int n;
cout<<"Enter the number of strings";
cin>>n;
int len[n];
char str[n][1000];
for(int i=0;i<n;i++)
{
cin>>str[i];
len[i]=strlen(str[i]);
}
int num,pos[n];
for(int i=0;i<n;i++)
{
pos[i]=0;
num=int(str[i][0]);
for(int j=1;j<len[i];j++)
{
if(int(str[i][j])>num)
{
num=int(str[i][j]);
pos[i]=j;
}
}
}
int i,j,k;
char temp[1];
for(i=0;i<n;i++)
{
for(j=0;j<pos[i];j++)
{
temp[0]=str[i][0];
for(k=0;k<len[i];k++)
{
str[i][k]=str[i][k+1];
}
strcat(str[i],temp);
str[i][len[i]]='\0';
}
cout<<str[i]<<"\n";
}
return 0;
}
But this code only ckecks for the largest number and not for the number present next to it and hence fails for the i/p
blowhowler
The o/p should be wlerblowho but i get the o/p as whowlerblo.
How can i keep track of each element that preceeds the largest character so as to get the correct output?
For good performance on the average case (actually, O(N)), but still O^2 on the worst (and always correct), you can keep track of possibilities, and keep eliminating them as you go. Basically something like this.
struct PermSum
{
int sum;
int perm;
}
LinkedList<PermSum> L;
for(int i = 0; i != input.size(); ++i) L.append(PermSum{0,i});
int depth = 0;
int max = 0;
const int length = input.size()
while(L.size() > 1 && depth < length)
{
for(l in L)
{
l.sum += input[(l.perm + depth) % length]
if (l.sum > max) max = l.sum
}
for(l in L)
{
if (l.sum < max) L.delete(l)
}
depth ++;
}
if (L.size() == 1)
return L.front().perm
else
return -1
I got a bit lazy in some parts with the c++ code but I'm sure you can figure out for l in L. The key line is the first for loop. The idea is that its adding the lexicographical value at the depth-th letter of the l.perm-th permutation. In this way, it updates all the possibilities, while simultaneously keeping track of the level of the best possibility. You then do a second pass to delete any possibility falling short of the best. It's worth noting that the way I coded this up, it probably uses the reverse of the standard convention for circular permutations. That is, the perm field in my program represents how many spots LEFT you circular shift, whereas usually positive numbers are circular shifting right. You can fix this with a minus sign somewhere.
As for the running time analysis, it's basically the same argument as Quickselect. Each while loop iteration takes time proportional to the length of L. The first iteration, L will always have length = N (where N is the length of the string, the same as the variable length in the code). The next round, we typically only expect 1/26 of the data to get through, the round after that 1/26 again... so we have N(1 + 1/26 + 2/26^2...) which is O(N).
You can just:
1. generate rotations
2. put all rotations in map<>
3. find last element of the map.
Here is the implementation in C++.
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
int main() {
// your code goes here
string str;int len,i=0,j=0,k=0;char temp;
cin>>str;
len = str.length();
map<string,int>m;
while(i<len)
{
temp = str[0];
while(j<len-1)
{
str[j] = str[j+1];
j++;
}
str[j] = temp;
m[str] = k;
k++;
i++;j=0;
}
str = m.rbegin()->first;
cout<<str;
return 0;
}
The problem can be solved in O(n log n) time by appending the string to itself first and build the suffix array out of it. Find the corresponding entry and there your wanted result. Implementation left as an exercise.
//Here the index with greater value is selected,
//if the same char occurs again the next characters
// of prev and curr characters is checked:-Prev=maxIndex,curr=i
#include<bits/stdc++.h>
using namespace std;
int getIndex(char *str){
int max=INT_MIN,maxIndex;
int n=strlen(str);
int j,p;
for(int i=0;i<n;i++)
{
if(str[i]>max)
{
max=str[i];
maxIndex=i;
}
else if(str[i]==max)
{
j=maxIndex+1;
p=(i+1)%n;
while(j<n && p<n && str[j]==str[p]){
j++;
p=(p+1)%n;
}
maxIndex=str[p]>str[j]?i:maxIndex;
}
}
return maxIndex;
}
int main(void)
{
char str[4000008];
scanf("%s",str);
int i=getIndex(str);
for(int j=i;j<strlen(str);j++)
cout<<str[j];
for(int j=0;j<i;j++)
cout<<str[j];
}
Your algorithm, corrected, comes down to:
Set current best rotation to identity (start of rotated string is current index 0).
For each possible rotation (all other starting indices):
Compare to current-best-rotation with something like wrapcmp below.
Set the current-best-rotation if we had a better candidate.
Time-Complexity: O(n*n)
Space-Complexity: in-place
// Function to do ordinal-comparison on two rotations of a buffer
// buffer: The buffer containing the string
// n: The buffers size (string-length)
// a: Index where the first buffer starts pre-rotation
// b: Index where the second buffer starts pre-rotation
int wrapcmp(const void* buffer, size_t n, size_t a, size_t b) {
auto x = (const unsigned char*)buffer;
auto m = n - std::max(a, b);
int ret = memcmp(x+a, x+b, m);
if(ret) return ret;
auto left = n - m;
a = (a + m) % n;
b = (b + m) % n;
m = left - std::max(a, b);
ret = memcmp(x+a, x+b, m);
if(ret) return ret;
a = (a + m) % n;
b = (b + m) % n;
return memcmp(x+a, x+b, left - m);
}
Used on coliru: http://coliru.stacked-crooked.com/a/4b138a6394483447
Putting it into the general algo left as an exercise for the reader.
This was too tempting so I may as well post my effort. Not sure how it rates efficiency wize. It seems to work as far as I tested it:
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
std::string max_rot(const std::string& s)
{
std::string tmp;
std::string max;
std::string::const_iterator m = std::max_element(s.begin(), s.end());
if(m != s.end())
for(char c = *m; (m = std::find(m, s.end(), c)) != s.end(); ++m)
if(max < tmp.assign(m, s.end()).append(s.begin(), m))
max = tmp;
return max;
}
int main()
{
size_t times = 0;
std::string text;
do { std::cout << "\nHow many words? : "; }
while(std::getline(std::cin, text) && !(std::istringstream(text) >> times));
std::vector<std::string> words;
while(times-- && (std::cin >> text))
words.push_back(text);
for(const auto& s: words)
std::cout << max_rot(s) << '\n';
}
By way of explanation. It finds the highest character value in the string and rotates the string to make that character first. If then looks for duplicate highest characters in the remainder of the string keeping track of the highest attempt. There maybe room for optimization.
This challenge is used in an active contest, I request no answer to be provided till 18th Sep 9 PM IST. Because the code is visible, we might have to ban the user from participating in any of our contests going forward.
One of our assignments in working with C++ in 1st year programming was to write a function that can check if a number is palindromic or not (e.g 16461). I'd upload my code but I don't even know where to begin when it comes to extracting digits from an integer or checking the number of digits in an integer. Any help or hints would be appreciated!
There are many ways to solve this. I like most the solution that builds the mirror number and checks whether it is identical to the original (even though, it is arguably not the most efficient way). The code should be something like:
bool isPalindrom(int n) {
int original = n;
int mirror = 0;
while (n) {
mirror = mirror * 10 + n % 10;
n /= 10;
}
return mirror == original;
}
You can use modulo arithmetic (% operator) to extract individual digits. An alternative would be to get the string representation of your number and work with that.
Hints:
"Number of digits" is a tricky thing to define, since you can always add 0's on the left-hand side and still have the same number. Read carefully and think carefully about how you want to define this.
The digits of an integer are associated with powers of 10 (recall 123 = 1*100 + 2*10 + 3*1), so to extract digits you need to be extracting powers of 10. The key operations are remainder and truncated division. What happens if you do (123 % 10)? How about (123 / 10)? How about ((123 / 10) % 10)?
Best convert the integer into a string first. Testing a string if it is a palindrome is much easier.
#include <sstream>
#include <iostream>
#include <string>
bool isPalindrome(int value)
{
// convert integer into text
std::ostringstream oss;
oss << value;
std::string valueText = oss.str();
if (valueText.size()%2==0) {
return false;
}
for (int i = 0; i < (valueText.size()/2); ++i) {
if (valueText[i]!=valueText[valueText.size()-i-1]) {
return false;
}
}
return true;
}
int main()
{
for (int i = 0; i < 100000; ++i) {
if (isPalindrome(i)) {
std::cout << i << std::endl;
}
}
return 0;
}
First convert the integer into a std::string:
std::ostringstream oss;
oss << value;
std::string valueText = oss.str();
Now check if the string has a odd number of digits:
if (valueText.size()%2==0) {
return false;
}
If the string has a odd number of digits, test if the digits match:
for (int i = 0; i < (valueText.size()/2); ++i) {
if (valueText[i]!=valueText[valueText.size()-i-1]) {
return false;
}
}
Here's a solution that converts the integer to a C-style string and go from there.
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
bool isPalindrome(int n) {
char s[256];
sprintf(s, "%d", n);
char *p = s, *q = &s[strlen(s) - 1];
while (*p == *q && p++ < q--)
;
return (p == q) || (*p == *q);
}
int main() {
int n = 1644451;
cout << isPalindrome(n) << endl;
return 0;
}
If performance is not an issue, and if you can do c++11, an easy to read solution :
template<class T>
bool isPalindrome(T i)
{
auto s = std::to_string(i);
auto s2 = s;
std::reverse(s.begin(), s.end());
return s == s2;
}
which is of course much slower than manually going through the digits, but imho is very readable...
call it with:
std::cout << isPalindrome<int>(12321);
std::cout << isPalindrome<int>(1232);
The program below I came up with for checking whether two strings are anagrams. Its working fine for small string but for larger strings ( i tried : listened , enlisted ) Its giving me a 'no !'
Help !
#include<iostream.h>
#include<string.h>
#include<stdio.h>
int main()
{
char str1[100], str2[100];
gets(str1);
gets(str2);
int i,j;
int n1=strlen(str1);
int n2=strlen(str2);
int c=0;
if(n1!=n2)
{
cout<<"\nThey are not anagrams ! ";
return 0;
}
else
{
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
if(str1[i]==str2[j])
++c;
}
if(c==n1)
cout<<"yes ! anagram !! ";
else
cout<<"no ! ";
system("pause");
return 0;
}
I am lazy, so I would use standard library functionality to sort both strings and then compare them:
#include <string>
#include <algorithm>
bool is_anagram(std::string s1, std::string s2)
{
std::sort(s1.begin(), s1.end());
std::sort(s2.begin(), s2.end());
return s1 == s2;
}
A small optimization could be to check that the sizes of the strings are the same before sorting.
But if this algorithm proved to be a bottle-neck, I would temporarily shed some of my laziness and compare it against a simple counting solution:
Compare string lengths
Instantiate a count map, std::unordered_map<char, unsigned int> m
Loop over s1, incrementing the count for each char.
Loop over s2, decrementing the count for each char, then check that the count is 0
The algorithm also fails when asked to find if aa and aa are anagrams. Try tracing the steps of the algorithm mentally or in a debugger to find why; you'll learn more that way.
By the way.. The usual method for finding anagrams is counting how many times each letter appears in the strings. The counts should be equal for each letter. This approach has O(n) time complexity as opposed to O(n²).
bool areAnagram(char *str1, char *str2)
{
// Create two count arrays and initialize all values as 0
int count1[NO_OF_CHARS] = {0};
int count2[NO_OF_CHARS] = {0};
int i;
// For each character in input strings, increment count in
// the corresponding count array
for (i = 0; str1[i] && str2[i]; i++)
{
count1[str1[i]]++;
count2[str2[i]]++;
}
// If both strings are of different length. Removing this condition
// will make the program fail for strings like "aaca" and "aca"
if (str1[i] || str2[i])
return false;
// Compare count arrays
for (i = 0; i < NO_OF_CHARS; i++)
if (count1[i] != count2[i])
return false;
return true;
}
I see 2 main approaches below:
Sort then compare
Count the occurrences of each letter
It's interesting to see that Suraj's nice solution got one point (by me, at the time of writing) but a sort one got 22. The explanation is that performance wasn't in people's mind - and that's fine for short strings.
The sort implementation is only 3 lines long, but the counting one beats it square for long strings. It is much faster (O(N) versus O(NlogN)).
Got the following results with 500 MBytes long strings.
Sort - 162.8 secs
Count - 2.864 secs
Multi threaded Count - 3.321 secs
The multi threaded attempt was a naive one that tried to double the speed by counting in separate threads, one for each string. Memory access is the bottleneck and this is an example where multi threading makes things a bit worse.
I would be happy to see some idea that would speed up the count solution (think by someone good with memory latency issues, caches).
#include<stdio.h>
#include<string.h>
int is_anagram(char* str1, char* str2){
if(strlen(str1)==strspn(str1,str2) && strlen(str1)==strspn(str2,str1) &&
strlen(str1)==strlen(str2))
return 1;
return 0;
}
int main(){
char* str1 = "stream";
char* str2 = "master";
if(is_anagram(str1,str2))
printf("%s and %s are anagram to each other",str1,str2);
else
printf("%s and %s are not anagram to each other",str1,str2);
return 0;
}
#include<iostream>
#include<unordered_map>
using namespace std;
int checkAnagram (string &str1, string &str2)
{
unordered_map<char,int> count1, count2;
unordered_map<char,int>::iterator it1, it2;
int isAnagram = 0;
if (str1.size() != str2.size()) {
return -1;
}
for (unsigned int i = 0; i < str1.size(); i++) {
if (count1.find(str1[i]) != count1.end()){
count1[str1[i]]++;
} else {
count1.insert(pair<char,int>(str1[i], 1));
}
}
for (unsigned int i = 0; i < str2.size(); i++) {
if (count2.find(str2[i]) != count2.end()) {
count2[str2[i]]++;
} else {
count2.insert(pair<char,int>(str2[i], 1));
}
}
for (unordered_map<char, int>::iterator itUm1 = count1.begin(); itUm1 != count1.end(); itUm1++) {
unordered_map<char, int>::iterator itUm2 = count2.find(itUm1->first);
if (itUm2 != count2.end()) {
if (itUm1->second != itUm2->second){
isAnagram = -1;
break;
}
}
}
return isAnagram;
}
int main(void)
{
string str1("WillIamShakespeare");
string str2("IamaWeakishSpeller");
cout << "checkAnagram() for " << str1 << "," << str2 << " : " << checkAnagram(str1, str2) << endl;
return 0;
}
It's funny how sometimes the best questions are the simplest.
The problem here is how to deduce whether two words are anagrams - a word being essentially an unsorted multiset of chars.
We know we have to sort, but ideally we'd want to avoid the time-complexity of sort.
It turns out that in many cases we can eliminate many words that are dissimilar in linear time by running through them both and XOR-ing the character values into an accumulator. The total XOR of all characters in both strings must be zero if both strings are anagrams, regardless of ordering. This is because anything xored with itself becomes zero.
Of course the inverse is not true. Just because the accumulator is zero does not mean we have an anagram match.
Using this information, we can eliminate many non-anagrams without a sort, short-circuiting at least the non-anagram case.
#include <iostream>
#include <string>
#include <algorithm>
//
// return a sorted copy of a string
//
std::string sorted(std::string in)
{
std::sort(in.begin(), in.end());
return in;
}
//
// check whether xor-ing the values in two ranges results in zero.
// #pre first2 addresses a range that is at least as big as (last1-first1)
//
bool xor_is_zero(std::string::const_iterator first1,
std::string::const_iterator last1,
std::string::const_iterator first2)
{
char x = 0;
while (first1 != last1) {
x ^= *first1++;
x ^= *first2++;
}
return x == 0;
}
//
// deduce whether two strings are the same length
//
bool same_size(const std::string& l, const std::string& r)
{
return l.size() == r.size();
}
//
// deduce whether two words are anagrams of each other
// I have passed by const ref because we may not need a copy
//
bool is_anagram(const std::string& l, const std::string& r)
{
return same_size(l, r)
&& xor_is_zero(l.begin(), l.end(), r.begin())
&& sorted(l) == sorted(r);
}
// test
int main() {
using namespace std;
auto s1 = "apple"s;
auto s2 = "eppla"s;
cout << is_anagram(s1, s2) << '\n';
s2 = "pppla"s;
cout << is_anagram(s1, s2) << '\n';
return 0;
}
expected:
1
0
Try this:
// Anagram. Two words are said to be anagrams of each other if the letters from one word can be rearranged to form the other word.
// From the above definition it is clear that two strings are anagrams if all characters in both strings occur same number of times.
// For example "xyz" and "zxy" are anagram strings, here every character 'x', 'y' and 'z' occur only one time in both strings.
#include <map>
#include <string>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
bool IsAnagram_1( string w1, string w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
sort( w1.begin(), w1.end() );
sort( w2.begin(), w2.end() );
return w1 == w2;
}
map<char, size_t> key_word( const string & w )
{
// Declare a map which is an associative container that will store a key value and a mapped value pairs
// The key value is a letter in a word and the maped value is the number of times this letter appears in the word
map<char, size_t> m;
// Step over the characters of string w and use each character as a key value in the map
for ( auto & c : w )
{
// Access the mapped value directly by its corresponding key using the bracket operator
++m[toupper( c )];
}
return ( m );
}
bool IsAnagram_2( const string & w1, const string & w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
return ( key_word( w1 ) == key_word( w2 ) );
}
bool IsAnagram_3( const string & w1, const string & w2 )
{
// Compare string lengths
if ( w1.length() != w2.length() )
return false;
// Instantiate a count map, std::unordered_map<char, unsigned int> m
unordered_map<char, size_t> m;
// Loop over the characters of string w1 incrementing the count for each character
for ( auto & c : w1 )
{
// Access the mapped value directly by its corresponding key using the bracket operator
++m[toupper(c)];
}
// Loop over the characters of string w2 decrementing the count for each character
for ( auto & c : w2 )
{
// Access the mapped value directly by its corresponding key using the bracket operator
--m[toupper(c)];
}
// Check to see if the mapped values are all zeros
for ( auto & c : w2 )
{
if ( m[toupper(c)] != 0 )
return false;
}
return true;
}
int main( )
{
string word1, word2;
cout << "Enter first word: ";
cin >> word1;
cout << "Enter second word: ";
cin >> word2;
if ( IsAnagram_1( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
if ( IsAnagram_2( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
if ( IsAnagram_3( word1, word2 ) )
cout << "\nAnagram" << endl;
else
cout << "\nNot Anagram" << endl;
system("pause");
return 0;
}
In this approach I took care of empty strings and repeated characters as well. Enjoy it and comment any limitation.
#include <iostream>
#include <map>
#include <string>
using namespace std;
bool is_anagram( const string a, const string b ){
std::map<char, int> m;
int count = 0;
for (int i = 0; i < a.length(); i++) {
map<char, int>::iterator it = m.find(a[i]);
if (it == m.end()) {
m.insert(m.begin(), pair<char, int>(a[i], 1));
} else {
m[a[i]]++;
}
}
for (int i = 0; i < b.length(); i++) {
map<char, int>::iterator it = m.find(b[i]);
if (it == m.end()) {
m.insert(m.begin(), pair<char, int>(b[i], 1));
} else {
m[b[i]]--;
}
}
if (a.length() <= b.length()) {
for (int i = 0; i < a.length(); i++) {
if (m[a[i]] >= 0) {
count++;
} else
return false;
}
if (count == a.length() && a.length() > 0)
return true;
else
return false;
} else {
for (int i = 0; i < b.length(); i++) {
if (m[b[i]] >= 0) {
count++;
} else {
return false;
}
}
if (count == b.length() && b.length() > 0)
return true;
else
return false;
}
return true;
}
Check if the two strings have identical counts for each unique char.
bool is_Anagram_String(char* str1,char* str2){
int first_len=(int)strlen(str1);
int sec_len=(int)strlen(str2);
if (first_len!=sec_len)
return false;
int letters[256] = {0};
int num_unique_chars = 0;
int num_completed_t = 0;
for(int i=0;i<first_len;++i){
int char_letter=(int)str1[i];
if(letters[char_letter]==0)
++num_unique_chars;
++letters[char_letter];
}
for (int i = 0; i < sec_len; ++i) {
int c = (int) str2[i];
if (letters[c] == 0) { // Found more of char c in t than in s.
return false;
}
--letters[c];
if (letters[c] == 0) {
++num_completed_t;
if (num_completed_t == num_unique_chars) {
// it’s a match if t has been processed completely
return i == sec_len - 1;
}
}
}
return false;}
#include <iostream>
#include <string.h>
using namespace std;
const int MAX = 100;
char cadA[MAX];
char cadB[MAX];
bool chrLocate;
int i,m,n,j, contaChr;
void buscaChr(char [], char []);
int main() {
cout << "Ingresa CadA: ";
cin.getline(cadA, sizeof(cadA));
cout << "Ingresa CadB: ";
cin.getline(cadB, sizeof(cadA));
if ( strlen(cadA) == strlen(cadB) ) {
buscaChr(cadA,cadB);
} else {
cout << "No son Anagramas..." << endl;
}
return 0;
}
void buscaChr(char a[], char b[]) {
j = 0;
contaChr = 0;
for ( i = 0; ( (i < strlen(a)) && contaChr < 2 ); i++ ) {
for ( m = 0; m < strlen(b); m++ ) {
if ( a[i] == b[m]) {
j++;
contaChr++;
a[i] = '-';
b[m] = '+';
} else { contaChr = 0; }
}
}
if ( j == strlen(a)) {
cout << "SI son Anagramas..." << endl;
} else {
cout << "No son Anagramas..." << endl;
}
}
Your algorithm is incorrect. You're checking each character in the first word to see how many times that character appears in the second word. If the two words were 'aaaa', and 'aaaa', then that would give you a count of 16. A small alteration to your code would allow it to work, but give a complexity of N^2 as you have a double loop.
for(i=0;i<n1;i++)
for(j=0;j<n2;j++)
if(str1[i]==str2[j])
++c, str2[j] = 0; // 'cross off' letters as they are found.
I done some tests with anagram comparisons. Comparing two strings of 72 characters each (the strings are always true anagrams to get maximum number of comparisons), performing 256 same-tests with a few different STL containers...
template<typename STORAGE>
bool isAnagram(const string& s1, const string& s2, STORAGE& asciiCount)
{
for(auto& v : s1)
{
asciiCount[v]++;
}
for(auto& v : s2)
{
if(--asciiCount[static_cast<unsigned char>(v)] == -1)
{
return false;
}
}
return true;
}
Where STORAGE asciiCount =
map<char, int> storage; // 738us
unordered_map<char, int> storage; // 260us
vector<int> storage(256); // 43us
// g++ -std=c++17 -O3 -Wall -pedantic
This is the fastest I can get.
These are crude tests using coliru online compiler + and std::chrono::steady_clock::time_point for measurements, however they give a general idea of performance gains.
vector has the same performance, uses only 256 bytes, although strings are limited to 255 characters in length (also change to: --asciiCount[static_cast(v)] == 255 for unsigned char counting).
Assuming vector is the fastest. An improvement would be to just allocate a C style array unsigned char asciiCount[256]; on the stack (since STL containers allocate their memory dynamically on the heap)
You could probably reduce this storage to 128 bytes, 64 or even 32 bytes (ascii chars are typically in range 0..127, while A-Z+a-z 64.127, and just upper or lower case 64..95 or 96...127) although not sure what gains would be found from fitting this inside a cache line or half.
Any better ways to do this? For Speed, Memory, Code Elegance?
1. Simple and fast way with deleting matched characters
bool checkAnagram(string s1, string s2) {
for (char i : s1) {
unsigned int pos = s2.find(i,0);
if (pos != string::npos) {
s2.erase(pos,1);
} else {
return false;
}
}
return s2.empty();
}
2. Conversion to prime numbers. Beautiful but very expensive, requires special Big Integer type for long strings.
// https://en.wikipedia.org/wiki/List_of_prime_numbers
int primes[255] = {2, 3, 5, 7, 11, 13, 17, 19, ... , 1613};
bool checkAnagramPrimes(string s1, string s2) {
long c1 = 1;
for (char i : s1) {
c1 = c1 * primes[i];
}
long c2 = 1;
for (char i : s2) {
c2 = c2 * primes[i];
if (c2 > c1) {
return false;
}
}
return c1 == c2;
}
string key="listen";
string key1="silent";
string temp=key1;
int len=0;
//assuming both strings are of equal length
for (int i=0;i<key.length();i++){
for (int j=0;j<key.length();j++){
if(key[i]==temp[j]){
len++;
temp[j] = ' ';//to deal with the duplicates
break;
}
}
}
cout << (len==key.length()); //if true: means the words are anagrams
Instead of using dot h header which is deprecated in modern c++.
Try this solution.
#include <iostream>
#include <string>
#include <map>
int main(){
std::string word_1 {};
std::cout << "Enter first word: ";
std::cin >> word_1;
std::string word_2 {};
std::cout << "Enter second word: ";
std::cin >> word_2;
if(word_1.length() == word_2.length()){
std::map<char, int> word_1_map{};
std::map<char, int> word_2_map{};
for(auto& c: word_1)
word_1_map[std::tolower(c)]++;
for(auto& c: word_2)
word_2_map[std::tolower(c)]++;
if(word_1_map == word_2_map){
std::cout << "Anagrams" << std::endl;
}
else{
std::cout << "Not Anagrams" << std::endl;
}
}else{
std::cout << "Length Mismatch" << std::endl;
}
}
#include <bits/stdc++.h>
using namespace std;
#define NO_OF_CHARS 256
int main()
{ bool ans = true;
string word1 = "rest";
string word2 = "tesr";
unordered_map<char,int>maps;
for(int i = 0 ; i <5 ; i++)
{
maps[word1[i]] +=1;
}
for(int i = 0 ; i <5 ; i++)
{
maps[word2[i]]-=1 ;
}
for(auto i : maps)
{
if(i.second!=0)
{
ans = false;
}
}
cout<<ans;
}
Well if you don't want to sort than this code will give you perfect output.
#include <iostream>
using namespace std;
int main(){
string a="gf da";
string b="da gf";
int al,bl;
int counter =0;
al =a.length();
bl =b.length();
for(int i=0 ;i<al;i++){
for(int j=0;j<bl;j++){
if(a[i]==b[j]){
if(j!=bl){
b[j]=b[b.length()-counter-1];
bl--;
counter++;
break;
}else{
bl--;
counter++;
}
}
}
}
if(counter==al){
cout<<"true";
}
else{
cout<<"false";
}
return 0;
}
Here is the simplest and fastest way to check for anagrams
bool anagram(string a, string b) {
int a_sum = 0, b_sum = 0, i = 0;
while (a[i] != '\0') {
a_sum += (int)a[i]; // (int) cast not necessary
b_sum += (int)b[i];
i++;
}
return a_sum == b_sum;
}
Simply adds the ASCII values and checks if the sums are equal.
For example:
string a = "nap" and string b = "pan"
a_sum = 110 + 97 + 112 = 319
b_sum = 112 + 97 + 110 = 319
I was asked this during an interview and apparently it's an easy question but it wasn't and still isn't obvious to me.
Given a string, count all the words in it. Doesn't matter if they are repeated. Just the total count like in a text files word count. Words are anything separated by a space and punctuation doesn't matter, as long as it's part of a word.
For example:
A very, very, very, very, very big dog ate my homework!!!! ==> 11 words
My "algorithm" just goes through looking for spaces and incrementing a counter until I hit a null. Since i didn't get the job and was asked to leave after that I guess My solution wasn't good? Anyone have a more clever solution? Am I missing something?
Assuming words are white space separated:
unsigned int countWordsInString(std::string const& str)
{
std::stringstream stream(str);
return std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>());
}
Note: There may be more than one space between words. Also this does not catch other white space characters like tab new line or carriage return. So counting spaces is not enough.
The stream input operator >> when used to read a string from a stream. Reads one white space separated word. So they were probably looking for you to use this to identify words.
std::stringstream stream(str);
std::string oneWord;
stream >> oneWord; // Reads one space separated word.
When can use this to count words in a string.
std::stringstream stream(str);
std::string oneWord;
unsigned int count = 0;
while(stream >> oneWord) { ++count;}
// count now has the number of words in the string.
Getting complicated:
Streams can be treated just like any other container and there are iterators to loop through them std::istream_iterator. When you use the ++ operator on an istream_iterator it just read the next value from the stream using the operator >>. In this case we are reading std::string so it reads a space separated word.
std::stringstream stream(str);
std::string oneWord;
unsigned int count = 0;
std::istream_iterator loop = std::istream_iterator<std::string>(stream);
std::istream_iterator end = std::istream_iterator<std::string>();
for(;loop != end; ++count, ++loop) { *loop; }
Using std::distance just wraps all the above in a tidy package as it find the distance between two iterators by doing ++ on the first until we reach the second.
To avoid copying the string we can be sneaky:
unsigned int countWordsInString(std::string const& str)
{
std::stringstream stream;
// sneaky way to use the string as the buffer to avoid copy.
stream.rdbuf()->pubsetbuf (str.c_str(), str.length() );
return std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>());
}
Note: we still copy each word out of the original into a temporary. But the cost of that is minimal.
A less clever, more obvious-to-all-of-the-programmers-on-your-team method of doing it.
#include <cctype>
int CountWords(const char* str)
{
if (str == NULL)
return error_condition; // let the requirements define this...
bool inSpaces = true;
int numWords = 0;
while (*str != '\0')
{
if (std::isspace(*str))
{
inSpaces = true;
}
else if (inSpaces)
{
numWords++;
inSpaces = false;
}
++str;
}
return numWords;
}
You can use the std::count or std::count_if to do that. Below a simple example with std::count:
//Count the number of words on string
#include <iostream>
#include <string>
#include <algorithm> //count and count_if is declared here
int main () {
std::string sTEST("Text to verify how many words it has.");
std::cout << std::count(sTEST.cbegin(), sTEST.cend(), ' ')+1;
return 0;
}
UPDATE: Due the observation made by Aydin Özcan (Nov 16) I made a change to this solution. Now the words may have more than one space between them. :)
//Count the number of words on string
#include <string>
#include <iostream>
int main () {
std::string T("Text to verify : How many words does it have?");
size_t NWords = T.empty() || T.back() == ' ' ? 0 : 1;
for (size_t s = T.size(); s > 0; --s)
if (T[s] == ' ' && T[s-1] != ' ') ++NWords;
std::cout << NWords;
return 0;
}
Another boost based solution that may work (untested):
vector<string> result;
split(result, "aaaa bbbb cccc", is_any_of(" \t\n\v\f\r"), token_compress_on);
More information can be found in the Boost String Algorithms Library
This can be done without manually looking at every character or copying the string.
#include <boost/iterator/transform_iterator.hpp>
#include <cctype>
boost::transform_iterator
< int (*)(int), std::string::const_iterator, bool const& >
pen( str.begin(), std::isalnum ), end( str.end(), std::isalnum );
size_t word_cnt = 0;
while ( pen != end ) {
word_cnt += * pen;
pen = std::mismatch( pen+1, end, pen ).first;
}
return word_cnt;
I took the liberty of using isalnum instead of isspace.
This is not something I would do at a job interview. (It's not like it compiled the first time.)
Or, for all the Boost haters ;v)
if ( str.empty() ) return 0;
size_t word_cnt = std::isalnum( * str.begin() );
for ( std::string::const_iterator pen = str.begin(); ++ pen != str.end(); ) {
word_cnt += std::isalnum( pen[ 0 ] ) && ! std::isalnum( pen[ -1 ] );
}
return word_cnt;
An O(N) solution that is also very simple to understand and implement:
(I haven't checked for an empty string input. But I am sure you can do that easily.)
#include <iostream>
#include <string>
using namespace std;
int countNumberOfWords(string sentence){
int numberOfWords = 0;
size_t i;
if (isalpha(sentence[0])) {
numberOfWords++;
}
for (i = 1; i < sentence.length(); i++) {
if ((isalpha(sentence[i])) && (!isalpha(sentence[i-1]))) {
numberOfWords++;
}
}
return numberOfWords;
}
int main()
{
string sentence;
cout<<"Enter the sentence : ";
getline(cin, sentence);
int numberOfWords = countNumberOfWords(sentence);
cout<<"The number of words in the sentence is : "<<numberOfWords<<endl;
return 0;
}
Here is a single pass, branchless (almost), locale-aware algorithm which handles cases with more than one space between words:
If the string is empty return 0
let transitions = number of adjacent char pairs (c1, c2) where c1 == ' ' and c2 != ' '
if the sentence starts with a space, return transitions else return transitions + 1
Here is an example with string = "A very, very, very, very, very big dog ate my homework!!!!"
i | 0123456789
c1 | A very, very, very, very, very big dog ate my homework!!!!
c2 | A very, very, very, very, very big dog ate my homework!!!!
| x x x x x x x x x x
Explanation
Let `i` be the loop counter.
When i=0: c1='A' and c2=' ', the condition `c1 == ' '` and `c2 != ' '` is not met
When i=1: c1=' ' and c2='A', the condition is met
... and so on for the remaining characters
Here are 2 solutions I came up with
Naive solution
size_t count_words_naive(const std::string_view& s)
{
if (s.size() == 0) return 0;
size_t count = 0;
bool isspace1, isspace2 = true;
for (auto c : s) {
isspace1 = std::exchange(isspace2, isspace(c));
count += (isspace1 && !isspace2);
}
return count;
}
If you think carefully, you will be able to reduce this set of operations into an inner product (just for fun, I don't recommend this as this is arguably much less readable).
Inner product solution
size_t count_words_using_inner_prod(const std::string_view& s)
{
if (s.size() == 0) return 0;
auto starts_with_space = isspace(s.front());
auto num_transitions = std::inner_product(
s.begin()+1, s.end(), s.begin(), 0, std::plus<>(),
[](char c2, char c1) { return isspace(c1) && !isspace(c2); });
return num_transitions + !starts_with_space;
}
I think that will help
the complexty O(n)
#include <iostream>
#include <string>
#include <ctype.h>
using namespace std;
int main()
{
int count = 0, size;
string sent;
getline(cin, sent);
size = sent.size();
check if the char is in alpha and the next char not in alpha
for (int i = 0; i < size - 1; ++i) {
if (isalpha(sent[i]) && !isalpha(sent[i+1])) {
++count;
}
}
if the word in the last of sentence didn't count above so it count here
if (isalpha(sent[size - 1]))++count;
cout << count << endl;
return 0;
}
A very concise O(N) approach:
bool is_letter(char c) { return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'; }
int count_words(const string& s) {
int i = 0, N = s.size(), count = 0;
while(i < N) {
while(i < N && !is_letter(s[i])) i++;
if(i == N) break;
while(i < N && is_letter(s[i])) i++;
count++;
}
return count;
}
A divide-and-conquer approach, complexity is also O(N):
int DC(const string& A, int low, int high) {
if(low > high) return 0;
int mid = low + (high - low) / 2;
int count_left = DC(A, low, mid-1);
int count_right = DC(A, mid+1, high);
if(!is_letter(A[mid]))
return count_left + count_right;
else {
if(mid == low && mid == high) return 1;
if(mid-1 < low) {
if(is_letter(A[mid+1])) return count_right;
else return count_right+1;
} else if(mid+1 > high) {
if(is_letter(A[mid-1])) return count_left;
else return count_left+1;
}
else {
if(!is_letter(A[mid-1]) && !is_letter(A[mid+1]))
return count_left + count_right + 1;
else if(is_letter(A[mid-1]) && is_letter(A[mid+1]))
return count_left + count_right - 1;
else
return count_left + count_right;
}
}
}
int count_words_divide_n_conquer(const string& s) {
return DC(s, 0, s.size()-1);
}
Efficient version based on map-reduce approach
#include <iostream>
#include <string_view>
#include <numeric>
std::size_t CountWords(std::string_view s) {
if (s.empty())
return 0;
std::size_t wc = (!std::isspace(s.front()) ? 1 : 0);
wc += std::transform_reduce(
s.begin(),
s.end() - 1,
s.begin() + 1,
std::size_t(0),
std::plus<std::size_t>(),
[](char left, char right) {
return std::isspace(left) && !std::isspace(right);
});
return wc;
}
int main() {
std::cout << CountWords(" pretty little octopus "sv) << std::endl;
return 0;
}