2

I am creating an conditioning experiment with three conditions (0,1,2) and need to pseudo-randomize condition order. I need a randomize list with each condition occurring only 2 times in a row. Here how I tried to achieve it. The code is running but it takes an eternity...

Any ideas why this code is not working well and any different approaches to solve the problem?

#create a list with 36 values
types  = [0] * 4 + [1] * 18 + [2]*14 #0=CS+ ohne Verstärkung; 1 = CS-, 2=CS+     mit shock

#random.shuffle(types)

while '1,1,1' or '2,2,2' or '0,0,0' in types:
    random.shuffle(types)
else: print(types)

Thank you in advance! Martina

2 Answers2

1
while '1,1,1' or '2,2,2' or '0,0,0' in types:
    random.shuffle(types)

evaluates as:

while True or True or '0,0,0' in types:
    random.shuffle(types)

and short-circuits at while True

Instead, use: any() which returns True if any of the inner terms are True

Additionally, your types is numbers and you're comparing it to strings:

>>> types
[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

so you need to map those numbers to a string which can be compared:

>>> ','.join(map(str, types))
'0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2'

Try:

while any(run in ','.join(map(str, types)) for run in ['0,0,0', '1,1,1', '2,2,2']):
    random.shuffle(types)

>>> types
[1, 2, 1, 2, 1, 2, 1, 1, 0, 2, 0, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 0, 2, 1, 1, 0, 2, 1, 1, 2, 2, 1, 1]
TemporalWolf
  • 7,727
  • 1
  • 30
  • 50
  • Thanks! That is a great solution as well! As a total python beginner, I do not really understand what's the map-function is doing. Does it apply "str" to every element in the list types? So is it iterating over all items or does a map function works differently? – Martina Takeaway Mar 25 '17 at 11:56
  • @MartinaTakeaway Yes, [map()](https://docs.python.org/2/library/functions.html#map) applies the given function to every item in the supplied iterator. – TemporalWolf Mar 25 '17 at 17:35
1

Your loop has several problems. First while '1,1,1' or '2,2,2' or '0,0,0' in types: is the same as while ('1,1,1') or ('2,2,2') or ('0,0,0' in types):. Non-zero strings are always True so your condition is always true and the while never stops. Even if it did, types is a list of integers. '0,0,0' is a string and is not an element of the list.

itertools.groupby is a good tool to solve this problem. Its an iterator that is designed to group a sequence into subiterators. You can use it to see if any clusters of numbers are too long.

import random
import itertools

#create a list with 36 values
types  = [0] * 4 + [1] * 18 + [2]*14 #
print(types)

while True:
    random.shuffle(types)
    # try to find spans that are too long
    for key, subiter in itertools.groupby(types):
        if len(list(subiter)) >= 3:
            break # found one, staty in while 
    else:
        break # found none, leave while

print(types)
tdelaney
  • 73,364
  • 6
  • 83
  • 116