как мне удалить элемент из списка и добавить его в конец того же списка - PullRequest
0 голосов
/ 09 мая 2020

У меня есть список из 52 кортежей (колода игральных карт), которые я пытаюсь перемешать без использования random.shuffle (не разрешено использовать его в этом проекте). я пытаюсь создать 2 случайных индекса, удалить эти элементы из списка и поместить 1 в начало и 1 в конец списка.

Я могу создать случайные #, но не знаю, как их переместить. похоже, что .pop - мой лучший метод, но не уверен, правильно это или нет.

def shuffle():
    ite = 0
    while ite <= 1000:
        rand1 = randint(0, len(card_deck) -1)
        rand2 = randint(0, len(card_deck) -1)
        card_deck.pop[rand1]
        card_deck.append(rand1)
        ite += 1
shuffle()

Ответы [ 3 ]

2 голосов
/ 09 мая 2020

Временная сложность Попа в этой ситуации не идеальна. Было бы разумнее сохранить значение в rand1 как временную переменную и заменить его значением в rand2, а затем заменить значение в rand2 временной переменной. И даже более эффективно, как указано в комментарии ниже, вы можете поменять местами два значения без временной переменной.

Если у вас есть список из 1000 элементов, например, и вы хотите вывести 500-й элемент, он будет работать за N (500) раз. В то время как вы можете получить доступ к элементу в списке в постоянное время.

Если вы делаете это как домашнее задание, постарайтесь не смотреть на мой ответ ниже, не реализовав сначала самостоятельно.

def shuffle():
    ite = 0
    while ite <= 1000:
        rand1 = randint(0, len(card_deck) - 1)
        rand2 = randint(0, len(card_deck) - 1)
        card_deck[rand1], card_deck[rand2] = card_deck[rand2], card_deck[rand1]
        ite += 1
0 голосов
/ 09 мая 2020

Я думаю, это то, что вы ищете

import random

def build_deck():
    '''
    build a fresh sorted deck of cards
    '''
    nums = range(1,14)
    types = ['Heart','Spade','Club','Diamond']
    deck = [(x,y) for x in types for y in nums]
    return deck


def get_random_indices(from_=1,to=50):
    '''
    get 2 random indices to choose from which are not similar
    '''
    index1 = random.randint(from_,to)
    index2 = random.randint(from_,to)
    if index1 == index2:
        index1,index2 = get_random_indices(from_,to)
    return index1,index2


def shuffle_deck(deck,n_times=52):
    '''
    shuffle deck n times
    '''
    if n_times>0:
        index1,index2 = get_random_indices()
        card1 = deck.pop(index1)
        card2 = deck.pop(index2)
        deck.append(card1)
        deck.insert(0,card2)
        n_times-=1
        shuffle_deck(deck,n_times=n_times)
    return deck

deck = build_deck()
new_deck = shuffle_deck(deck,52)
new_deck

Вы можете добавить дополнительную случайность, выбрав, следует ли вставлять card1 или добавлять, используя random.choice()

0 голосов
/ 09 мая 2020

Как отмечает @Sean Payne; pop() - это не путь к go. pop() ужасно медленный, когда все, что вам нужно сделать, это поменять местами значения. Python разрешает (поощряет) присваивание кортежей, поэтому можно менять местами значения без использования временного хранилища x, y = y, x, или в данном случае deck[i], deck[j] = deck[j], deck[i].

A for l oop больше pythoni c, чем while l oop.

Я предполагаю, что ваш инструктор пытается заставить вас написать правильный тасование Кнута ( ссылка ), также называемое Фишером -Йетс, или Фишер-Йетс-Кнут. Дюрстенфельд внес еще один важный вклад в разработку алгоритма.

import random

def shuffle(deck):
    for i in range(len(deck)-1, 0, -1):
        j = random.randint(0,i)
        deck[i], deck[j] = deck[j], deck[i]
    return deck

mydeck = list(range(52))
print(mydeck)
print(shuffle(mydeck))

Попробуйте онлайн!

Следует отметить большое различие в том, что как только вы выбираете, какой элемент идет до конца списка, с которым вы работаете, оставьте его там. Если вы продолжите генерировать числа, которые позволяют перетасовать ваши уже перемешанные элементы, это фактически снижает случайность перемешивания. Майк Босток и Джефф Этвуд оба имеют очень хорошее объяснение этой проблемы.

Если вы действительно хотите перетасовать и перед, и в назад, вы можете сделать что-то вроде

import random

def shuffle2(deck):
    back_of_deck = len(deck) - 1
    for i in range(len(deck)//2):
        front = random.randint(i,back_of_deck)
        back = random.randint(i,back_of_deck)
        deck[i], deck[front] = deck[front], deck[i]
        deck[back_of_deck], deck[back] = deck[back], deck[back_of_deck]
        back_of_deck -= 1
    return deck

mydeck = list(range(52))
print(mydeck)
print(shuffle2(mydeck))

Попробуйте онлайн!

...