0

I am implementing a shuffling algorithm and I need to check how many times I have ti run the algorithm to get the original array. I have tried implementing a while loop and initiating a counter but there is some problem with the scope. The arrays arr and arr2 have equal values. Can someone help?

from random import randint, random
from math import floor


def shuffle(the_list):
    amnt_to_shuffle = len(the_list)
    while amnt_to_shuffle > 1:
        i = int(floor(random() * amnt_to_shuffle))
        amnt_to_shuffle -= 1
        the_list[i], the_list[amnt_to_shuffle] = the_list[amnt_to_shuffle], the_list[i]
    return the_list

arr = [i for i in range(1,11)]
original_arr = arr
k = 0

while 1:
    arr2 = shuffle(arr)
    if arr2 == original_arr:
        break
    else:
        shuffle(arr)
        k += 1

print(k)
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • Do these answer your question? [How do I clone a list so that it doesn't change unexpectedly after assignment?](https://stackoverflow.com/questions/2612802/how-do-i-clone-a-list-so-that-it-doesnt-change-unexpectedly-after-assignment) and [Why can a function modify some arguments as perceived by the caller, but not others?](https://stackoverflow.com/questions/575196/why-can-a-function-modify-some-arguments-as-perceived-by-the-caller-but-not-oth) – wjandrea Apr 29 '22 at 21:14
  • To be clear, this problem has nothing to do with scope. – wjandrea Apr 29 '22 at 21:15

2 Answers2

1

Your code has only one list. arr, original_arr, arr2, ... they are all the same list. Your shuffle function mutates the list it gets as argument. Even though that function returns the list, this is the caller's list that it passed as argument, so it is that list that is shuffled.

It would be more pythonic to not return the list in this shuffle function, so to make absolutely clear to the caller that their list is mutated (shuffled) by it. This also means you don't need arr2.

Unrelated, but your loop should just have one call to shuffle, not two.

The key is to make original_arr a new list that is a copy of arr. You can do this in several ways, e.g. by slice syntax:

original_arr = arr[:]
k = 0

while 1:
    shuffle(arr)
    if arr == original_arr:
        break
    k += 1
trincot
  • 317,000
  • 35
  • 244
  • 286
0

By writing original_arr = arr you copy the pointer of arr to original_arr hence any change in any one of them will effect the other.

You can import copy.deepcopy to deep copy the list or to use original_arr = arr[:]

wjandrea
  • 28,235
  • 9
  • 60
  • 81
tnuva
  • 35
  • 5