Algorithm 茶叶袋风味混合算法
我买了一盒盒不同口味(A、B、C)的茶叶袋 我希望以这样一种方式混合它们——永远不会有两个连续的袋具有相同的味道(避免使用ABCCAB);-混合是“最”随机的,即避免像ABCABC。。。或者阿巴巴,BCBC,卡卡卡 对于这种混合有一种已知的算法吗 目前,我随机洗牌许多“ABC”并连接结果,如果上次洗牌的最新字母与新洗牌的开头相同,则交换第一个字母(…ABCCAB=>…ABCACB) 我想我可以通过预先计算ABC的排列来改进这个算法,并在那些不以相同字母开头的排列中画出一个排列 我试图用谷歌搜索这个问题,但作为一个母语为法语的人,我可能没有找到合适的关键词Algorithm 茶叶袋风味混合算法,algorithm,Algorithm,我买了一盒盒不同口味(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”的所有六个排列,以词汇顺序串联起来?如果将其计算为随机数,请参见。如果不是,请看。这个答案是我改进算法的途径之一(这对“路径”或“方式”正确吗)。在第三种味道只剩下一袋之前,我感觉到了耗尽两种味道的风险。可能是,有可能偏向随机性,偏向最容易获得的味道。当剩余量等于总量的一半时,强制使用一个选项可能就足够了(因为此时您需要每两次选择一个选项)。我会看看是否可以用这个更新我的解决方案。虽然它比您当前的解决方案具有更大的全局随机性,但在序列结束时,它可能会“感觉不那么随机”(如中所示,您将有更少的局部变化)。。。我的茶包盒有有限数量的袋子。这导致频率不平衡,这意味着序列可能以重复一种味道结束。我同意我可以购买另一组盒子,以达到无穷大:-),但这种算法有一些项目数量有限的应用:例如学生名单。