Как проверить, назначено ли значение ключу и наоборот в dict в Python - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь диктовать в python назначение каждой буквы (от A до Z) другой (или себе) случайным образом.
Например: A: S B: C C: B D: D ... S: A ... Y: Z Z: Y .

Мой код:

import random
tblconex = {}
alphabet = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E", 6: "F", 7: "G", 8: "H", 9: "I", 10: "J", 11: "K", 12: "L", 13: "M", 14: "N", 15: "O", 16: "P", 17: "Q", 18: "R", 19: "S", 20: "T", 21: "U", 22: "V", 23: "W", 24: "X", 25: "Y", 26: "Z"}
while n < 27:
    var = alphabet[random.randint(1, 26)] #We randomly choose a letter
    if var in tblconex or alphabet[n] in tblconex: #We test if she is not already assign to an other
        n += 1
    else:
        tblconex.update({alphabet[n]: var}) #We assign it
        tblconex.update({var: alphabet[n]}) 
    n += 1
z=1
while z<len(tblconex)+1: #We print our letters
    print("    ", alphabet[z], " : ", tblconex[alphabet[z]])
    z += 1

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

Извините за мой плохой английский, я француз;)

Спасибо!

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Основная проблема заключается в том, что вы увеличиваете n, даже если вы уже добавили элемент в словарь. Поэтому, если вы уже добавили элемент, он все равно считается как один. Если он был добавлен , а не , он считается как два, но, таким образом, возможны случаи, когда

В любом случае, нет никаких причин делать это, мы можем сначала создать случайную строку, перетасовывая символы, а затем «сшить» их вместе, например:

Основная проблема заключается в том, что вы увеличиваете n, даже если вы уже добавили элемент в словарь. Поэтому, если вы уже добавили элемент, он все равно считается как один. Если он был добавлен , а не , он считается как два, но, таким образом, возможны случаи, когда

В любом случае, нет никаких причин делать это, мы можем сначала создать случайную строку, перетасовывая символы, а затем «сшить» их вместе, например:

from string import ascii_uppercase
from random import shuffle

dt = list(ascii_uppercase)
shuffle(dt)
dt = iter(dt)

result = {k: v for a, b in zip(dt, dt) for k, v in ((a,b), (b, a))}

Или, если персонаж может «спариться» вместе с самим собой, мы можем реализовать его следующим образом:

from string import ascii_uppercase
from random import shuffle, randint

dt = list(ascii_uppercase)
shuffle(dt)

result = {}
i = 0
while i < len(dt):
    d = randint(0,len(dt)-i-1 > 0)
    k = dt[i]
    v = dt[i+d]
    result.update({k: v, v: k})
    i += 1 + d

assert len(result) == len(ascii_uppercase)
assert len(set(result.values())) == len(ascii_uppercase)

Оба алгоритма работают в линейном времени, поскольку они делают один проход по списку случайных символов и каждый раз связывают предыдущий со следующим символом (или текущий символ с самим собой).

0 голосов
/ 29 августа 2018

Вы можете использовать random.choice для выбора из алфавита и удаления 1 буквы каждый раз:

import random
import string

letters = string.ascii_uppercase
values = dict.fromkeys(letters)
for letter in values:
    choose = random.choice(letters)
    if choose in values.values():
        continue
        # see note **
    letters.remove(choose)
    values[letter] = choose

for k, v in values.items():
    values[v] = k

** проверяет, был ли выбор уже назначен, если это так, пропустите клавишу и продолжайте. Это обеспечит отображение A на B и B на A. В конце я добавлю пропущенные пары обратно, но с заменой ключа / значения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...