Как я могу исправить мой дескремблер python word?

#python

#python

Вопрос:

ВОПРОС: Завершите функцию scramble(str1, str2), которая возвращает true, если часть символов str1 может быть изменена в соответствии с str2, в противном случае возвращает false .

Примечания:

Будут использоваться только строчные буквы (a-z). Знаки препинания или цифры не будут включены. Необходимо учитывать производительность

 MY CODE:
s1 = 'rkqodlw'
s2 = 'world'

def scramble(s1, s2):
    unscrambled_word = []
    n = 0
    x = 0
    s1_list = list(s1)
    s2_list = list(s2)
    s1_letter = s1_list[n]
    s2_letter = s2_list[x]
    for letters in range(len(s2_list)):
        while n > len(s1_list):
            if s1_letter == s2_letter:
                n = n   1
                x = x   1
            else:
                n = n   1
    return 'True' if x == len(s2_list) else 'False'
 

Я пытаюсь заставить свой код анализировать каждую из двух строк. Если слово первой строки не совпадает со словом второй строки, тогда n будет 1 и перейдет ко второй букве. Если он совпадает, то и n, и x будут 1. Моя мысль о моем коде заключается в том, что если x == длина второй строки до окончания гигантского цикла, то она вернет True. В противном случае False. Проблема в цикле. Кажется, что цикл проходит только по первым двум буквам обеих строк, а затем останавливается. Я довольно новый программист, любой ввод приветствуется! Спасибо!

Комментарии:

1. Каков ваш ожидаемый доход? Вы пытаетесь вернуть True , если s1 является зашифрованной версией s2, возможно, с дополнительными буквами? Если это так, наборы кажутся элегантным решением.

2. Я тоже думал о наборах, однако наборы не будут работать. Если первое слово равно moon , а второе слово равно money , это приведет к True, что неверно. Когда вы пытаетесь увидеть, находится ли word1 в word2

3. Ваша общая идея кажется правильной. Однако у вас что-то не так в вашем цикле while, вы проверяете, n превышает ли оно длину вашего списка, и, поскольку n начинается с 0, ваш цикл while никогда не будет выполнен.

4. Вам нужно отсортировать оба слова. Затем сравните по позиции. Если он не соответствует, то сбой

5. Я даже не уверен, что такое наборы, как я уже сказал, я все еще довольно новичок. Но я думаю, что мне не нужно расшифровывать слова, если я могу заставить программу проверить, что в первой строке достаточно слов, которые соответствуют словам во второй строке, чтобы создать второе строковое слово. Надеюсь, это поможет.

Ответ №1:

Вам просто нужно убедиться, что все буквы в str2 присутствуют в str1 в достаточном количестве

 def scramble(str1,str2):
    d1 = {}
    for c in str1:
        if not c in d1:
           d1[c] = 0
        d1[c]  = 1
    for c in str2:
        if not c in d1 or d1[c] < 1:
            return False
        d1[c] -= 1
    return True
 

Идея состоит в том, чтобы просмотреть все символы в str2, и если, например, str2 содержит три буквы «a», убедитесь, что str1 содержит как минимум три буквы «a». Для этого требуется подсчитать, сколько раз каждый символ встречается в str1. Это наиболее естественно сделать со словарем. Словарь сопоставляет вещи, называемые ключами, с другими вещами, называемыми значениями. В этом случае мы сопоставляем ключи, которые являются одиночными символами, со значениями, которые являются числовыми числами.

Первый шаг — создать пустой словарь d1={} . Далее нужно перейти посимвольно в str1, который является первым циклом for . Для каждого из этих символов мы спрашиваем, был ли этот символ когда-либо ранее помещен в d1. Если этого не произошло, то мы создаем новое сопоставление внутри d1 для этого символа с начальным значением, равным нулю. Каждый раз, когда в этом цикле через str1 встречается символ, значение count, сопоставленное с этим символом в d1, увеличивается на 1. После завершения первого цикла for (который проходит через str1) словарь содержит количество каждой буквы в str1.

Следующая идея — перебрать каждый символ в str2. Если это символ, отсутствующий в d1, то это означает, что символ отсутствовал в str1, поэтому в str1 отсутствует символ, который нужно было бы скремблировать в str2. На этом этапе вы можете остановить обработку и просто вернуть False .

В противном случае, если вы сталкиваетесь только с символами, которые существуют в качестве ключей в d1, вы вычитаете единицу из отображенного значения счетчика d1 каждый раз, когда вы сталкиваетесь с этим символом во время выполнения цикла через str2. Если вычитание когда-либо приведет к тому, что значение d1 count опустится ниже нуля, то это означает, что str2 имеет большее число этого конкретного символа, чем str1, поэтому str1 снова не может скремблироваться в str2. Поэтому вы можете вернуть False в этот момент и остановить обработку.

