简体   繁体   中英

Find if 2 strings are composed of same letters

I have a problem, this function should return 1 if secret is composed of same letters than letters_guessed .

It works fine, as long as letters_guessed has atleast 1 same letter which are in the secret . If there is same letter 2 times or more, it does not work. I know why, but I can not solve it because I can not remove same letters. I can not remove same letters from letters_guessed array, because it is constant, and I can not change it to nonconstant.

Again ...

If:

secret = "cat"

letters_guessed = "txaoc"

return 1

**Right**

If:

secret = "dog"

letters_guessed = "gefxd"

return 0 

**Right**

If:

secret = "car"

letters_guessed = "ccr"

return 1

**Wrong, How can I solve this?**

Sorry for my bad English and long explanation. Here is my program:

 int is_word_guessed(const char secret[], const char letters_guessed[])
    {
    int same = 0;
    for(int i = 0; i < strlen(letters_guessed); i++)
    {
        for(int j = 0; j < strlen(secret); j++)
        {
            if(letters_guessed[i] == secret[j])
                same++;
        }
    }
    if (same == strlen(secret))
        return 1;
    else 
        return 0;
    }

You can:

  • make a copy of your strings in order to flag already counted letters (since you tell you don't want to modify the strings, I suggest making a copy first in order to discard already counted letters);
  • get sorted versions of your strings and then compare them with a single loop; this solution would also provide a better complexity (you could get O(n log n) instead of your current O(n^2) ).

You can keep iteration in memory by maintaining an array of all 26 alphabets.

Assumptions:- All letters should be in lower case. Secret should not have repeated letters.

Logic:- Make array entry to 1 if we have considered that letter. 97 is ascii value of 'a'

// declare header file

#include "string.h"


int is_word_guessed(const char secret[], const char letters_guessed[])
{
    int same = 0;

    int alphabets[26];
    // make all enteries 0
    for (int k = 0; k <= 25; k++)
    {
        alphabets[k] = 0;
    }

    for (int i = 0; i < strlen(letters_guessed); i++)
    {
        for (int j = 0; j < strlen(secret); j++)
        {
            if (letters_guessed[i] == secret[j] && (alphabets[(char)letters_guessed[i] - 97] == 0))
            {
                same++;
                alphabets[(char)letters_guessed[i] - 97] = 1;
            }
        }
    }
    if (same == strlen(secret))
        return 1;
    else
        return 0;
}

One way to do this without modifying the strings is to count the occurrences of letters in the strings. When the guess has more occurrences of a letter than the secret, it's a miss. The case where a letter occurs in the guess that isn't in the secret is just a special case, because then the count of occurrences in the secret is zero.

In practice, you don't keep two separate counts: Add the letters of the guess to the count first, then remove the letters of the secret. As soon as one count drops below zero, it's a miss.

You can make use of the fact that there are only 256 different chars and keep the counts in an array. The index to the array is the letter's ASCII code. Be careful not to access the array at negative indices. C's char isn't guaranteed to be unsigned, so you could cast it or use an unsigned temporary variable or chose not to consider negative values.

Here's an implementation:

int contains(const char *guess, const char *secret)
{
    int count[256] = {0};               // start with all-zero array

    while (*guess) {
        unsigned char c = *guess++;

        count[c]++;
    }

    while (*secret) {
        unsigned char c = *secret++;

        if (count[c] == 0) return 0;
        count[c]--;
    }

    return 1;
}

It's easy.
In Haskell it would be:

all (`elem` letters_guessed) secret

in other words: All chars in secret must be in letters_guessed.

In C its (not tested):

// Iterate though string 'secret' until there is a char not
// part of 'letters_guessed'. If there is none, return 1
unsigned check(char *secret, char *letters_guessed) {
  unsigned length_secret = length(secret);
  unsigned length_guessed = length(letters_guessed);

  for (int i = 0; i < length_secret; i++) {
    if (!elem(secret[i], letters_guessed) {
      return 0;
    }
  }

  return 1;
}

// Check if char 'current' is part of 'string'
unsigned elem(char current, char *string) {
  unsigned length = length(string);
  unsigned found = 0;

  for (int i = 0; i < length; i++) {
    if (current == string[i]) {
      return 1;
    }
  }

  return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM