Условие генерации строки

Есть код, который генерирует последовательность символов. Но в нем должно быть условие, что буквы не могут идти больше 4-х раз подряд (т.е может быть строчка 'aaa', но не должно быть 'aaaa'). Сама программа реализована на Python, код прикладываю ниже. Реализация происходит при помощи модуля random.

import random

text = 'abcdef'
num = '1234567890'

qua = 10

sym = []
sym.extend(list(text))
sym.extend(list(num))

random.shuffle(sym)
key = []

for yx in range(qua):
    key.append(''.join([random.choice(sym) for x in range(32)]))

file = open('Password.txt', 'w')
file.write('\n'.join(key))
file.close()

print('\n'.join(key))
print('\n')

Что следует добавить в код, чтобы вывод был с условием?


Ответы (2 шт):

Автор решения: CameL

Очевидно, что добавить счетчик количества одинаковых элементов. Обратите внимание, что первый элемент мы добавляем в список до цикла, чтобы нам было с чем сравнивать последующие

import random

text = 'ab'
num = '12'

qua = 10

sym = []
sym.extend(list(text))
sym.extend(list(num))

random.shuffle(sym)
key = []

counter = 1  # Добавляем счетчик
key.append(''.join([random.choice(sym) for x in range(32)]))
for yx in range(qua):
    sumbol = [random.choice(sym) for x in range(32)] # Генерируем символ
    if sumbol == key[-1] and counter <3: # Если символ повторяется, и счетчик меньше трех, то добавляем увеличивая счетчик
        counter += 1
        key.append(''.join(sumbol))
    elif sumbol != key[-1]: # Если символ другой, то обнуляем счетчик
        counter = 1
        key.append(''.join(sumbol))
    else: # Иначе генерируем символы до тех пор, пока, не сгенерируется символ отличающийся от последних трех
        while sumbol == key[-1]:
            sumbol = [random.choice(sym) for x in range(32)]
        key.append(''.join(sumbol))
        counter = 1

print('\n'.join(key))
print('\n')
→ Ссылка
Автор решения: SergFSM

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

from random import choices
from itertools import groupby

k = []
for i in range(10):
    while True:
        p = ''.join(choices('abcd1234567890', k=32))
        if max(len(list(g)) for _,g in groupby(p))<4:
            k.append(p)
            break
>>> k
'''
['6c3097a070db48a03524d471d19ab946',
 '7653c7d043805bd945824c3c33729c1c',
 '683cda6b1527511b033b5239d756d4dd',
 '4b9503428d597d4a41c4da63bd7cc114',
 '83258d224d43d5623b0bbcad15b80621',
 '3441029358676405055cdb602abddd23',
 '28336b1d19dd5c3c579b7206da505b4b',
 '04ab80660654971a9886a69c8aa30a5c',
 'a638b626568cb5d709a26695916c5b99',
 '6bca4796218b49392a889668b8c5302c']

UPD

проверил скорость, этот вариант работает немного быстрее чем если проверять каждый символ отдельно: 341 µs ± 2.71 µs против 447 µs ± 3.06 µs

вариант с регуляркой работает еще быстрее (188 µs ± 2.23 µs):

from random import choices
from re import search

k = []
for i in range(10):
    while True:
        p = ''.join(choices('abcd1234567890', k=32))
        if not search(r'(\w)\1\1\1', p):
            k.append(p)
            break
→ Ссылка