如何在Python中进行随机但部分的随机播放?

384*_*X21 6 python string random shuffle

而不是一个完整的shuffle,我在python中寻找一个部分 shuffle功能.

示例: "string"必须产生"stnrig",但不能产生"nrsgit"

如果我可以定义必须重新排列的特定"百分比"字符会更好.

目的是测试字符串比较算法.我想确定"shuffle的百分比",超过这个百分比,(my)算法将两个(混乱)字符串标记为完全不同.

更新:

这是我的代码.欢迎改进!

import random

percent_to_shuffle = int(raw_input("Give the percent value to shuffle : "))
to_shuffle = list(raw_input("Give the string to be shuffled : "))

num_of_chars_to_shuffle = int((len(to_shuffle)*percent_to_shuffle)/100)

for i in range(0,num_of_chars_to_shuffle):
    x=random.randint(0,(len(to_shuffle)-1))
    y=random.randint(0,(len(to_shuffle)-1))
    z=to_shuffle[x]
    to_shuffle[x]=to_shuffle[y]
    to_shuffle[y]=z

print ''.join(to_shuffle)
Run Code Online (Sandbox Code Playgroud)

for*_*ran 3

您的问题很棘手,因为需要考虑一些边缘情况:

  • 具有重复字符的字符串(即如何打乱“aaaab”的顺序?)
  • 如何测量链式字符交换或重新排列块?

无论如何,定义为将字符串打乱到一定百分比的指标可能与您在算法中使用的用于查看它们有多接近的指标相同。

我的随机n字符代码:

import random
def shuffle_n(s, n):
  idx = range(len(s))
  random.shuffle(idx)
  idx = idx[:n]
  mapping = dict((idx[i], idx[i-1]) for i in range(n))
  return ''.join(s[mapping.get(x,x)] for x in range(len(s)))
Run Code Online (Sandbox Code Playgroud)

基本上随机选择n要交换的位置,然后将每个位置与列表中的下一个交换...这样可以确保不会生成反向交换并且精确地n交换字符(如果有重复的字符,则运气不好)。

解释以 'string', 3 作为输入运行:

idx is [0, 1, 2, 3, 4, 5]
we shuffle it, now it is [5, 3, 1, 4, 0, 2]
we take just the first 3 elements, now it is [5, 3, 1]
those are the characters that we are going to swap
s t r i n g
  ^   ^   ^
t (1) will be i (3)
i (3) will be g (5)
g (5) will be t (1)
the rest will remain unchanged
so we get 'sirgnt'
Run Code Online (Sandbox Code Playgroud)

此方法的缺点是它不会生成所有可能的变化,例如,它无法从“string”生成“gnrits”。这可以通过对索引分区进行洗牌来解决,如下所示:

import random

def randparts(l):
    n = len(l)
    s = random.randint(0, n-1) + 1
    if s >= 2 and n - s >= 2: # the split makes two valid parts
        yield l[:s]
        for p in randparts(l[s:]):
            yield p
    else: # the split would make a single cycle
        yield l

def shuffle_n(s, n):
    idx = range(len(s))
    random.shuffle(idx)
    mapping = dict((x[i], x[i-1])
        for i in range(len(x))
        for x in randparts(idx[:n]))
    return ''.join(s[mapping.get(x,x)] for x in range(len(s)))
Run Code Online (Sandbox Code Playgroud)