2015-11-27 14 views
7

Sono nuovo di Python e ho qualche problema con la creazione di elenchi casuali.Elenco casuale Python

Sto usando random.sample(range(x, x), y).

voglio ottenere 4 liste con numeri unici, 1-4, quindi ho utilizzato questo

a = random.sample(range(1, 5), 4) 
b = random.sample(range(1, 5), 4) 
c = random.sample(range(1, 5), 4) 
d = random.sample(range(1, 5), 4) 

in modo da ottenere, per esempio

a = 1, 3, 2, 4 
b = 1, 4, 3, 2 
c = 2, 3, 1, 4 
d = 4, 2, 3, 1 

Come posso fare in modo che la colonna è anche unica?

+0

sì, ma solo i numeri 1- 4 :) – PythonUserNew

+0

Stai cercando di generare un quadrato latino casuale? –

+0

@ John Coleman, sì, ho bisogno di generare un quadrato latino – PythonUserNew

risposta

1

Probabilmente il modo più semplice è quello di creare una matrice valida, e poi rimescola le righe, e poi rimescola le colonne:

import random 

def random_square(U): 
    U = list(U) 
    rows = [U[i:] + U[:i] for i in range(len(U))] 
    random.shuffle(rows) 
    rows_t = [list(i) for i in zip(*rows)] 
    random.shuffle(rows_t) 
    return rows_t 

Usage:

>>> random_square(range(1, 1+4)) 
[[2, 3, 4, 1], [4, 1, 2, 3], [3, 4, 1, 2], [1, 2, 3, 4]] 

Questo dovrebbe essere in grado di creare qualsiasi matrice valida con uguale probabilità. Dopo aver fatto qualche lettura sembra che questo abbia ancora pregiudizi, anche se non ne comprendo pienamente il motivo.

1

Creare un elenco di tutti gli elementi e, come riempire la riga, rimuovere l'elemento utilizzato.

import random 

def fill_line(length): 
    my_list = list(range(length)) 

    to_return = [] 

    for i in range(length): 
     x = random.choice(my_list) 

     to_return.append(x) 
     my_list.remove(x) 

    return to_return 

x = [fill_line(4) 
    for i in range(4)] 

print(x) 
3

Assente una chiara teoria matematica, diffido qualcosa di diverso da un approccio un po 'hit-and-miss. In particolare, tornando indietro approcci può introdurre una sottile distorsione:

from random import shuffle 

def isLatin(square): 
    #assumes that square is an nxn list 
    #where each row is a permutation of 1..n 
    n = len(square[0]) 
    return all(len(set(col)) == n for col in zip(*square)) 

def randSquare(n): 
    row = [i for i in range(1,1+n)] 
    square = [] 
    for i in range(n): 
     shuffle(row) 
     square.append(row[:]) 
    return square 

def randLatin(n): 
    #uses a hit and miss approach 
    while True: 
     square = randSquare(n) 
     if isLatin(square): return square 

uscita tipica:

>>> s = randLatin(4) 
>>> for r in s: print(r) 

[4, 1, 3, 2] 
[2, 3, 4, 1] 
[1, 4, 2, 3] 
[3, 2, 1, 4] 
+0

grazie mille ragazzi, sto per sperimentare e provarlo: D – PythonUserNew

+0

Questo metodo è completamente privo di pregiudizi, ma questo è un metodo __molto inefficiente tuttavia come N cresce. Per l'ultima fila ci sono N! permutazioni, ma solo 1 è fattibile. Questo mette il tempo di esecuzione almeno a O (N!). A seconda del numero di bit che il generatore di numeri casuali Python ha internamente, potrebbe non terminare mai per il grande N. – orlp

2

tutto casuale allora:

def gen_matrix(): 
    first_row = random.sample(range(1, 5), 4) 
    tmp = first_row + first_row 
    rows = [] 
    for i in range(4): 
     rows.append(tmp[i:i+4]) 
    return random.sample(rows, 4) 
+0

Probabilmente la migliore risposta per questo. Breve concisa e funziona. E qui stavo facendo funzioni troppo complesse per fare questo. Nice +1 –

+0

Questo è effettivamente identico alla mia risposta, ad eccezione del codice diverso. – orlp

0

Vorrei costruire un quadrato latino casuale per 1) inizio con una sola permutazione casuale, 2) popolare le righe con le rotazioni 3) mescola le righe 4) traspone il quadrato 5) rimischia le righe ancora:

from collections import deque 
from random import shuffle 

def random_latin_square(elements): 
    elements = list(elements) 
    shuffle(elements) 
    square = [] 
    for i in range(len(elements)): 
     square.append(list(elements)) 
     elements = elements[1:] + [elements[0]] 
    shuffle(square) 
    square[:] = zip(*square) 
    shuffle(square) 
    return square 

if __name__ == '__main__': 
    from pprint import pprint 
    square = random_latin_square('ABCD') 
    pprint(square)