- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有 tried to ask this question before ,但一直无法正确表达。我希望这次我做对了:
我有一个独特元素的列表。我想改组这个列表以生成一个新列表。但是,我想限制随机播放,使每个元素的新位置最多 d
远离其在列表中的原始位置。
例如:
L = [1,2,3,4]
d = 2
answer = magicFunction(L, d)
现在,一种可能的结果是:
>>> print(answer)
[3,1,2,4]
注意 3
移动了两个索引,1
和 2
移动了一个索引,4
移动了一个索引根本不动。因此,根据我之前的定义,这是一个有效的洗牌。以下代码片段可用于验证这一点:
old = {e:i for i,e in enumerate(L)}
new = {e:i for i,e in enumerate(answer)}
valid = all(abs(i-new[e])<=d for e,i in old.items())
现在,我可以轻松地生成所有可能的 L
排列,过滤出有效的排列,然后随机选择一个。但这似乎不是很优雅。有没有人对如何实现这一点有任何其他想法?
最佳答案
这将是漫长而干燥的。
我有一个产生均匀分布的解决方案。它需要 O(len(L) * d**d)
时间和空间进行预计算,然后在 O(len(L)*d)
时间1。如果不需要均匀分布,则不需要预计算,由于更快的随机选择,shuffle时间可以减少到O(len(L))
;我还没有实现非均匀分布。这个算法的两个步骤都比蛮力快得多,但它们仍然没有我希望的那么好。此外,虽然这个概念应该可行,但我并没有像我想要的那样彻底测试我的实现。
假设我们从前面迭代 L
,为每个元素选择一个位置。将 lag 定义为下一个要放置的元素与第一个未填充位置之间的距离。每次我们放置一个元素,延迟最多增长一个,因为下一个元素的索引现在高一个,但第一个未填充位置的索引不能变低。
只要滞后是d
,我们就被迫将下一个元素放在第一个未填充的位置,即使在d
的距离内可能还有其他空白点.如果我们这样做了,那么延迟就不会超过 d
,我们将始终有一个位置来放置每个元素,并且我们将生成一个有效的列表混洗。因此,我们对如何生成 shuffle 有了大致的了解;但是,如果我们随机均匀地做出选择,则整体分布将不均匀。例如,对于 len(L) == 3
和 d == 1
,有 3 种可能的 shuffle(中间元素的每个位置一个),但是如果我们统一选择第一个元素的位置,一个随机播放的可能性是其他任何一个的两倍。
如果我们想要在有效 shuffle 上均匀分布,我们需要对每个元素的位置进行加权随机选择,其中一个位置的权重基于我们选择该位置时可能的 shuffle 的数量。天真地完成,这将需要我们生成所有可能的 shuffle 来计算它们,这将花费 O(d**len(L))
时间。但是,在算法的任何步骤之后剩余的可能洗牌次数仅取决于我们填充了哪些点,而不是它们被填充的顺序。对于任何填充或未填充点的模式,数量of possible shuffles 是下一个元素的每个可能位置的可能 shuffle 数量的总和。在任何一步,最多有 d
个可能的位置来放置下一个元素,并且有 O(d**d)
个可能的未填充点模式(因为任何点比当前元素后面的 d
更远的位置必须是满的,并且任何位置 d
或更靠前的位置必须是空的)。我们可以使用它来生成大小为 O(len(L) * d**d)
的马尔可夫链,取 O(len(L) * d**d)
时间这样做,然后使用这个马尔可夫链在 O(len(L)*d)
时间内执行 shuffle。
示例代码(由于马尔可夫链表示效率低,目前不完全是O(len(L)*d)
):
import random
# states are (k, filled_spots) tuples, where k is the index of the next
# element to place, and filled_spots is a tuple of booleans
# of length 2*d, representing whether each index from k-d to
# k+d-1 has an element in it. We pretend indices outside the array are
# full, for ease of representation.
def _successors(n, d, state):
'''Yield all legal next filled_spots and the move that takes you there.
Doesn't handle k=n.'''
k, filled_spots = state
next_k = k+1
# If k+d is a valid index, this represents the empty spot there.
possible_next_spot = (False,) if k + d < n else (True,)
if not filled_spots[0]:
# Must use that position.
yield k-d, filled_spots[1:] + possible_next_spot
else:
# Can fill any empty spot within a distance d.
shifted_filled_spots = list(filled_spots[1:] + possible_next_spot)
for i, filled in enumerate(shifted_filled_spots):
if not filled:
successor_state = shifted_filled_spots[:]
successor_state[i] = True
yield next_k-d+i, tuple(successor_state)
# next_k instead of k in that index computation, because
# i is indexing relative to shifted_filled_spots instead
# of filled_spots
def _markov_chain(n, d):
'''Precompute a table of weights for generating shuffles.
_markov_chain(n, d) produces a table that can be fed to
_distance_limited_shuffle to permute lists of length n in such a way that
no list element moves a distance of more than d from its initial spot,
and all permutations satisfying this condition are equally likely.
This is expensive.
'''
if d >= n - 1:
# We don't need the table, and generating a table for d >= n
# complicates the indexing a bit. It's too complicated already.
return None
table = {}
termination_state = (n, (d*2 * (True,)))
table[termination_state] = 1
def possible_shuffles(state):
try:
return table[state]
except KeyError:
k, _ = state
count = table[state] = sum(
possible_shuffles((k+1, next_filled_spots))
for (_, next_filled_spots) in _successors(n, d, state)
)
return count
initial_state = (0, (d*(True,) + d*(False,)))
possible_shuffles(initial_state)
return table
def _distance_limited_shuffle(l, d, table):
# Generate an index into the set of all permutations, then use the
# markov chain to efficiently find which permutation we picked.
n = len(l)
if d >= n - 1:
random.shuffle(l)
return
permutation = [None]*n
state = (0, (d*(True,) + d*(False,)))
permutations_to_skip = random.randrange(table[state])
for i, item in enumerate(l):
for placement_index, new_filled_spots in _successors(n, d, state):
new_state = (i+1, new_filled_spots)
if table[new_state] <= permutations_to_skip:
permutations_to_skip -= table[new_state]
else:
state = new_state
permutation[placement_index] = item
break
return permutation
class Shuffler(object):
def __init__(self, n, d):
self.n = n
self.d = d
self.table = _markov_chain(n, d)
def shuffled(self, l):
if len(l) != self.n:
raise ValueError('Wrong input size')
return _distance_limited_shuffle(l, self.d, self.table)
__call__ = shuffled
1我们可以使用基于树的加权随机选择算法来将 shuffle 时间缩短到 O(len(L)*log(d))
,但由于即使对于中等大小的 d
,表格也会变得如此巨大,这似乎不值得。此外,d**d
的因子在边界中被高估了,但实际因子仍然至少是 d 的指数。
关于python - 控制洗牌距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30747690/
这是一个面试问题。请给一些提示: 使用 vector 实现一个方法,洗一副牌。 public class Card { private int value; Card(int v) {
我非常是 C++ 的新手,我还没有完全理解基本概念,但我的教授希望我们编写一个算法来洗牌和展示一副纸牌和一副牌需要表示为二维数组。 但是我在模拟一副纸牌时遇到了麻烦! #include #inclu
我想用 php 创建随机桥牌的集合。我认为我可以将一副有序的纸牌编码为下面的字符串 $deal(考虑到大写和小写时,我喜欢它有 52 个字母)。我发现了 php 函数 str_shuffle。所以我想
我想随机重新排序矩阵 A 的行以生成另一个新矩阵。如何在 R 中做到这一点? 最佳答案 使用 sample()以(伪)随机顺序生成行索引并使用 [ 重新排列矩阵. ## create a matrix
我计划在 android-Java 上开发一个简单的纸牌游戏,在我的应用程序中,我洗牌,所以我想知道将我的牌组存储在数组或堆栈中的最佳方法是什么..?堆栈的唯一问题是我不知道如何对其进行洗牌。 最佳答
我正在尝试创建一种方法,使用 Arraylist 随机打乱基元数组。我想知道 .get(); 方法是否是在我的 Arraylist 上使用的正确方法,在 for 循环中的普通数组上它只是 array[
我是 C++ 的新手,但是,我正在尝试创建一些盐和胡椒噪音。它几乎完成了,只是在这之间我想洗牌一个整数数组,无论我做什么,无论我使用什么洗牌功能,我总是得到令人讨厌的“从这里需要”,它没有告诉我任何事
我被要求编写一个程序(主要是一个方法)来洗牌。我编写了以下程序: public class Deck { //////////////////////////////////////// // Dat
我已经看到其他与此相关的话题,但似乎没有一个能回答我的问题。我尝试在 vector 上使用 shuffle() 函数,但我一直收到错误消息: deck_of_cards.cpp:34:5: error
是否与sort 一致导致更随机的数组或者是 sort这里只是浪费? use List::Util qw(shuffle); @random1 = shuffle sort keys %vocables
首先,这个问题是从 this 中摘下来的问题。我这样做是因为我认为这部分比较长问题的子部分更大。如有冒犯,请见谅。 假设您有一个生成随机性的算法。现在你如何测试它?或者更直接地说 - 假设您有一个洗牌
我正在制作一个配对游戏,其中有 8 个 ImageView 和 4 个不同的图像。我想知道页面何时加载是否可以交换 ImageView 的位置? 让每张图片的顺序每次都变? 最佳答案 试试这个:
我正在制作一款纸牌游戏,需要在游戏开始前洗牌。通过在将数组插入数据库之前对其进行混洗,可以毫无问题地完成此操作。然而,在游戏开始后,有些情况下玩家需要洗牌。我想到的唯一方法是重新洗牌后重新插入套牌,但
我正在运行一个网站,其中用户导航子目录的唯一方式是通过随机页面(类似于维基百科的随机页面功能)。我已经实现了调用随机页面的代码并且它工作正常,但我想尽量减少在 onclick 执行后再次调用同一页面的
我想用一个条件打乱一个 2d Numpy 数组。例如,仅随机播放非零值。 import numpy as np a = np.arange(9).reshape((3,3)) a[2,2] = 0 #
我将如何获取 RLMArray 并对其进行洗牌,以便 RLMArray 中的当前项目是随机的。 我已经查看了 RLMArray 的文档,但是我没有看到对其进行洗牌的好方法。 最佳答案 你最好的选择可能
在我的 Qt c++ 应用程序中,我有一个包含一组 QString 值的 QStringList!我想随机播放(任意更改 QStringList 中 QString 的位置)。 perl中是否有任何默
我知道它是如何工作的,但我在排序和配对方面仍然有问题,这样我才能确定获胜者。 将它们配对(配对是具有相同值(value)的卡片。)例如,红心 A 和黑桃 A 组成一对。然后我数那些对。拥有最高对子的手
我有一组这样的 div: 我需要在点击其中一个红色 div 时随机播放它们,但点击的 div 应该始终与黄色 div 交换。 fiddle here $('.box-red').click(funct
// deck of cards // below are initializations #include #include #include using namespace std; int
我是一名优秀的程序员,十分优秀!