2

I was wondering how one would create a function that could accept an input such as "Computre", or any possibility... "Cmoputer," "romputeC" instead of "Computer".

//This function would be something like this:
void ignore_switched_letters(char word[]);

int main(){//...}

void ignore_switched_letters(char word[]){
     //... code implimentation...
     char computer[9] = "Computer";
     int length = strlen(computer);
     for (int i = 0; i < length; ++i){
          if (word[i] == 'C'){ ....
          }
     }
}
nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • I've tried iterating through character arrays, but I've been struggling with how to do it. If I were to iterate through all the indexes in the character array "word" and see if it matches all of the letters, that would be quite the mess. – Dave Thomas Jul 15 '15 at 05:51
  • Possible duplicate of http://stackoverflow.com/questions/12257735/detect-a-permutation-of-sequence – marom Jul 15 '15 at 05:59
  • possible duplicate of [finding if two words are anagrams of each other](http://stackoverflow.com/questions/4236906/finding-if-two-words-are-anagrams-of-each-other) – Ken Y-N Jul 15 '15 at 06:02
  • Are you just trying to ignore a single switch? Or is any permutation ok? – Chris Drew Jul 15 '15 at 06:04
  • Any permutation involving a switch between 2 characters. – Dave Thomas Jul 15 '15 at 06:06
  • If its any 2 letters that are switched, create an iteration that would compare 2 strings and have a counter for each letter that matched up. Once the counter reaches length -2. Have the other word automatically be set to the compared word. Do you want me to show you? – TimLayne Jul 15 '15 at 06:13

6 Answers6

2

I recommend you put the word in a std::string in all lower-case. Then you have the power of standard library algorithms available to you including std::mismatch which returns the first position where two ranges differ. You can check if there are two mismatches that are inverse to each other. It is probably more flexible to write it as a function that compares two words:

#include <string>
#include <algorithm>
#include <cassert>

bool compareIgnoreSingleSwitch(const std::string& word1, const std::string& word2) {
  if (word1.size() != word2.size())
    return false;

  auto mismatch1 = std::mismatch(word1.begin(), word1.end(), word2.begin());
  if (mismatch1.first == word1.end())
    return true;  // no mismatches

  auto mismatch2 
    = std::mismatch(std::next(mismatch1.first), word1.end(), std::next(mismatch1.second));

  if (mismatch2.first == word1.end())
    return false;  // only one mismatch, can't be a switch

  // check the two mismatches are inverse of each other
  if (*mismatch1.first != *mismatch2.second || *mismatch1.second != *mismatch2.first)
    return false;

  // ensure no more mismatches  
  return std::equal(std::next(mismatch2.first), word1.end(), std::next(mismatch2.second));
}

int main() {
  assert(compareIgnoreSingleSwitch("computer", "computer"));  // equal
  assert(compareIgnoreSingleSwitch("computer", "pomcuter"));  // one switch
  assert(!compareIgnoreSingleSwitch("computer", "aomxuter"));  // not a switch 
  assert(!compareIgnoreSingleSwitch("computer", "pomputer"));  // one mismatch
  assert(!compareIgnoreSingleSwitch("computer", "ocmupter"));  // two switches
  assert(!compareIgnoreSingleSwitch("computer", "compute"));  // different length    
}

Live demo.

Chris Drew
  • 14,926
  • 3
  • 34
  • 54
0

This is more or less (1) compare astr and bstr until you find a difference. (2) Remember the difference (3) Continue to compare until you find a second diff (4) Check if the second diff matches the inverse of the first diff (5) continue to compare.

int main(int argc,char ** argv) {                                                                                                                                                                                                            
    std::string astr="Computer";                                                                                                                                                                                                             
    if(argc==2) {                                                                                                                                                                                                                            
        std::string bstr(argv[1]);                                                                                                                                                                                                           

        // Not the same length == no permutation                                                                                                                                                                                             
        if(astr.size()!=bstr.size()) {                                                                                                                                                                                                       
            std::cerr << "nope" << std::endl;                                                                                                                                                                                                
            return 1;
        }
        int i;
        for(i=0;i<astr.size();i++) {
            if(astr[i]!=bstr[i]) {
                break;
            }
        }

        // We iterated thru == strings are equal
        if(i==astr.size()) {
            std::cerr << "yes" << std::endl;
            return 0;
        }

        // We have found the one different char
        // continue iteration and search for the
        // second difference

        int j;

        for(j=i+1;j<astr.size();j++) {

            // another difference
            if(astr[j] != bstr[j]) {
                // it is the one from astr and vice versa
                if(astr[i] == bstr[j] && astr[j] == bstr[i]) {
                    break;
                }
                // No it isn't
                std::cerr << "*nope" << std::endl;
                return 1;
            }
        }

        // Didn't find the second difference
        if(j==astr.size()) {
            std::cerr << "nope" << std::endl;
            return 1;
        }
        j++;
        // All others have to be identical
        for(;j<astr.size();j++) {
            if(astr[j] != bstr[j]) {
                std::cerr << "nope" << std::endl;
                return 1;
            }
        }
        std::cerr << "yes" << std::endl;
        return 0;
    }
}
Oncaphillis
  • 1,888
  • 13
  • 15
0
it will return 1 if found else 0
int ignore_switched_letters(char word[]){
     //... code implimentation...
     char computer[9] = "Computer";
     int length = strlen(computer);
     int flag=1;
     for (int i = 0; i < length; ++i){
           int falg2=0;
          for (int j = 0; j < length; ++j)
               if(computer[i]==word[j]){ word[j]=0; falg2=1 }
            if(0==falg2)
             {
               flag=0;
               break;
             }
     }
      return flag;
}
Rsvay
  • 1,285
  • 2
  • 13
  • 36
0

I wrote a code for validate 2 switched letter in a desired char[]:

#include <iostream>
#include <string.h>

using namespace std;


bool is_ignore_switched_letters(char word[]);
void swapArray(char word[],const int &firstFlag,const int &secondFlag);
bool isEqual(const char A[] ,const char B[]);
int main()
{
char word[] = "Computre";
if(is_ignore_switched_letters(word)){
    cout<<"Accepted"<<endl;
}else{
    cout<<"Rejected"<<endl;
}

return 0;
}

bool is_ignore_switched_letters(char word[]){

 const char COMPUTER[9] = "Computer";
 int length = strlen(COMPUTER);

 int firstFlag = -1;
 int secondFlag = -1;


 for (int i = 0; i < length; ++i){

     if (word[i] != COMPUTER[i] and firstFlag== -1){
            firstFlag = i;
      }
      else if (word[i] != COMPUTER[i] and secondFlag== -1){
            secondFlag = i;
      }

     if(secondFlag != -1){
        swapArray(word,firstFlag,secondFlag);
        break;
      }
 }
 if(firstFlag==-1 || secondFlag == -1) {
    return false;
 }
 if(isEqual(COMPUTER,word)){
    return true;
 }
 else{
    return false;
 }

}

void swapArray(char word[],const int &firstFlag,const int &secondFlag){
char buf = word[firstFlag];
word[firstFlag] = word[secondFlag];
word[secondFlag] = buf;
}

bool isEqual(const char A[] ,const char B[]){
const int lengthA = strlen(A);
const int lengthB = strlen(B);
if(lengthA != lengthB) {return false;}
for(int i = 0 ; i < lengthA ; i++){
    if(A[i]!=B[i]) {return false;}
}
return true;
}
Anson Tan
  • 1,256
  • 2
  • 13
  • 34
0

All of these are very complicated. You should stick to the utilities at hand. I would highly recommend switching to a std::string interface and using the standard library algorithms.

Here's how I would solve your issue:

void ignore_switched_letters(const std::string &word){
    static std::string computer = "computer";
    if(!std::is_permutation(std::begin(computer), std::end(computer), std::begin(word)))
        throw std::runtime_error("string is not a permutation of 'computer'");

    // do whatever you like with 'word'
}

Of course you don't have to throw exceptions; but where performance isn't a concern, I like to.

A more generic solution may be even better:

template<typename Functor>
void ignore_switched_letters(const std::string &check, const std::string &word, Functor &&f){
    if(!std::is_permutation(std::begin(check), std::end(check), std::begin(word)))
        throw std::runtime_error(word + " is not a permutation of " check);

    f();
}

Then you can have multiple cases to check, like so:

int main(){
    std::string computer = "computer";
    std::string chair = "chair";
    std::string microwave = "microwave";

    try{
        ignore_switched_letters(computer, "puterc", [](){
            std::cout << "is a computer\n";
        });

        // throws 'std::runtime_error'
        ignore_switched_letters(chair, "hair", [](){
            std::cout << "is a chair\n";
        });

        ignore_switched_letters(microwave, "wavemicro", [](){
            std::cout << "is a microwave\n";
        });
    }
    catch(const std::exception &e){
        std::cerr << e.what() << '\n';
        exit(EXIT_FAILURE);
    }
}

Which is a nice little convenience.

EDIT

I jumped the gun and missed that you only wanted permutations of 2 characters, I'll leave my answer for interest though.

Community
  • 1
  • 1
RamblingMad
  • 5,332
  • 2
  • 24
  • 48
0

The Standard library has plenty of useful algorithms:

bool compareOnePermutation(std::string s1, std::string s2)
{
   if (!std::is_permutation(s1.begin(), s1.end(), s2.begin(), s2.end()))
   {
       return false; // strings contain different letters
   } 
   // Find the differences
   std::transform(s1.begin(),s1.end(),s2.begin(), s1.begin(), std::bit_xor<char>());
   int equal = std:count(s1.begin(),s1.end(), char(0));
   if (equal==s1.size()) return true; // s1==s2
   if (equal==s1.size()-2) return true; // Permutation with 1 swap.
   return false;
}

The trick used is that char1^char2 == 0 if and only if char1==char2. Thus after the transform I can quickly count zeroes. It's of course slightly more efficient to code this out yourself, as you just need to count the differences and can bail out when you reach 3:

// Find the differences
auto iter2 = s2.begin();
size_t diff = 0;
for (char c:s1) {
   if (c != *iter2++) ++diff;
   if (diff==3) return false;
}
return diff !=1;
MSalters
  • 173,980
  • 10
  • 155
  • 350