伪随机算法

时间:2018-08-13 13:53:45

标签: algorithm random sequence

我想在序列上创建一个伪随机算法。 该序列如下所示:

A B C D E F A B C D E F A B C D E F A B C D E F...

该算法的目的是创建这些字母的较短随机序列,规则为:

  • 彼此之间不得有2个相同的字母(例如A A B C D)。这很容易,麻烦就来了。
  • 双元组只能重复两次(例如A B A B A C B D可以,但A B C D A B A B不能);
  • tryad绝不能重复(例如A B C D A B C不好)。

我并不是真的很擅长算法,并且我已经尝试使这一功能工作很长时间了,但是并没有成功,所以希望您能对我有所帮助!

1 个答案:

答案 0 :(得分:2)

您可以使用回溯算法,跟踪前两个字符以及到目前为止看到的字符对和三元组的计数。然后只需递归地生成所有有效序列。为了使此操作更加随机,您可以采样/随机排列每个递归调用中尝试字符的顺序。

如果将其实现为生成器(例如,在Python中),则可以使用它生成全部或仅生成下一个此类组合。否则,只需返回找到的第一个解决方案即可。

Python示例:

Var test

Function .onInit
StrCpy $test ""
FunctionEnd

Section
${If} $test == "something"
${EndIf}
SectionEnd

示例:

import collections, random
def backtrack(available, n, counts, last=None, lastlast=None):
    if n == 0:
        yield []
    else:
        for c in random.sample(list(available), len(available)):
            # check constraints
            if available[c] == 0: continue
            if c == last: continue
            if last is not None and counts[c+last] > 1: continue
            if lastlast is not None and counts[c+last+lastlast] > 0: continue
            # update counts
            available[c] -= 1
            if last: counts[c+last] += 1
            if lastlast: counts[c+last+lastlast] += 1
            # recursive call to get remainder
            for rest in backtrack(available, n-1, counts, c, last):
                yield [c] + rest
            # reset counts
            available[c] += 1
            if last: counts[c+last] -= 1
            if lastlast: counts[c+last+lastlast] -= 1

输出:

lst = "A B C D E F A B C D E F A B C D E F A B C D E F".split()
print(next(backtrack(collections.Counter(lst), 6, collections.Counter())))
print(next(backtrack(collections.Counter(lst), 6, collections.Counter())))
print(next(backtrack(collections.Counter(lst), 6, collections.Counter())))
res = list(backtrack(collections.Counter(lst), 6, collections.Counter()))
print(len(res))

但是,根据列表和要从中获取的元素数量,从列表中生成随机样本并检查约束条件,直到找到可行的约束条件,也可能会起作用。