Algorithm 茶叶袋风味混合算法

Algorithm 茶叶袋风味混合算法,algorithm,Algorithm,我买了一盒盒不同口味(A、B、C)的茶叶袋 我希望以这样一种方式混合它们——永远不会有两个连续的袋具有相同的味道(避免使用ABCCAB);-混合是“最”随机的,即避免像ABCABC。。。或者阿巴巴,BCBC,卡卡卡 对于这种混合有一种已知的算法吗 目前,我随机洗牌许多“ABC”并连接结果,如果上次洗牌的最新字母与新洗牌的开头相同,则交换第一个字母(…ABCCAB=>…ABCACB) 我想我可以通过预先计算ABC的排列来改进这个算法,并在那些不以相同字母开头的排列中画出一个排列 我试图用谷歌搜索这

我买了一盒盒不同口味(A、B、C)的茶叶袋

我希望以这样一种方式混合它们——永远不会有两个连续的袋具有相同的味道(避免使用ABCCAB);-混合是“最”随机的,即避免像ABCABC。。。或者阿巴巴,BCBC,卡卡卡

对于这种混合有一种已知的算法吗

目前,我随机洗牌许多“ABC”并连接结果,如果上次洗牌的最新字母与新洗牌的开头相同,则交换第一个字母(…ABCCAB=>…ABCACB)

我想我可以通过预先计算ABC的排列来改进这个算法,并在那些不以相同字母开头的排列中画出一个排列

我试图用谷歌搜索这个问题,但作为一个母语为法语的人,我可能没有找到合适的关键词


PS:我之前在scicomp.stackexchange.com上发布了这个问题,并被建议在这里复制它。

类似的方法应该可以:

amount_of_teabags_per_flavour = x
choices = {
    A : amount_of_teabags_per_flavour,
    B : amount_of_teabags_per_flavour,
    C : amount_of_teabags_per_flavour
}
previous_choice = 0
picks_left = amount_of_teabags_per_flavour * choices.size

function select_available_choices() :
    mandatory_choice = [ key from choices where key != previous_choice and value <= picks_left/2 ] 
    if mandatory_choice == [] :
        available_choices = [ key from choices where key != previous_choice and value > 0 ]
    otherwise
        available_choices = mandatory_choice


result = []
select_available_choices()
while available_choices != [] :
    choice = pick_randomly_from(available_choices)
    result[last] = choice
    previous_choice = choice
    choices[choice]--
    picks_left--
    select_available_choices()
每种味道的茶包数量=x
选择={
A:每种口味的茶包数量,
B:每种口味的茶包数量,
C:每种味道的茶袋数量
}
上一个选项=0
picks_left=每种味道的茶叶袋数量*choices.size
函数选择可用选项()
强制_选项=[来自选项的键,其中键!=上一个_选项和值0]
否则
可用选项=强制选项
结果=[]
选择可用的选项()
在可用的情况下_选择!=[] :
选择=从(可用选项)中随机选择
结果[最后]=选择
先前的选择=选择
选择--
左勾--
选择可用的选项()

对于第一种口味,您可以随机从三个字母
A
B
C
中的一个开始,然后从其他两种可能性中的一个计算下一个字母(因为您不希望口味重复)

python3中的快速脚本:

from random import randint

rand = lambda x: randint(0,x)

flavors = ['A', 'B', 'C']
freq = [0, 0, 0]

index = rand(2)
mix = flavors[index]

for i in range(1000):
        index = (index + 1 + rand(1)) % 3
        mix += flavors[index]
        freq[index] += 1

print(mix)
print(freq)

您可以看到随机性很好(给定频率和足够宽的范围),并且没有字符在一行中重复两次。

避免在边界处重复是一个图形问题。从每个节点(排列)到每个其他节点都有一条定向边。。。除了双重边界。你需要一个通过图的哈密顿路径;在线解决方案随时可用。然后根据需要复制或截断该路径,以匹配每个箱子中的行李数量

如果要简化问题,请生成边以仅将每个节点与以上一个包的第二个包开始的节点连接。例如,您的3盒设计

ABC -> BAC, BCA
CBA -> BAC, BCA
BAC -> ABC, ACB
CAB -> ABC, ACB
ACB -> CAB, CBA
BCA -> CAB, CBA
任何从完全置换集构建的图都有一个哈密顿路径,而且它的查找速度要快得多。一个简单的递归算法(带回溯)应该很容易编码。如果你按照二阶可用性对你的选择进行排序,我认为问题本身就可以解决,而不会出现回溯

例如,如果您在节点
ABC
,请查看以
B
开头的可用选项:
BAC
BCA
查看其中的第二个字母:
A
只提供了一个剩余的选择(
ABC
已经使用),但
C
仍然有两个选择。因此,您将转到
BCA
。如果你的首要选择是并列的,那么决定你想要的任何方式。。。保留在结束时返回起始节点的功能


这解决了你的问题吗?

另一个交叉建议是,既然你已经有了一个有效的解决方案,那么你能澄清一下,你目前产生的三重值是否与你以后加入的单一口味的茶包一样多?特别是,一个解决方案应该产生整个序列,还是只是提供下一袋茶的一种方法?不清楚“最随机”是什么意思。我想你的意思是“看起来随机”,你的意思是没有明显的模式。或者你的意思是,没有重复字母的每个序列都有相同的可能性?如果你指的是前者,那就不是一个明确的问题。谢谢。顺便说一下,我对Stase*来说是相当新的:是否有一种在USENET中实现交叉的方法?你会认为“ABCACBACBCCAABCBA”是一个相当随机的字符串,因为它仅仅是“ABC”的所有六个排列,以词汇顺序串联起来?如果将其计算为随机数,请参见。如果不是,请看。这个答案是我改进算法的途径之一(这对“路径”或“方式”正确吗)。在第三种味道只剩下一袋之前,我感觉到了耗尽两种味道的风险。可能是,有可能偏向随机性,偏向最容易获得的味道。当剩余量等于总量的一半时,强制使用一个选项可能就足够了(因为此时您需要每两次选择一个选项)。我会看看是否可以用这个更新我的解决方案。虽然它比您当前的解决方案具有更大的全局随机性,但在序列结束时,它可能会“感觉不那么随机”(如中所示,您将有更少的局部变化)。。。我的茶包盒有有限数量的袋子。这导致频率不平衡,这意味着序列可能以重复一种味道结束。我同意我可以购买另一组盒子,以达到无穷大:-),但这种算法有一些项目数量有限的应用:例如学生名单。