4

I have the following list:

a = [1, 2, 5, 4, 3, 6]

And I want to know how I can swap any two values at a time randomly within a list regardless of position within the list. Below are a few example outputs on what I'm thinking about:

[1, 4, 5, 2, 3, 6]
[6, 2, 3, 4, 5, 1]
[1, 6, 5, 4, 3, 2]
[1, 3, 5, 4, 2, 6]

Is there a way to do this in Python 2.7? My current code is like this:

import random
n = len(a)
if n:
    i = random.randint(0,n-1)
    j = random.randint(0,n-1)
    a[i] += a[j]
    a[j] = a[i] - a[j]
    a[i] -= a[j]

The issue with the code I currently have, however, is that it starts setting all values to zero given enough swaps and iterations, which I do not want; I want the values to stay the same in the array, but do something like 2opt and only switch around two with each swap.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Leggerless
  • 321
  • 4
  • 16
  • can't you use extra variable `temp = a[i] ; a[i] = a[j] ; a[j] = temp` ? – furas Dec 09 '17 at 00:30
  • 1
    @furas Not necessary in Python, `a[i], a[j] = a[j], a[i]` will do. – mkrieger1 Dec 09 '17 at 00:30
  • See: https://stackoverflow.com/questions/2493920/how-to-switch-position-of-two-items-in-a-python-list and https://stackoverflow.com/questions/6494508/how-do-you-pick-x-number-of-unique-numbers-from-a-list-in-python – mkrieger1 Dec 09 '17 at 00:32
  • @mkrieger1 yes I know :) version with `temp` should be more obvious for beginner so I started with `temp`. – furas Dec 09 '17 at 00:33

1 Answers1

13

You are over-complicating it, it seems. Just randomly sample two indices from the list, then swap the values at those indicies:

>>> def swap_random(seq):
...     idx = range(len(seq))
...     i1, i2 = random.sample(idx, 2)
...     seq[i1], seq[i2] = seq[i2], seq[i1]
...
>>> a
[1, 2, 5, 4, 3, 6]
>>> swap_random(a)
>>> a
[1, 2, 3, 4, 5, 6]
>>> swap_random(a)
>>> a
[1, 2, 6, 4, 5, 3]
>>> swap_random(a)
>>> a
[1, 2, 6, 5, 4, 3]
>>> swap_random(a)
>>> a
[6, 2, 1, 5, 4, 3]

Note, I used the Python swap idiom, which doesn't require an intermediate variable. It is equivalent to:

temp = seq[i1]
seq[i1] = seq[i2]
seq[i2] = temp
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172