Наконец, если мы пройдем весь 2-й цикл (через str2), не встретив ни одного из случаев возврата False, упомянутых выше, это означает, что str1 содержит по крайней мере столько же символов, сколько и str2, и поэтому может скремблироваться в str2, используя некоторые из его букв. Затем вы возвращаете True.

Комментарии:

1. я немного смущен тем, что компьютер делает в некоторых ваших коде. Не могли бы вы еще немного разбить его и объяснить, что делает ваш код? Извините, я большой новичок, лол.

2. @Jace Я добавлю больше объяснений

3. большой палец вверх для деталей. С точки зрения производительности я не вижу ничего, что могло бы превзойти ваш ответ

4. @BingWang Мне действительно понравилось, как вы используете коллекции. Ваши были элегантными.

Ответ №2:

 from collections import defaultdict
s1 = 'rkqodlw'
s2 = 'world'

def scramble(s, t):
    d=defaultdict(int)
    for c in s:
        d[c] =1
    for c in t:
        d[c]-=1
    return min(d.values())>=0
scramble(s1,s2)
 

в качестве альтернативы используйте счетчик

 from collections import Counter
s1 = 'rkqodlw'
s2 = 'world'

def scramble(s, t):
    c=Counter(s)
    c.subtract(Counter(t))
    return min(c.values())>=0
scramble(s1,s2)
 

Ответ №3:

Альтернатива:

 s1 = 'rkqodlw'
s2 = 'world'

def scramble(s1, s2):
  s1_list = list(s1)
  for char in s2:
    if char in s1_list:
      s1_list.pop(s1_list.index(char))
    else:
      return False
  return True

print(scramble(s1,s2))
 

Вот как это работает: вы выполняете цикл для каждой буквы в s2, и если эта буква также находится в версии списка s1, вы удаляете ее из этой версии списка. Таким образом, если 'rabbit' , например, s2 был, а s1 был 'braintrain' , вы встретили бы первый 'r' , 'a' , и первый 'b' , удалите его из 'braintrain' , чтобы получить 'intrain' , а следующий 'b' затем провалит тест и False будет возвращен. Если бы было достаточно 'b' s, скремблер вернулся True бы. Финал True возвращается, если тест никогда не завершается неудачно (то есть все буквы в s2 также находятся в s1), когда функция завершается.

Комментарии:

1. Вы можете использовать remove так же, как у вас уже есть char

2. Я бы не рекомендовал это. список pop равен O (N), а ваш ответ — O (N ^ 2) сложность. И Matt, и мой ответ выполняются с O (N)

Ответ №4:

Обновленная версия:

s1 = зашифрованное слово, которое может содержать s2

s2 = слово для поиска

Шаг 1. Найдите набор s2

Шаг 2. Перебирайте каждую букву набора s2. Давайте назовем каждую букву как s

Шаг 3. Для каждой буквы s узнайте, сколько раз она встречается в s1 и s2

Шаг 4: Если количество букв в s2 <= количество букв в s1, тогда ОК, иначе выйдите и верните False

Шаг 5: Если все буквы в наборе s2 соответствуют условию шага 4, то s2 находится в s1. Вы можете вернуть True

Код для этого:

 def scramble_check(s1,s2):
    return True if all(s2.count(s) <= s1.count(s) for s in set(s2)) else False

print (scramble_check('rkqodlw', 'world'))
print (scramble_check('moonshine', 'moon'))
print (scramble_check('strain', 'brain'))
print (scramble_check('aaaappppleeeset', 'apple'))
print (scramble_check('braintrain', 'rabbit'))
 

Вывод приведенного выше кода:

 True
True
False
True
False
 

Джейс, чтобы ты понял, что одна строка кода, я расширил функцию. Вот более расширенная версия.

 def scramble_check(s1,s2):
    ss = set(s2)  #create a set from word s2
    
    for s in ss: #iterate through each letter in set ss

        #compare count of occurrences of s in both s1 and s2
        #if s2 count is more than s1, then the word cannot be made with s1
        #so return False and exit the function
        if s2.count(s) > s1.count(s): return False

    #if we iterated through all of ss and each letter met the condition, then s2 can be created using s1. So return True
    return True
 

Все это одна строка:

 return True if all(s2.count(s) <= s1.count(s) for s in set(s2)) else
 

Комментарии:

1. да, это поможет — я всегда забываю, что функция str.count существует. Вероятно, вы можете просто напрямую вернуть все (…) вместо выполнения условия.