简体   繁体   English

查找2个字符串是否由相同字母组成

[英]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 . 我有一个问题,如果这个功能应该返回1, secret是由相同的字母比letters_guessed

It works fine, as long as letters_guessed has atleast 1 same letter which are in the secret . 只要letters_guessed至少有1个相同的secret字母,它就可以正常工作。 If there is same letter 2 times or more, it does not work. 如果相同字母2次以上,则不起作用。 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. 我不能从letters_guessed数组中删除相同的字母,因为它是常量,因此无法将其更改为非常量。

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) ). 此解决方案还将提供更好的复杂性(您可以获得O(n log n)而不是当前的O(n ^ 2) )。

You can keep iteration in memory by maintaining an array of all 26 alphabets. 您可以通过维护所有26个字母组成的数组将迭代保留在内存中。

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. 逻辑:-如果我们考虑过该字母,则将数组条目设置为1。 97 is ascii value of 'a' 97是'a'的ascii值

// 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. 您可以利用只有256个不同字符的事实,并将计数保留在数组中。 The index to the array is the letter's ASCII code. 数组的索引是字母的ASCII码。 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. C的char不能保证是无符号的,因此您可以将其强制转换或使用无符号的临时变量,或者选择不考虑负值。

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: 在Haskell中,它将是:

all (`elem` letters_guessed) secret

in other words: All chars in secret must be in letters_guessed. 换句话说:所有秘密字符必须以字母猜测。

In C its (not tested): 在C中(未经测试):

// 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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