2015-11-27 12 views
7

Jestem nowicjuszem w Pythonie i mam pewne problemy z tworzeniem losowych list.Losowa lista Pythona

Używam random.sample(range(x, x), y).

Chcę dostać 4 list z unikalnymi numerami od 1-4, więc używam tego

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) 

więc mogę na przykład

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

Jak mogę zrobić to, że kolumna jest również wyjątkowa?

+0

tak, ale tylko cyfry 1- 4 :) – PythonUserNew

+0

Czy próbujesz wygenerować losowy łaciński kwadrat? –

+0

@ John Coleman, tak, potrzebuję wygenerować łaciński kwadrat – PythonUserNew

Odpowiedz

1

Prawdopodobnie Najprostszym sposobem jest stworzenie ważnego macierzy, a następnie losowo wiersze, a następnie shuffle kolumny:

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 

Zastosowanie:

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

ta powinna być w stanie stworzyć dowolna poprawna macierz z równym prawdopodobieństwem. Po pewnym lekturze wydaje się, że to nadal ma stronniczość, chociaż nie rozumiem jeszcze do końca dlaczego.

1

Utwórz listę wszystkich elementów i, podobnie jak wypełnienie linii, usuń użyty element.

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

Bez wyraźnej teorii matematycznej nie ufam niczemu poza podejściem, w którym coś jest nie tak. W szczególności backtracking podejścia mogą wprowadzać subtelne nastawienie:

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 

Typowe wyjście:

>>> 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

dziękuję bardzo chłopaki, będę eksperymentować i wypróbować to: D – PythonUserNew

+0

Ta metoda jest całkowicie bez uprzedzeń, ale jest to metoda nieefektywna _ jakkolwiek nieskuteczna jak N rośnie. W ostatnim rzędzie jest N! permutacji, ale tylko 1 jest wykonalne. Stawia to środowisko wykonawcze co najmniej w O (N!). W zależności od liczby bitów, które generator liczb losowych Python ma wewnętrznie, może nigdy nie kończyć się dla dużego numeru. – orlp

2

całkowicie losowy następnie:

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

Prawdopodobnie najlepsza odpowiedź na to. Krótki zwięzły i działa. I tutaj robiłem zbyt skomplikowane funkcje, aby to zrobić. Nice +1 –

+0

To jest faktycznie identyczna z moją odpowiedzią, z wyjątkiem kodowanych inaczej. – orlp

0

Chciałbym zbudować losową kwadratu łacińskiego przez 1) początkowy z jedną losową permutacją, 2) zapełnij rzędy obrotami 3) przetasuj rzędy 4) przetrząśnij kwadrat 5) ponownie przetasuj rzędy:

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)