Are strings anagram

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
5
down vote

favorite
2












This is a question from the book "Cracking the Coding Interview".




Write a method to decide if two strings are anagrams or not




I think interviewer will not be convinced with this solution because here it is no test of logic. Please help me to optimise this solution.



#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

std::string toLower(std::string str)

std::transform(str.begin(), str.end(), str.begin(),
(unsigned char ch) return std::tolower(ch); );
return str;


bool areAnagrams(std::string& str1, std::string& str2)


str1 = toLower(str1);
str2 = toLower(str2);
std::sort(str1.begin(), str1.end());
std::sort(str2.begin(), str2.end());

if (str1.compare(str2) == 0)

return true;

else

return false;



int main()

std::string str1, str2;
std::cout << "Enter String 1: ";
std::getline(std::cin, str1);
std::cout << "Enter String 2: ";
std::getline(std::cin, str2);
bool res = areAnagrams(str1, str2);
if (res == 1)

std::cout << "Strings are anagramn";

else

std::cout << "Strings are not anagramn";








share|improve this question

























    up vote
    5
    down vote

    favorite
    2












    This is a question from the book "Cracking the Coding Interview".




    Write a method to decide if two strings are anagrams or not




    I think interviewer will not be convinced with this solution because here it is no test of logic. Please help me to optimise this solution.



    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <cctype>

    std::string toLower(std::string str)

    std::transform(str.begin(), str.end(), str.begin(),
    (unsigned char ch) return std::tolower(ch); );
    return str;


    bool areAnagrams(std::string& str1, std::string& str2)


    str1 = toLower(str1);
    str2 = toLower(str2);
    std::sort(str1.begin(), str1.end());
    std::sort(str2.begin(), str2.end());

    if (str1.compare(str2) == 0)

    return true;

    else

    return false;



    int main()

    std::string str1, str2;
    std::cout << "Enter String 1: ";
    std::getline(std::cin, str1);
    std::cout << "Enter String 2: ";
    std::getline(std::cin, str2);
    bool res = areAnagrams(str1, str2);
    if (res == 1)

    std::cout << "Strings are anagramn";

    else

    std::cout << "Strings are not anagramn";








    share|improve this question





















      up vote
      5
      down vote

      favorite
      2









      up vote
      5
      down vote

      favorite
      2






      2





      This is a question from the book "Cracking the Coding Interview".




      Write a method to decide if two strings are anagrams or not




      I think interviewer will not be convinced with this solution because here it is no test of logic. Please help me to optimise this solution.



      #include <iostream>
      #include <string>
      #include <algorithm>
      #include <cctype>

      std::string toLower(std::string str)

      std::transform(str.begin(), str.end(), str.begin(),
      (unsigned char ch) return std::tolower(ch); );
      return str;


      bool areAnagrams(std::string& str1, std::string& str2)


      str1 = toLower(str1);
      str2 = toLower(str2);
      std::sort(str1.begin(), str1.end());
      std::sort(str2.begin(), str2.end());

      if (str1.compare(str2) == 0)

      return true;

      else

      return false;



      int main()

      std::string str1, str2;
      std::cout << "Enter String 1: ";
      std::getline(std::cin, str1);
      std::cout << "Enter String 2: ";
      std::getline(std::cin, str2);
      bool res = areAnagrams(str1, str2);
      if (res == 1)

      std::cout << "Strings are anagramn";

      else

      std::cout << "Strings are not anagramn";








      share|improve this question











      This is a question from the book "Cracking the Coding Interview".




      Write a method to decide if two strings are anagrams or not




      I think interviewer will not be convinced with this solution because here it is no test of logic. Please help me to optimise this solution.



      #include <iostream>
      #include <string>
      #include <algorithm>
      #include <cctype>

      std::string toLower(std::string str)

      std::transform(str.begin(), str.end(), str.begin(),
      (unsigned char ch) return std::tolower(ch); );
      return str;


      bool areAnagrams(std::string& str1, std::string& str2)


      str1 = toLower(str1);
      str2 = toLower(str2);
      std::sort(str1.begin(), str1.end());
      std::sort(str2.begin(), str2.end());

      if (str1.compare(str2) == 0)

      return true;

      else

      return false;



      int main()

      std::string str1, str2;
      std::cout << "Enter String 1: ";
      std::getline(std::cin, str1);
      std::cout << "Enter String 2: ";
      std::getline(std::cin, str2);
      bool res = areAnagrams(str1, str2);
      if (res == 1)

      std::cout << "Strings are anagramn";

      else

      std::cout << "Strings are not anagramn";










      share|improve this question










      share|improve this question




      share|improve this question









      asked Aug 2 at 17:02









      coder

      911425




      911425




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          12
          down vote



          accepted











          I think interviewer will not be convinced with this solution because here it is no test of logic.




          I'm not sure what you mean by "because here it is no test of logic," but if what you mean is "because I found this puzzle too easy," then good! That's what the interviewer is likely to be hiring for: people who solve problems easily and quickly.



          When you get an easy problem in an interview, that may be a sign that the interviewer is trying to judge your coding skills rather than your algorithmic/research skills. So make sure your code is as polished as (reasonably) possible.



          • areAnagrams takes its parameters by non-const reference. This is probably a bug. The interviewer will ask you to "explain your choice." Your answer should be something like "oops, I forgot to remove the &." (This reflects a little badly on your coding skills.)


          • if (res == 1) is a very strange way to test for boolean true-ness. It would be less unusual, but still a minor yellow flag, to test for if (res == true) or if (res). It would be good to remove the useless variable and test directly for if (areAnagrams(str1, str2)).



          Similarly, in the body of areAnagrams, you have written



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          This is a very long-winded and confusing way of writing



          return str1 == str2;


          and is kind of a big deal. The interviewer is not looking to hire people who write eight lines of convoluted code when one line of simple code would do the job.



          You also have an extra blank line at the beginning of areAnagrams; this shows a possible tendency toward sloppiness. The interviewer is not looking to hire people who might "typo" their way into a bug.




          On the plus side, your definition of toLower is very good! The interviewer might ask you to explain why you took by value instead of by const&. The interviewer might ask you whether the line return str; makes a copy of the string or whether the copy is elided. (Trick question! The answer is "neither.")






          share|improve this answer





















          • The answer is "neither." Why does NRVO not work in this case?
            – yuri
            Aug 2 at 20:22






          • 4




            Funny you should ask! NRVO works by constructing the object str directly into toLower's return slot. But in this case, toLower does not control where str gets constructed (because str is a parameter). The result is that str will be moved into the return slot — neither copied nor copy-elided, but moved.
            – Quuxplusone
            Aug 2 at 23:07

















          up vote
          9
          down vote













          I see some things that may help you improve your code.




          bool is not int



          The bool type is a full-fledged first class type in C++. If I were an interviewer reading this code, I'd be perplexed:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          A similar thing is being done here:



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          First, we are comparing a bool to 1 (an int) which is odd enough. Next, if we're returning the result of the comparison, why don't we return the result of the comparison?



          return !str1.compare(str2);


          Better still:



          return str1 == str2;


          Understand references



          The prototype of the toLower function is this:



          std::string toLower(std::string str);
          bool areAnagrams(std::string& str1, std::string& str2);


          So reading this, the toLower makes a copy of its argument and areAnagrams uses references. However, the first few lines of the latter function are these:



          str1 = toLower(str1);
          str2 = toLower(str2);


          There's little point to making copies and then assigning the copy back to the original. What I would recommend instead is to have toLower take a reference and areAnagrams pass by value. That way, we have a much more logical interface in which toLower modifies the passed string but areAnagrams does not.



          Use auto to simplify code



          The better choice for res in main would be to declare it auto instead of explicitly naming bool.



          Consider the use of locale



          Rather than writing your own toLower, why not use the one in <locale>? Here's how that might look:



          auto& facetstd::use_facet<std::ctype<char>>(std::locale());
          facet.tolower(&str1.front(), &str1.back());
          facet.tolower(&str2.front(), &str2.back());


          Use better naming



          The function toLower is a good name because (with the suggested change mentioned above) it says what it actually does. However, res is not a good name and it's not necessary to have a separate variable anyway. Instead of this strange construction:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          I would probably instead have written this:



          std::cout << "Strings " << (areAnagrams(str1, str2) ? "are" : "are not")
          << " anagramsn";


          Although, as @TobySpeight points out in a comment, better for the purposes of translating the string into another language would be to keep the strings intact. One way to do that:



          std::cout << (areAnagrams(str1, str2) ? "Strings are anagramsn"
          : "Strings are not anagramsn");


          Declare variables each on a separate line



          Clarify variable declaration by declaring each one on a single line. See Guideline ES.10



          Consider namespace or static



          During an interview, I'd probably ask why you chose not to encapsulate the functions in a namespace, and why the functions are not static. There are arguments both ways for each of those; be aware of what they are and be able to explain and defend your choices.






          share|improve this answer























          • std::string::compare returns <0, 0, or >0, so the first part of your answer doesn't make any sense.
            – jamesdlin
            Aug 2 at 22:25










          • @jamesdlin: it was missing a ! which is now corrected.
            – Edward
            Aug 2 at 22:47






          • 3




            I meant that the whole "bool is not int" premise is misdirected ("we are comparing a bool to 0..."; no, it's comparing int to 0). Regarding your edit: I personally dislike !str.compare(str) for the same reason as you originally give: bool is not int, and ! on an int seems weird.
            – jamesdlin
            Aug 2 at 22:55







          • 1




            First, within main we have if (res == 1) which is comparing a bool to an int. Second, I agree that !str1.compare(str2) is not very good, which is why what I recommend instead is return str1 == str2; which I suspect we both agree is the most clear and straightforward way to do it.
            – Edward
            Aug 2 at 23:12






          • 2




            Under "Use better naming", you go a bit further than I would. There's an argument against breaking strings into pieces like that - it's an anti-pattern that hinders translation. When your program is likely to be translated (and in an interview you do want to demonstrate that you can work with translators), it's usually better to keep strings whole - this is where C-style format strings can be valuable: std::printf(areAnagrams(str1, str2) ? "%s is an anagram of %sn" : "%s is not an anagram of %sn", str1.c_str(), str2.c_str());
            – Toby Speight
            Aug 3 at 7:59

















          up vote
          2
          down vote













          You know, when deciding whether you have anagrams, you are generally only interested in alpha-numeric characters, the rest are disregarded.



          Next, making extraneous copies is generally a bad idea. So, accept a constant view and don't make a copy.



          When you accept a mutable reference, be sure that it's obvious from the function-name and arity that it's a mutable reference.



          If you can, avoid external linkage. It promotes inlining and avoids unfortunate name-clashes.



          Finally, a faster algorithm is normally preferable:



          bool isAnagram(std::string_view a, std::string_view b) noexcept 
          unsigned counts[1ULL + (unsigned char)-1] = ;
          for (unsigned char c : a)
          ++counts[std::tolower(c)];
          for (unsigned char c : b)
          --counts[std::tolower(c)];
          for (std::size_t i = 0; i < std::size(counts); ++i)
          if (counts[i] && std::isalnum(i))
          return false;
          return true;






          share|improve this answer



















          • 3




            While this may be a faster algorithm, is it a clearer algorithm? I think that for an interview, it may be better to write for clarity.
            – Edward
            Aug 2 at 18:21










          • @Edward Yes, I would say so.
            – Deduplicator
            Aug 2 at 18:49










          • (2) This code is different from OP's, it ignores non-alnum characters. (3) It's actually slower for short string, as it allocates an array of ~256 ints.
            – user176443
            Aug 3 at 3:56











          • Why int map? unsigned map will likely give the right answer in most cases for extremely long strings even if a bucket wraps around, without any signed-overflow UB. (If you can rule out long strings, unsigned char map cuts the cache footprint by 4 on most modern C++ implementations, and allows faster checking for non-zero buckets on targets where the compiler can use SIMD for the final loop.) I was going to say uint8_t, but you don't need to stop the code from working on implementations without uint8_t, like some DSPs where char is 32 bits.
            – Peter Cordes
            Aug 3 at 8:10






          • 1




            @user17... If you're checking all characters, then check if lengths are equal as an early-out before doing anything else. But allocating 1kiB on the stack is basically free; literally 1 instruction. Zeroing it has some small cost. Touching it might cause some cache misses, but store-forwarding might manage to hide a lot of the cost of that (i.e. the reloads don't have to wait for the stores to commit); only 32x 32-byte stores, so maybe 32 store-buffer entries for zeroing it. The load part of each increment should forward from the zeroing, but the store part uses another buffer.
            – Peter Cordes
            Aug 3 at 11:14











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200835%2fare-strings-anagram%23new-answer', 'question_page');

          );

          Post as a guest






























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          12
          down vote



          accepted











          I think interviewer will not be convinced with this solution because here it is no test of logic.




          I'm not sure what you mean by "because here it is no test of logic," but if what you mean is "because I found this puzzle too easy," then good! That's what the interviewer is likely to be hiring for: people who solve problems easily and quickly.



          When you get an easy problem in an interview, that may be a sign that the interviewer is trying to judge your coding skills rather than your algorithmic/research skills. So make sure your code is as polished as (reasonably) possible.



          • areAnagrams takes its parameters by non-const reference. This is probably a bug. The interviewer will ask you to "explain your choice." Your answer should be something like "oops, I forgot to remove the &." (This reflects a little badly on your coding skills.)


          • if (res == 1) is a very strange way to test for boolean true-ness. It would be less unusual, but still a minor yellow flag, to test for if (res == true) or if (res). It would be good to remove the useless variable and test directly for if (areAnagrams(str1, str2)).



          Similarly, in the body of areAnagrams, you have written



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          This is a very long-winded and confusing way of writing



          return str1 == str2;


          and is kind of a big deal. The interviewer is not looking to hire people who write eight lines of convoluted code when one line of simple code would do the job.



          You also have an extra blank line at the beginning of areAnagrams; this shows a possible tendency toward sloppiness. The interviewer is not looking to hire people who might "typo" their way into a bug.




          On the plus side, your definition of toLower is very good! The interviewer might ask you to explain why you took by value instead of by const&. The interviewer might ask you whether the line return str; makes a copy of the string or whether the copy is elided. (Trick question! The answer is "neither.")






          share|improve this answer





















          • The answer is "neither." Why does NRVO not work in this case?
            – yuri
            Aug 2 at 20:22






          • 4




            Funny you should ask! NRVO works by constructing the object str directly into toLower's return slot. But in this case, toLower does not control where str gets constructed (because str is a parameter). The result is that str will be moved into the return slot — neither copied nor copy-elided, but moved.
            – Quuxplusone
            Aug 2 at 23:07














          up vote
          12
          down vote



          accepted











          I think interviewer will not be convinced with this solution because here it is no test of logic.




          I'm not sure what you mean by "because here it is no test of logic," but if what you mean is "because I found this puzzle too easy," then good! That's what the interviewer is likely to be hiring for: people who solve problems easily and quickly.



          When you get an easy problem in an interview, that may be a sign that the interviewer is trying to judge your coding skills rather than your algorithmic/research skills. So make sure your code is as polished as (reasonably) possible.



          • areAnagrams takes its parameters by non-const reference. This is probably a bug. The interviewer will ask you to "explain your choice." Your answer should be something like "oops, I forgot to remove the &." (This reflects a little badly on your coding skills.)


          • if (res == 1) is a very strange way to test for boolean true-ness. It would be less unusual, but still a minor yellow flag, to test for if (res == true) or if (res). It would be good to remove the useless variable and test directly for if (areAnagrams(str1, str2)).



          Similarly, in the body of areAnagrams, you have written



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          This is a very long-winded and confusing way of writing



          return str1 == str2;


          and is kind of a big deal. The interviewer is not looking to hire people who write eight lines of convoluted code when one line of simple code would do the job.



          You also have an extra blank line at the beginning of areAnagrams; this shows a possible tendency toward sloppiness. The interviewer is not looking to hire people who might "typo" their way into a bug.




          On the plus side, your definition of toLower is very good! The interviewer might ask you to explain why you took by value instead of by const&. The interviewer might ask you whether the line return str; makes a copy of the string or whether the copy is elided. (Trick question! The answer is "neither.")






          share|improve this answer





















          • The answer is "neither." Why does NRVO not work in this case?
            – yuri
            Aug 2 at 20:22






          • 4




            Funny you should ask! NRVO works by constructing the object str directly into toLower's return slot. But in this case, toLower does not control where str gets constructed (because str is a parameter). The result is that str will be moved into the return slot — neither copied nor copy-elided, but moved.
            – Quuxplusone
            Aug 2 at 23:07












          up vote
          12
          down vote



          accepted







          up vote
          12
          down vote



          accepted







          I think interviewer will not be convinced with this solution because here it is no test of logic.




          I'm not sure what you mean by "because here it is no test of logic," but if what you mean is "because I found this puzzle too easy," then good! That's what the interviewer is likely to be hiring for: people who solve problems easily and quickly.



          When you get an easy problem in an interview, that may be a sign that the interviewer is trying to judge your coding skills rather than your algorithmic/research skills. So make sure your code is as polished as (reasonably) possible.



          • areAnagrams takes its parameters by non-const reference. This is probably a bug. The interviewer will ask you to "explain your choice." Your answer should be something like "oops, I forgot to remove the &." (This reflects a little badly on your coding skills.)


          • if (res == 1) is a very strange way to test for boolean true-ness. It would be less unusual, but still a minor yellow flag, to test for if (res == true) or if (res). It would be good to remove the useless variable and test directly for if (areAnagrams(str1, str2)).



          Similarly, in the body of areAnagrams, you have written



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          This is a very long-winded and confusing way of writing



          return str1 == str2;


          and is kind of a big deal. The interviewer is not looking to hire people who write eight lines of convoluted code when one line of simple code would do the job.



          You also have an extra blank line at the beginning of areAnagrams; this shows a possible tendency toward sloppiness. The interviewer is not looking to hire people who might "typo" their way into a bug.




          On the plus side, your definition of toLower is very good! The interviewer might ask you to explain why you took by value instead of by const&. The interviewer might ask you whether the line return str; makes a copy of the string or whether the copy is elided. (Trick question! The answer is "neither.")






          share|improve this answer














          I think interviewer will not be convinced with this solution because here it is no test of logic.




          I'm not sure what you mean by "because here it is no test of logic," but if what you mean is "because I found this puzzle too easy," then good! That's what the interviewer is likely to be hiring for: people who solve problems easily and quickly.



          When you get an easy problem in an interview, that may be a sign that the interviewer is trying to judge your coding skills rather than your algorithmic/research skills. So make sure your code is as polished as (reasonably) possible.



          • areAnagrams takes its parameters by non-const reference. This is probably a bug. The interviewer will ask you to "explain your choice." Your answer should be something like "oops, I forgot to remove the &." (This reflects a little badly on your coding skills.)


          • if (res == 1) is a very strange way to test for boolean true-ness. It would be less unusual, but still a minor yellow flag, to test for if (res == true) or if (res). It would be good to remove the useless variable and test directly for if (areAnagrams(str1, str2)).



          Similarly, in the body of areAnagrams, you have written



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          This is a very long-winded and confusing way of writing



          return str1 == str2;


          and is kind of a big deal. The interviewer is not looking to hire people who write eight lines of convoluted code when one line of simple code would do the job.



          You also have an extra blank line at the beginning of areAnagrams; this shows a possible tendency toward sloppiness. The interviewer is not looking to hire people who might "typo" their way into a bug.




          On the plus side, your definition of toLower is very good! The interviewer might ask you to explain why you took by value instead of by const&. The interviewer might ask you whether the line return str; makes a copy of the string or whether the copy is elided. (Trick question! The answer is "neither.")







          share|improve this answer













          share|improve this answer



          share|improve this answer











          answered Aug 2 at 17:22









          Quuxplusone

          9,62011451




          9,62011451











          • The answer is "neither." Why does NRVO not work in this case?
            – yuri
            Aug 2 at 20:22






          • 4




            Funny you should ask! NRVO works by constructing the object str directly into toLower's return slot. But in this case, toLower does not control where str gets constructed (because str is a parameter). The result is that str will be moved into the return slot — neither copied nor copy-elided, but moved.
            – Quuxplusone
            Aug 2 at 23:07
















          • The answer is "neither." Why does NRVO not work in this case?
            – yuri
            Aug 2 at 20:22






          • 4




            Funny you should ask! NRVO works by constructing the object str directly into toLower's return slot. But in this case, toLower does not control where str gets constructed (because str is a parameter). The result is that str will be moved into the return slot — neither copied nor copy-elided, but moved.
            – Quuxplusone
            Aug 2 at 23:07















          The answer is "neither." Why does NRVO not work in this case?
          – yuri
          Aug 2 at 20:22




          The answer is "neither." Why does NRVO not work in this case?
          – yuri
          Aug 2 at 20:22




          4




          4




          Funny you should ask! NRVO works by constructing the object str directly into toLower's return slot. But in this case, toLower does not control where str gets constructed (because str is a parameter). The result is that str will be moved into the return slot — neither copied nor copy-elided, but moved.
          – Quuxplusone
          Aug 2 at 23:07




          Funny you should ask! NRVO works by constructing the object str directly into toLower's return slot. But in this case, toLower does not control where str gets constructed (because str is a parameter). The result is that str will be moved into the return slot — neither copied nor copy-elided, but moved.
          – Quuxplusone
          Aug 2 at 23:07












          up vote
          9
          down vote













          I see some things that may help you improve your code.




          bool is not int



          The bool type is a full-fledged first class type in C++. If I were an interviewer reading this code, I'd be perplexed:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          A similar thing is being done here:



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          First, we are comparing a bool to 1 (an int) which is odd enough. Next, if we're returning the result of the comparison, why don't we return the result of the comparison?



          return !str1.compare(str2);


          Better still:



          return str1 == str2;


          Understand references



          The prototype of the toLower function is this:



          std::string toLower(std::string str);
          bool areAnagrams(std::string& str1, std::string& str2);


          So reading this, the toLower makes a copy of its argument and areAnagrams uses references. However, the first few lines of the latter function are these:



          str1 = toLower(str1);
          str2 = toLower(str2);


          There's little point to making copies and then assigning the copy back to the original. What I would recommend instead is to have toLower take a reference and areAnagrams pass by value. That way, we have a much more logical interface in which toLower modifies the passed string but areAnagrams does not.



          Use auto to simplify code



          The better choice for res in main would be to declare it auto instead of explicitly naming bool.



          Consider the use of locale



          Rather than writing your own toLower, why not use the one in <locale>? Here's how that might look:



          auto& facetstd::use_facet<std::ctype<char>>(std::locale());
          facet.tolower(&str1.front(), &str1.back());
          facet.tolower(&str2.front(), &str2.back());


          Use better naming



          The function toLower is a good name because (with the suggested change mentioned above) it says what it actually does. However, res is not a good name and it's not necessary to have a separate variable anyway. Instead of this strange construction:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          I would probably instead have written this:



          std::cout << "Strings " << (areAnagrams(str1, str2) ? "are" : "are not")
          << " anagramsn";


          Although, as @TobySpeight points out in a comment, better for the purposes of translating the string into another language would be to keep the strings intact. One way to do that:



          std::cout << (areAnagrams(str1, str2) ? "Strings are anagramsn"
          : "Strings are not anagramsn");


          Declare variables each on a separate line



          Clarify variable declaration by declaring each one on a single line. See Guideline ES.10



          Consider namespace or static



          During an interview, I'd probably ask why you chose not to encapsulate the functions in a namespace, and why the functions are not static. There are arguments both ways for each of those; be aware of what they are and be able to explain and defend your choices.






          share|improve this answer























          • std::string::compare returns <0, 0, or >0, so the first part of your answer doesn't make any sense.
            – jamesdlin
            Aug 2 at 22:25










          • @jamesdlin: it was missing a ! which is now corrected.
            – Edward
            Aug 2 at 22:47






          • 3




            I meant that the whole "bool is not int" premise is misdirected ("we are comparing a bool to 0..."; no, it's comparing int to 0). Regarding your edit: I personally dislike !str.compare(str) for the same reason as you originally give: bool is not int, and ! on an int seems weird.
            – jamesdlin
            Aug 2 at 22:55







          • 1




            First, within main we have if (res == 1) which is comparing a bool to an int. Second, I agree that !str1.compare(str2) is not very good, which is why what I recommend instead is return str1 == str2; which I suspect we both agree is the most clear and straightforward way to do it.
            – Edward
            Aug 2 at 23:12






          • 2




            Under "Use better naming", you go a bit further than I would. There's an argument against breaking strings into pieces like that - it's an anti-pattern that hinders translation. When your program is likely to be translated (and in an interview you do want to demonstrate that you can work with translators), it's usually better to keep strings whole - this is where C-style format strings can be valuable: std::printf(areAnagrams(str1, str2) ? "%s is an anagram of %sn" : "%s is not an anagram of %sn", str1.c_str(), str2.c_str());
            – Toby Speight
            Aug 3 at 7:59














          up vote
          9
          down vote













          I see some things that may help you improve your code.




          bool is not int



          The bool type is a full-fledged first class type in C++. If I were an interviewer reading this code, I'd be perplexed:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          A similar thing is being done here:



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          First, we are comparing a bool to 1 (an int) which is odd enough. Next, if we're returning the result of the comparison, why don't we return the result of the comparison?



          return !str1.compare(str2);


          Better still:



          return str1 == str2;


          Understand references



          The prototype of the toLower function is this:



          std::string toLower(std::string str);
          bool areAnagrams(std::string& str1, std::string& str2);


          So reading this, the toLower makes a copy of its argument and areAnagrams uses references. However, the first few lines of the latter function are these:



          str1 = toLower(str1);
          str2 = toLower(str2);


          There's little point to making copies and then assigning the copy back to the original. What I would recommend instead is to have toLower take a reference and areAnagrams pass by value. That way, we have a much more logical interface in which toLower modifies the passed string but areAnagrams does not.



          Use auto to simplify code



          The better choice for res in main would be to declare it auto instead of explicitly naming bool.



          Consider the use of locale



          Rather than writing your own toLower, why not use the one in <locale>? Here's how that might look:



          auto& facetstd::use_facet<std::ctype<char>>(std::locale());
          facet.tolower(&str1.front(), &str1.back());
          facet.tolower(&str2.front(), &str2.back());


          Use better naming



          The function toLower is a good name because (with the suggested change mentioned above) it says what it actually does. However, res is not a good name and it's not necessary to have a separate variable anyway. Instead of this strange construction:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          I would probably instead have written this:



          std::cout << "Strings " << (areAnagrams(str1, str2) ? "are" : "are not")
          << " anagramsn";


          Although, as @TobySpeight points out in a comment, better for the purposes of translating the string into another language would be to keep the strings intact. One way to do that:



          std::cout << (areAnagrams(str1, str2) ? "Strings are anagramsn"
          : "Strings are not anagramsn");


          Declare variables each on a separate line



          Clarify variable declaration by declaring each one on a single line. See Guideline ES.10



          Consider namespace or static



          During an interview, I'd probably ask why you chose not to encapsulate the functions in a namespace, and why the functions are not static. There are arguments both ways for each of those; be aware of what they are and be able to explain and defend your choices.






          share|improve this answer























          • std::string::compare returns <0, 0, or >0, so the first part of your answer doesn't make any sense.
            – jamesdlin
            Aug 2 at 22:25










          • @jamesdlin: it was missing a ! which is now corrected.
            – Edward
            Aug 2 at 22:47






          • 3




            I meant that the whole "bool is not int" premise is misdirected ("we are comparing a bool to 0..."; no, it's comparing int to 0). Regarding your edit: I personally dislike !str.compare(str) for the same reason as you originally give: bool is not int, and ! on an int seems weird.
            – jamesdlin
            Aug 2 at 22:55







          • 1




            First, within main we have if (res == 1) which is comparing a bool to an int. Second, I agree that !str1.compare(str2) is not very good, which is why what I recommend instead is return str1 == str2; which I suspect we both agree is the most clear and straightforward way to do it.
            – Edward
            Aug 2 at 23:12






          • 2




            Under "Use better naming", you go a bit further than I would. There's an argument against breaking strings into pieces like that - it's an anti-pattern that hinders translation. When your program is likely to be translated (and in an interview you do want to demonstrate that you can work with translators), it's usually better to keep strings whole - this is where C-style format strings can be valuable: std::printf(areAnagrams(str1, str2) ? "%s is an anagram of %sn" : "%s is not an anagram of %sn", str1.c_str(), str2.c_str());
            – Toby Speight
            Aug 3 at 7:59












          up vote
          9
          down vote










          up vote
          9
          down vote









          I see some things that may help you improve your code.




          bool is not int



          The bool type is a full-fledged first class type in C++. If I were an interviewer reading this code, I'd be perplexed:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          A similar thing is being done here:



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          First, we are comparing a bool to 1 (an int) which is odd enough. Next, if we're returning the result of the comparison, why don't we return the result of the comparison?



          return !str1.compare(str2);


          Better still:



          return str1 == str2;


          Understand references



          The prototype of the toLower function is this:



          std::string toLower(std::string str);
          bool areAnagrams(std::string& str1, std::string& str2);


          So reading this, the toLower makes a copy of its argument and areAnagrams uses references. However, the first few lines of the latter function are these:



          str1 = toLower(str1);
          str2 = toLower(str2);


          There's little point to making copies and then assigning the copy back to the original. What I would recommend instead is to have toLower take a reference and areAnagrams pass by value. That way, we have a much more logical interface in which toLower modifies the passed string but areAnagrams does not.



          Use auto to simplify code



          The better choice for res in main would be to declare it auto instead of explicitly naming bool.



          Consider the use of locale



          Rather than writing your own toLower, why not use the one in <locale>? Here's how that might look:



          auto& facetstd::use_facet<std::ctype<char>>(std::locale());
          facet.tolower(&str1.front(), &str1.back());
          facet.tolower(&str2.front(), &str2.back());


          Use better naming



          The function toLower is a good name because (with the suggested change mentioned above) it says what it actually does. However, res is not a good name and it's not necessary to have a separate variable anyway. Instead of this strange construction:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          I would probably instead have written this:



          std::cout << "Strings " << (areAnagrams(str1, str2) ? "are" : "are not")
          << " anagramsn";


          Although, as @TobySpeight points out in a comment, better for the purposes of translating the string into another language would be to keep the strings intact. One way to do that:



          std::cout << (areAnagrams(str1, str2) ? "Strings are anagramsn"
          : "Strings are not anagramsn");


          Declare variables each on a separate line



          Clarify variable declaration by declaring each one on a single line. See Guideline ES.10



          Consider namespace or static



          During an interview, I'd probably ask why you chose not to encapsulate the functions in a namespace, and why the functions are not static. There are arguments both ways for each of those; be aware of what they are and be able to explain and defend your choices.






          share|improve this answer















          I see some things that may help you improve your code.




          bool is not int



          The bool type is a full-fledged first class type in C++. If I were an interviewer reading this code, I'd be perplexed:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          A similar thing is being done here:



          if (str1.compare(str2) == 0)

          return true;

          else

          return false;



          First, we are comparing a bool to 1 (an int) which is odd enough. Next, if we're returning the result of the comparison, why don't we return the result of the comparison?



          return !str1.compare(str2);


          Better still:



          return str1 == str2;


          Understand references



          The prototype of the toLower function is this:



          std::string toLower(std::string str);
          bool areAnagrams(std::string& str1, std::string& str2);


          So reading this, the toLower makes a copy of its argument and areAnagrams uses references. However, the first few lines of the latter function are these:



          str1 = toLower(str1);
          str2 = toLower(str2);


          There's little point to making copies and then assigning the copy back to the original. What I would recommend instead is to have toLower take a reference and areAnagrams pass by value. That way, we have a much more logical interface in which toLower modifies the passed string but areAnagrams does not.



          Use auto to simplify code



          The better choice for res in main would be to declare it auto instead of explicitly naming bool.



          Consider the use of locale



          Rather than writing your own toLower, why not use the one in <locale>? Here's how that might look:



          auto& facetstd::use_facet<std::ctype<char>>(std::locale());
          facet.tolower(&str1.front(), &str1.back());
          facet.tolower(&str2.front(), &str2.back());


          Use better naming



          The function toLower is a good name because (with the suggested change mentioned above) it says what it actually does. However, res is not a good name and it's not necessary to have a separate variable anyway. Instead of this strange construction:



          bool res = areAnagrams(str1, str2);
          if (res == 1)

          std::cout << "Strings are anagramn";

          else

          std::cout << "Strings are not anagramn";



          I would probably instead have written this:



          std::cout << "Strings " << (areAnagrams(str1, str2) ? "are" : "are not")
          << " anagramsn";


          Although, as @TobySpeight points out in a comment, better for the purposes of translating the string into another language would be to keep the strings intact. One way to do that:



          std::cout << (areAnagrams(str1, str2) ? "Strings are anagramsn"
          : "Strings are not anagramsn");


          Declare variables each on a separate line



          Clarify variable declaration by declaring each one on a single line. See Guideline ES.10



          Consider namespace or static



          During an interview, I'd probably ask why you chose not to encapsulate the functions in a namespace, and why the functions are not static. There are arguments both ways for each of those; be aware of what they are and be able to explain and defend your choices.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Aug 3 at 11:36


























          answered Aug 2 at 17:45









          Edward

          43.8k373199




          43.8k373199











          • std::string::compare returns <0, 0, or >0, so the first part of your answer doesn't make any sense.
            – jamesdlin
            Aug 2 at 22:25










          • @jamesdlin: it was missing a ! which is now corrected.
            – Edward
            Aug 2 at 22:47






          • 3




            I meant that the whole "bool is not int" premise is misdirected ("we are comparing a bool to 0..."; no, it's comparing int to 0). Regarding your edit: I personally dislike !str.compare(str) for the same reason as you originally give: bool is not int, and ! on an int seems weird.
            – jamesdlin
            Aug 2 at 22:55







          • 1




            First, within main we have if (res == 1) which is comparing a bool to an int. Second, I agree that !str1.compare(str2) is not very good, which is why what I recommend instead is return str1 == str2; which I suspect we both agree is the most clear and straightforward way to do it.
            – Edward
            Aug 2 at 23:12






          • 2




            Under "Use better naming", you go a bit further than I would. There's an argument against breaking strings into pieces like that - it's an anti-pattern that hinders translation. When your program is likely to be translated (and in an interview you do want to demonstrate that you can work with translators), it's usually better to keep strings whole - this is where C-style format strings can be valuable: std::printf(areAnagrams(str1, str2) ? "%s is an anagram of %sn" : "%s is not an anagram of %sn", str1.c_str(), str2.c_str());
            – Toby Speight
            Aug 3 at 7:59
















          • std::string::compare returns <0, 0, or >0, so the first part of your answer doesn't make any sense.
            – jamesdlin
            Aug 2 at 22:25










          • @jamesdlin: it was missing a ! which is now corrected.
            – Edward
            Aug 2 at 22:47






          • 3




            I meant that the whole "bool is not int" premise is misdirected ("we are comparing a bool to 0..."; no, it's comparing int to 0). Regarding your edit: I personally dislike !str.compare(str) for the same reason as you originally give: bool is not int, and ! on an int seems weird.
            – jamesdlin
            Aug 2 at 22:55







          • 1




            First, within main we have if (res == 1) which is comparing a bool to an int. Second, I agree that !str1.compare(str2) is not very good, which is why what I recommend instead is return str1 == str2; which I suspect we both agree is the most clear and straightforward way to do it.
            – Edward
            Aug 2 at 23:12






          • 2




            Under "Use better naming", you go a bit further than I would. There's an argument against breaking strings into pieces like that - it's an anti-pattern that hinders translation. When your program is likely to be translated (and in an interview you do want to demonstrate that you can work with translators), it's usually better to keep strings whole - this is where C-style format strings can be valuable: std::printf(areAnagrams(str1, str2) ? "%s is an anagram of %sn" : "%s is not an anagram of %sn", str1.c_str(), str2.c_str());
            – Toby Speight
            Aug 3 at 7:59















          std::string::compare returns <0, 0, or >0, so the first part of your answer doesn't make any sense.
          – jamesdlin
          Aug 2 at 22:25




          std::string::compare returns <0, 0, or >0, so the first part of your answer doesn't make any sense.
          – jamesdlin
          Aug 2 at 22:25












          @jamesdlin: it was missing a ! which is now corrected.
          – Edward
          Aug 2 at 22:47




          @jamesdlin: it was missing a ! which is now corrected.
          – Edward
          Aug 2 at 22:47




          3




          3




          I meant that the whole "bool is not int" premise is misdirected ("we are comparing a bool to 0..."; no, it's comparing int to 0). Regarding your edit: I personally dislike !str.compare(str) for the same reason as you originally give: bool is not int, and ! on an int seems weird.
          – jamesdlin
          Aug 2 at 22:55





          I meant that the whole "bool is not int" premise is misdirected ("we are comparing a bool to 0..."; no, it's comparing int to 0). Regarding your edit: I personally dislike !str.compare(str) for the same reason as you originally give: bool is not int, and ! on an int seems weird.
          – jamesdlin
          Aug 2 at 22:55





          1




          1




          First, within main we have if (res == 1) which is comparing a bool to an int. Second, I agree that !str1.compare(str2) is not very good, which is why what I recommend instead is return str1 == str2; which I suspect we both agree is the most clear and straightforward way to do it.
          – Edward
          Aug 2 at 23:12




          First, within main we have if (res == 1) which is comparing a bool to an int. Second, I agree that !str1.compare(str2) is not very good, which is why what I recommend instead is return str1 == str2; which I suspect we both agree is the most clear and straightforward way to do it.
          – Edward
          Aug 2 at 23:12




          2




          2




          Under "Use better naming", you go a bit further than I would. There's an argument against breaking strings into pieces like that - it's an anti-pattern that hinders translation. When your program is likely to be translated (and in an interview you do want to demonstrate that you can work with translators), it's usually better to keep strings whole - this is where C-style format strings can be valuable: std::printf(areAnagrams(str1, str2) ? "%s is an anagram of %sn" : "%s is not an anagram of %sn", str1.c_str(), str2.c_str());
          – Toby Speight
          Aug 3 at 7:59




          Under "Use better naming", you go a bit further than I would. There's an argument against breaking strings into pieces like that - it's an anti-pattern that hinders translation. When your program is likely to be translated (and in an interview you do want to demonstrate that you can work with translators), it's usually better to keep strings whole - this is where C-style format strings can be valuable: std::printf(areAnagrams(str1, str2) ? "%s is an anagram of %sn" : "%s is not an anagram of %sn", str1.c_str(), str2.c_str());
          – Toby Speight
          Aug 3 at 7:59










          up vote
          2
          down vote













          You know, when deciding whether you have anagrams, you are generally only interested in alpha-numeric characters, the rest are disregarded.



          Next, making extraneous copies is generally a bad idea. So, accept a constant view and don't make a copy.



          When you accept a mutable reference, be sure that it's obvious from the function-name and arity that it's a mutable reference.



          If you can, avoid external linkage. It promotes inlining and avoids unfortunate name-clashes.



          Finally, a faster algorithm is normally preferable:



          bool isAnagram(std::string_view a, std::string_view b) noexcept 
          unsigned counts[1ULL + (unsigned char)-1] = ;
          for (unsigned char c : a)
          ++counts[std::tolower(c)];
          for (unsigned char c : b)
          --counts[std::tolower(c)];
          for (std::size_t i = 0; i < std::size(counts); ++i)
          if (counts[i] && std::isalnum(i))
          return false;
          return true;






          share|improve this answer



















          • 3




            While this may be a faster algorithm, is it a clearer algorithm? I think that for an interview, it may be better to write for clarity.
            – Edward
            Aug 2 at 18:21










          • @Edward Yes, I would say so.
            – Deduplicator
            Aug 2 at 18:49










          • (2) This code is different from OP's, it ignores non-alnum characters. (3) It's actually slower for short string, as it allocates an array of ~256 ints.
            – user176443
            Aug 3 at 3:56











          • Why int map? unsigned map will likely give the right answer in most cases for extremely long strings even if a bucket wraps around, without any signed-overflow UB. (If you can rule out long strings, unsigned char map cuts the cache footprint by 4 on most modern C++ implementations, and allows faster checking for non-zero buckets on targets where the compiler can use SIMD for the final loop.) I was going to say uint8_t, but you don't need to stop the code from working on implementations without uint8_t, like some DSPs where char is 32 bits.
            – Peter Cordes
            Aug 3 at 8:10






          • 1




            @user17... If you're checking all characters, then check if lengths are equal as an early-out before doing anything else. But allocating 1kiB on the stack is basically free; literally 1 instruction. Zeroing it has some small cost. Touching it might cause some cache misses, but store-forwarding might manage to hide a lot of the cost of that (i.e. the reloads don't have to wait for the stores to commit); only 32x 32-byte stores, so maybe 32 store-buffer entries for zeroing it. The load part of each increment should forward from the zeroing, but the store part uses another buffer.
            – Peter Cordes
            Aug 3 at 11:14















          up vote
          2
          down vote













          You know, when deciding whether you have anagrams, you are generally only interested in alpha-numeric characters, the rest are disregarded.



          Next, making extraneous copies is generally a bad idea. So, accept a constant view and don't make a copy.



          When you accept a mutable reference, be sure that it's obvious from the function-name and arity that it's a mutable reference.



          If you can, avoid external linkage. It promotes inlining and avoids unfortunate name-clashes.



          Finally, a faster algorithm is normally preferable:



          bool isAnagram(std::string_view a, std::string_view b) noexcept 
          unsigned counts[1ULL + (unsigned char)-1] = ;
          for (unsigned char c : a)
          ++counts[std::tolower(c)];
          for (unsigned char c : b)
          --counts[std::tolower(c)];
          for (std::size_t i = 0; i < std::size(counts); ++i)
          if (counts[i] && std::isalnum(i))
          return false;
          return true;






          share|improve this answer



















          • 3




            While this may be a faster algorithm, is it a clearer algorithm? I think that for an interview, it may be better to write for clarity.
            – Edward
            Aug 2 at 18:21










          • @Edward Yes, I would say so.
            – Deduplicator
            Aug 2 at 18:49










          • (2) This code is different from OP's, it ignores non-alnum characters. (3) It's actually slower for short string, as it allocates an array of ~256 ints.
            – user176443
            Aug 3 at 3:56











          • Why int map? unsigned map will likely give the right answer in most cases for extremely long strings even if a bucket wraps around, without any signed-overflow UB. (If you can rule out long strings, unsigned char map cuts the cache footprint by 4 on most modern C++ implementations, and allows faster checking for non-zero buckets on targets where the compiler can use SIMD for the final loop.) I was going to say uint8_t, but you don't need to stop the code from working on implementations without uint8_t, like some DSPs where char is 32 bits.
            – Peter Cordes
            Aug 3 at 8:10






          • 1




            @user17... If you're checking all characters, then check if lengths are equal as an early-out before doing anything else. But allocating 1kiB on the stack is basically free; literally 1 instruction. Zeroing it has some small cost. Touching it might cause some cache misses, but store-forwarding might manage to hide a lot of the cost of that (i.e. the reloads don't have to wait for the stores to commit); only 32x 32-byte stores, so maybe 32 store-buffer entries for zeroing it. The load part of each increment should forward from the zeroing, but the store part uses another buffer.
            – Peter Cordes
            Aug 3 at 11:14













          up vote
          2
          down vote










          up vote
          2
          down vote









          You know, when deciding whether you have anagrams, you are generally only interested in alpha-numeric characters, the rest are disregarded.



          Next, making extraneous copies is generally a bad idea. So, accept a constant view and don't make a copy.



          When you accept a mutable reference, be sure that it's obvious from the function-name and arity that it's a mutable reference.



          If you can, avoid external linkage. It promotes inlining and avoids unfortunate name-clashes.



          Finally, a faster algorithm is normally preferable:



          bool isAnagram(std::string_view a, std::string_view b) noexcept 
          unsigned counts[1ULL + (unsigned char)-1] = ;
          for (unsigned char c : a)
          ++counts[std::tolower(c)];
          for (unsigned char c : b)
          --counts[std::tolower(c)];
          for (std::size_t i = 0; i < std::size(counts); ++i)
          if (counts[i] && std::isalnum(i))
          return false;
          return true;






          share|improve this answer















          You know, when deciding whether you have anagrams, you are generally only interested in alpha-numeric characters, the rest are disregarded.



          Next, making extraneous copies is generally a bad idea. So, accept a constant view and don't make a copy.



          When you accept a mutable reference, be sure that it's obvious from the function-name and arity that it's a mutable reference.



          If you can, avoid external linkage. It promotes inlining and avoids unfortunate name-clashes.



          Finally, a faster algorithm is normally preferable:



          bool isAnagram(std::string_view a, std::string_view b) noexcept 
          unsigned counts[1ULL + (unsigned char)-1] = ;
          for (unsigned char c : a)
          ++counts[std::tolower(c)];
          for (unsigned char c : b)
          --counts[std::tolower(c)];
          for (std::size_t i = 0; i < std::size(counts); ++i)
          if (counts[i] && std::isalnum(i))
          return false;
          return true;







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Aug 3 at 10:50


























          answered Aug 2 at 17:56









          Deduplicator

          9,7211744




          9,7211744







          • 3




            While this may be a faster algorithm, is it a clearer algorithm? I think that for an interview, it may be better to write for clarity.
            – Edward
            Aug 2 at 18:21










          • @Edward Yes, I would say so.
            – Deduplicator
            Aug 2 at 18:49










          • (2) This code is different from OP's, it ignores non-alnum characters. (3) It's actually slower for short string, as it allocates an array of ~256 ints.
            – user176443
            Aug 3 at 3:56











          • Why int map? unsigned map will likely give the right answer in most cases for extremely long strings even if a bucket wraps around, without any signed-overflow UB. (If you can rule out long strings, unsigned char map cuts the cache footprint by 4 on most modern C++ implementations, and allows faster checking for non-zero buckets on targets where the compiler can use SIMD for the final loop.) I was going to say uint8_t, but you don't need to stop the code from working on implementations without uint8_t, like some DSPs where char is 32 bits.
            – Peter Cordes
            Aug 3 at 8:10






          • 1




            @user17... If you're checking all characters, then check if lengths are equal as an early-out before doing anything else. But allocating 1kiB on the stack is basically free; literally 1 instruction. Zeroing it has some small cost. Touching it might cause some cache misses, but store-forwarding might manage to hide a lot of the cost of that (i.e. the reloads don't have to wait for the stores to commit); only 32x 32-byte stores, so maybe 32 store-buffer entries for zeroing it. The load part of each increment should forward from the zeroing, but the store part uses another buffer.
            – Peter Cordes
            Aug 3 at 11:14













          • 3




            While this may be a faster algorithm, is it a clearer algorithm? I think that for an interview, it may be better to write for clarity.
            – Edward
            Aug 2 at 18:21










          • @Edward Yes, I would say so.
            – Deduplicator
            Aug 2 at 18:49










          • (2) This code is different from OP's, it ignores non-alnum characters. (3) It's actually slower for short string, as it allocates an array of ~256 ints.
            – user176443
            Aug 3 at 3:56











          • Why int map? unsigned map will likely give the right answer in most cases for extremely long strings even if a bucket wraps around, without any signed-overflow UB. (If you can rule out long strings, unsigned char map cuts the cache footprint by 4 on most modern C++ implementations, and allows faster checking for non-zero buckets on targets where the compiler can use SIMD for the final loop.) I was going to say uint8_t, but you don't need to stop the code from working on implementations without uint8_t, like some DSPs where char is 32 bits.
            – Peter Cordes
            Aug 3 at 8:10






          • 1




            @user17... If you're checking all characters, then check if lengths are equal as an early-out before doing anything else. But allocating 1kiB on the stack is basically free; literally 1 instruction. Zeroing it has some small cost. Touching it might cause some cache misses, but store-forwarding might manage to hide a lot of the cost of that (i.e. the reloads don't have to wait for the stores to commit); only 32x 32-byte stores, so maybe 32 store-buffer entries for zeroing it. The load part of each increment should forward from the zeroing, but the store part uses another buffer.
            – Peter Cordes
            Aug 3 at 11:14








          3




          3




          While this may be a faster algorithm, is it a clearer algorithm? I think that for an interview, it may be better to write for clarity.
          – Edward
          Aug 2 at 18:21




          While this may be a faster algorithm, is it a clearer algorithm? I think that for an interview, it may be better to write for clarity.
          – Edward
          Aug 2 at 18:21












          @Edward Yes, I would say so.
          – Deduplicator
          Aug 2 at 18:49




          @Edward Yes, I would say so.
          – Deduplicator
          Aug 2 at 18:49












          (2) This code is different from OP's, it ignores non-alnum characters. (3) It's actually slower for short string, as it allocates an array of ~256 ints.
          – user176443
          Aug 3 at 3:56





          (2) This code is different from OP's, it ignores non-alnum characters. (3) It's actually slower for short string, as it allocates an array of ~256 ints.
          – user176443
          Aug 3 at 3:56













          Why int map? unsigned map will likely give the right answer in most cases for extremely long strings even if a bucket wraps around, without any signed-overflow UB. (If you can rule out long strings, unsigned char map cuts the cache footprint by 4 on most modern C++ implementations, and allows faster checking for non-zero buckets on targets where the compiler can use SIMD for the final loop.) I was going to say uint8_t, but you don't need to stop the code from working on implementations without uint8_t, like some DSPs where char is 32 bits.
          – Peter Cordes
          Aug 3 at 8:10




          Why int map? unsigned map will likely give the right answer in most cases for extremely long strings even if a bucket wraps around, without any signed-overflow UB. (If you can rule out long strings, unsigned char map cuts the cache footprint by 4 on most modern C++ implementations, and allows faster checking for non-zero buckets on targets where the compiler can use SIMD for the final loop.) I was going to say uint8_t, but you don't need to stop the code from working on implementations without uint8_t, like some DSPs where char is 32 bits.
          – Peter Cordes
          Aug 3 at 8:10




          1




          1




          @user17... If you're checking all characters, then check if lengths are equal as an early-out before doing anything else. But allocating 1kiB on the stack is basically free; literally 1 instruction. Zeroing it has some small cost. Touching it might cause some cache misses, but store-forwarding might manage to hide a lot of the cost of that (i.e. the reloads don't have to wait for the stores to commit); only 32x 32-byte stores, so maybe 32 store-buffer entries for zeroing it. The load part of each increment should forward from the zeroing, but the store part uses another buffer.
          – Peter Cordes
          Aug 3 at 11:14





          @user17... If you're checking all characters, then check if lengths are equal as an early-out before doing anything else. But allocating 1kiB on the stack is basically free; literally 1 instruction. Zeroing it has some small cost. Touching it might cause some cache misses, but store-forwarding might manage to hide a lot of the cost of that (i.e. the reloads don't have to wait for the stores to commit); only 32x 32-byte stores, so maybe 32 store-buffer entries for zeroing it. The load part of each increment should forward from the zeroing, but the store part uses another buffer.
          – Peter Cordes
          Aug 3 at 11:14













           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200835%2fare-strings-anagram%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Greedy Best First Search implementation in Rust

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          C++11 CLH Lock Implementation