2013-05-20 19 views
5

Cho một xâu có độ dài n, thế nào tôi sẽ (giả) lấy mẫu ngẫu nhiên m chuỗi con của kích thước k như vậy mà không ai trong số các chuỗi con được lấy mẫu chồng chéo? Hầu hết các kinh nghiệm kịch bản của tôi là trong Perl, nhưng một giải pháp dễ chạy trong bất kỳ ngôn ngữ chung nào cũng đủ.lấy mẫu ngẫu nhiên của chuỗi con không chồng chéo có độ dài k

+0

Chia chuỗi thành các mẫu có chiều dài mong muốn; có thể bằng cách điền vào mảng, và sau đó 'my $ rnd = $ array [int rand @array]' –

+0

Tôi nghĩ rằng tôi sẽ tiếp cận nó bằng cách xem xét rằng có các ký tự 'nm * k' mà _will not_ được sử dụng, và' m + 1 'khoảng trống mà họ có thể đi. Chọn độ dài của những khoảng trống 'm + 1' đó để chúng thêm chính xác' n-m * k'. (Bằng cách này, bạn không cần phải xem xét chồng chéo.) – cjm

+0

Tôi giả định các chất nền cần phải được tiếp giáp (nếu không nó sẽ rất dễ dàng để làm với một iterator)? –

Trả lời

2

Nếu có một ký tự không thể xảy ra trong đầu vào, ví dụ: X, chỉ:

my $size = 20; 
my $count = 20; 
my $mark = 'X'; 
my $input = 'CCACGCATTTTTGTTCATTGTTCTGGCTTCTTACAAGGTTCAGTAGACTTTGTAACACAGTTGTGTCTCTCACAGATTGGCAGATGTTTGGTAAAGGATTGACTTTTCAGCCAACTCATGGGAAAGTGAAATAATGTAAAAAACAGGAAGAATACAGTTTTAGGCCTTTCAAGTGAGGCATGGCTTTCAGCTCTTGGCAAGAACAGGCAAGGAGATGCAAGTTTTAGGACTCTAAGAGGCTAGGCTTTTCAAAGTGCTTCTCTCCCCTTCACCCTCCTTCAGTTACAGCACCAAGCACCACCGAGGTGTTACCTGCAGCCTCACTCTCTACCTGGTTGTGGGATCCTGCCACTTCCTTAACCCACACTGAGTTCCTTGTGGTTCACAGGGTCACACAGAGGGCTGTAGAGATACAAAAGATATATGTGATTTTATATCACCTATCATATGAAGATATATTTATAAAATAGGAAACATATTAACCACTTATCATTTTATATATTTATGGTTTTATGTGTCAAAAATATATTGTTTCATGTATGTATTAAAGGATAAGTATGTATAAGAGGTTTTATAGATGTGTAAAATTATATATTTATACGTATCTTTACAAATTTAAGAATAAAGGAAGGAAAATTCTCAAAGAGGAATTCAGATATCAAGCAGTGCCCTTTGACCAAGAGCCTTGGTTACAACATACCTACAAAAGTGAACTATCATTGAAAGACCTATGGACACTGGATTTCTCTTTCCTTATTTAGAAGGGCAGTCTGTGTCTTGGAAAAGCATACAGTTTGTTGTATCTTGCTGGACAACAGGAGTCA'; 

if (2*$size*$count-$size-$count >= length($input)) { 
    die "selection may not complete; choose a shorter length or fewer substrings, or provide a longer input string\n"; 
} 

my @substrings; 
while (@substrings < $count) { 
    my $pos = int rand(length($input)-$size+1); 
    push @substrings, substr($input, $pos, $size, $mark x $size) 
     if substr($input, $pos, $size) !~ /\Q$mark/; 
} 
+0

Câu trả lời rất rõ ràng và đơn giản. Tuy nhiên, một câu hỏi, mục đích của '\ Q' trong cụm từ thông dụng là gì? –

+0

Dường như nó có phân phối khá không thiên vị: http://i.imgur.com/EPLexRr.png. –

+0

trong trường hợp bạn đặt $ mark thành một cái gì đó như '|'. có, điều này sẽ không thiên vị (nhưng không từ chối thậm chí cố gắng nếu bạn sẽ mất nhiều hơn một nửa chuỗi) – ysth

2

Đây là phương pháp đệ quy trong Python. Tại mỗi bước, chọn ngẫu nhiên trong số các phân vùng còn lại của chuỗi, sau đó chọn ngẫu nhiên chuỗi con có độ dài k từ phân vùng đã chọn. Thay thế phân vùng này bằng cách chia phân vùng trên chuỗi con được chọn. Lọc ra các phân vùng có độ dài nhỏ hơn k và lặp lại. Danh sách các giá trị trả về khi có m, hoặc không có phân vùng nào có chiều dài lớn hơn hoặc bằng k.

import random 

def f(l, k, m, result=[]): 
    if len(result) == m or len(l) == 0: 
     return result 
    else: 
     if isinstance(l, str): 
      l = [l] 
     part_num = random.randint(0, len(l)-1) 
     partition = l[part_num] 
     start = random.randint(0, len(partition)-k) 
     result.append(partition[start:start+k]) 
     l.remove(partition) 
     l.extend([partition[:start], partition[start+k:]]) 
     return f([part for part in l if len(part) >= k], k, m, result)