I can not figure out the puzzle.

Create a program that will display a list of words in a random order. All words from the presented list should be printed without repetition on the screen.

Here is my code:

spisok = ["Alex", "Kate", "Love", "World", "Peace", "Putin",] empty_list = [] count = len(spisok) schetchik = 0 while count != schetchik: for item in spisok: randitem = random.choice(spisok) schetchik += 1 if randitem not in spisok: empty_list += randitem else: break print(empty_list) 

Screenshot of the execution result:

alt text

Displays an empty list.

10 answers 10

Once such a booze has gone, here is my option:

 import random spisok = ["Love", "World", "Peace", "Putin",] random.shuffle(spisok) print spisok 

To derive unique words from the list in a random order, using different pseudo-random number generators:

 #!/usr/bin/env python import random words = ["Alex", "Kate", "Love", "World", "Peace", "Putin",] unique_words = list(set(words)) random.shuffle(unique_words) # shuffle using default Mersenne Twister generator random.SystemRandom().shuffle(unique_words) # OS-provided generator print("\n".join(unique_words)) 
     import random spisok = ["Love", "World", "Peace", "Putin",] while spisok: print spisok.pop(random.randint(0, len(spisok)-1)) 
    • I wrote about shuffle above, then you would have at least brought this decision. It would only be worthwhile to clarify that these examples change the original list (your method clears it altogether). But the answer is higher memory, but it requires more. It would be better to give an example so that the source list does not change, and the memory is barely eaten)) - BOPOH

    I would do it like this:

      import random spisok = ["Alex", "Kate", "Love", "World", "Peace", "Putin",] empty_list = [] while len(empty_list) != len(spisok): randitem = random.choice(spisok) if randitem not in empty_list: empty_list.append(randitem) print(empty_list) 

    Update

    But this option is not suitable for long lists. But @RAVON would do this:

     import random spisok = ... empty_list = [] for item in spisok: rand_index = random.randint(0, len(empty_list) empty_list.insert(rand_index), item) 

    and this option is much better.

    • And I would use shuffle/random.shuffle . And then - there will be a million entries in the list and how long will I have to wait for the sizes of the lists to equal? If you do it yourself, then delete it from the spisok . Then the check for presence in empty_list will not be needed. - BOPOH
    • I tried to fix the current solution, not create a new one. - abalckin
    • 2
      Well, it was possible to point out a mistake in logic in the comments. That's why I did not make my comment a response. For the answer, there would not be enough analysis of examples with possible options. And in the current form, you are not so much “correcting” the decision, as you have masked the error (the one that will be executed for a long time). The author’s version should be corrected somehow like this: import random spisok = ... empty_list = [] for item in spisok: rand_index = random.randint (0, len (empty_list) empty_list.insert (rand_index), item) Then the fill rate is even million words would be acceptable. - BOPOH
    • Yes, your option is much better. - abalckin

    @BOPOH ,

    so that the original list does not change, and the memory is almost not eaten))

    Challange accepted

     import random def iter_shuffled(l): indices = list(range(len(l))) random.shuffle(indices) for i in indices: yield l[i] spisok = ["Love", "World", "Peace", "Putin",] for item in iter_shuffled(spisok): print (item) 

    UPDATE Since when copying the list of elements of the new list will be links to the original values, then you can do without the list of indices:

     import random def iter_shuffled(l): new_list = list(l) random.shuffle(new_list) for item in new_list: yield item 

    But then the sense of formatting the code as an iterator function is almost lost and the code can be reduced to the following lines:

     import random spisok = ["Love", "World", "Peace", "Putin",] new_list = list(spisok) random.shuffle(new_list) print new_list 
    • And what indices = list(range(len(l))) better is another_list = list(spisok) and the subsequent shuffle on it? Just the fact that instead of strings of a number? Well, the original array could be numeric. - BOPOH
    • @BOPOH, you can and list (spisok), still it will be inside the links to the source lines. But it would not be so interesting :) - insolor

    so that the original list does not change, and the memory is almost not eaten))

     from random import shuffle lst = [ "Alex", "Kate", "Love", "World", "Peace", "Freddie Mercury" ] idx = list(range(len(lst))) shuffle(idx) while idx: print(lst[idx.pop()]) 
    • Well, the memory consumes 2N here, if not the bytes are counted, but the number of elements, because the original array could be numeric. There is an option through recursion, but I do not know how much memory this solution will take. Maybe the overhead will be large, and the limit of recursion can be quickly reached. Yes, and the solution is not entirely clear - the original list still changes when working, but then returns to the original one. There is another option with recursion, but it is "very, very pseudo-random." There, recursion is also used, but its depth is just log N. Another “very pseudo-random” option is still ripening) - BOPOH
    • What about bit vectors in Python? If yes, then everything is solved with additional memory of N bits in N cycles of obtaining a random number. Similar to resolving collisions when hashing with open addressing. - avp
    • Well, just play "Much Ado About Nothing." Author V.I. Hespeare :) But I learned a lot of new things. - abalckin

    I corrected the code:

     import random spisok = ["Alex", "Kate", "Love", "World", "Peace", "Putin",] empty_list = [] count = len(spisok) schetchik = 0 while count != schetchik: for item in spisok: item = random.choice(spisok) empty_list.append(item) schetchik += 1 print(empty_list) 

      The code from Artyom’s answer does not fulfill the original condition of the problem: " ... display a list of words in a random order. All words from the presented list should be printed on the screen without repetitions ... because repetitions from the list should be printed - there is no check for already selected items . Slightly correct:

       import random spisok = ["Alex", "Kate", "Love", "World", "Peace", "Putin",] empty_list = list() count = len(spisok) schetchik = 0 while count != schetchik: for i in spisok: item = random.choice(spisok) if item in empty_list: print("Есть такие данные в новом списке!") else: empty_list.append(item) schetchik += 1 print(empty_list) # можно оставить вывод в for - увидим все попытки поиска, либо вывести из цикла. 

      As the authors have already noted in the comments, there is a more concise and practical option with creating a slice of the original list:

       import random spisok_slov = ["кот", "кот", "код", "код", "ток", "ток", "ток", "ток", "тук-тук", "мак", "крот", "плот", "кнут"] final_no_repeat_list = list(set(spisok_slov[:])) random.shuffle(final_no_repeat_list) print(final_no_repeat_list) 

        You can even like this:

         >>> import random >>> array = ["Alex", "Kate", "Love", "World", "Peace", "Putin"] >>> print(*random.sample(set(array), len(set(array))), sep='\n') 
           import random inp = ["Alex", "Kate", "Love", "World", "Peace", "Putin"] l = list(set(inp)) random.shuffle(l) print (l) 
          • Will the output be in random order without repetitions? - 0xdb
          • It does not guarantee random order. Try PYTHONHASHSEED=0 environment variable. Therefore, I removed this option from later versions of the original version of my answer - jfs
          • @jfs, I would understand the question as "in any order", and not that it is necessary to mix everything in random. - Qwertiy