提问人:Carra 提问时间:11/29/2011 最后编辑:ShahbazCarra 更新时间:11/17/2023 访问量:251
号码分布
Number distribution
问:
问题:我们有 x 个复选框,我们想均匀地选中 y 个复选框。
示例 1:选中 50 个复选框,共 100 个复选框。
[-]
[x]
[-]
[x]
...
示例 2:选中 33 个复选框,共 100 个复选框。
[-]
[-]
[x]
[-]
[-]
[x]
...
示例 3:选中 66 个复选框,共 100 个复选框:
[-]
[x]
[x]
[-]
[x]
[x]
...
但是我们很难想出一个公式来检查代码中的它们,尤其是当你进入 11/111 或类似的东西时。有人有想法吗?
答:
我们首先假设可以被 整除。然后我们表示,解决方案很简单。浏览列表,每个元素,标记其中的 1 个。y
x
p = y/x
p
现在,假设 r = y%x
不为零。仍然 p = y/x
,其中 /
是整数表示。因此,您需要:
在第一个p-r
元素中,标记 1 个元素在最后一个r
元素中,标记 2 个元素
注意:这取决于如何定义均匀分布。您可能希望将具有x+1
元素的 r 部分分布在具有 x
元素的 p-r
部分之间,这确实又是同一个问题,并且可以通过递归方式解决。
好吧,所以它实际上不正确。我认为这可以:
无论可分割性如何:
- 如果 ,则将每个元素标记 1 个元素,次数。
y > 2*x
p = y/x
x
- 如果 ,则全部标记,并执行上一步取消标记复选框(与前一种情况类似,但替换为
y < 2*x
y-x
y
x
y-x
)
注意:这取决于如何定义均匀分布。例如,您可能希望在 和 元素之间进行更改,以便更好地分布它们。p
p+1
评论
p-1
p
假设复选框的数量是 C,X 的数量是 N。
您的示例指出,C=111 和 N=11 是最麻烦的情况。
试试这个:除以 C/N,称之为 D。数组中的索引为双数 I。将另一个变量作为计数器 M。
double D = (double)C / (double)N;
double I = 0.0;
int M = N;
while (M > 0) {
if (checkboxes[Round(I)].Checked) { // if we selected it, skip to next
I += 1.0;
continue;
}
checkboxes[Round(I)].Checked = true;
M --;
I += D;
if (Round(I) >= C) { // wrap around the end
I -= C;
}
}
请注意,Round(x) 应返回 x 的最接近的整数值。
这个可能对你有用。
我认为关键是要计算您期望每张支票有多少个框。
假设您想要 100 个框中的 33 张支票。,因此您希望每 3.030303 次检查一次...盒。这意味着每 3.030303...框中,您需要添加一个勾选。100 个框中的 66 张支票意味着每 1.51515 张支票一张......框,11 个框中的 111 个检查意味着每 10.090909 个检查一次......盒子,等等。100 / 33 = 3.030303...
double count = 0;
for (int i = 0; i < boxes; i++) {
count += 1;
if (count >= boxes/checks) {
checkboxes[i] = true;
count -= count.truncate(); // so 1.6 becomes 0.6 - resetting the count but keeping the decimal part to keep track of "partial boxes" so far
}
}
您可能更愿意使用 as 而不是 for ,或者由于舍入错误,最后一个框可能会被跳过。decimal
double
count
这是一个使用整数算术的简单解决方案:
void check(char boxes[], int total_count, int check_count)
{
int i;
for (i = 0; i < total_count; i++)
boxes[i] = '-';
for (i = 0; i < check_count; i++)
boxes[i * total_count / check_count] = 'x';
}
total_count
是框的总数,也是要检查的框数。check_count
首先,它将每个框设置为未选中。然后,它选中复选框,将计数器缩放到框数。check_count
注意:这是左偏的,而不是像你的例子中那样偏右的。也就是说,它打印而不是 .你可以通过替换x--x--
--x--x
boxes[i * total_count / check_count] = 'x';
跟:
boxes[total_count - (i * total_count / check_count) - 1] = 'x';
正确性
假设 ,并且至少可以容纳项目,我们可以证明:0 <= check_count <= total_count
boxes
total_count
不会重叠任何复选标记。 每次迭代至少递增 1,因为 .
i * total_count / check_count
total_count >= check_count
这不会溢出缓冲区。下标
i * total_count / check_count
将是.、 和 都将是 。
>= 0
i
total_count
check_count
>= 0
将是.何时和 :
< total_count
n > 0
d > 0
(n * d - 1) / d < n
换句话说,如果我们取 ,并将分子向下推,商也会下降。
n * d / d
因此,在上述假设下,将小于 。除以零不会发生,因为如果为 0,则相关循环的迭代次数将为零。
(check_count - 1) * total_count / check_count
total_count
check_count
快速 html/javascript 解决方案:
<html>
<body>
<div id='container'></div>
<script>
var cbCount = 111;
var cbCheckCount = 11;
var cbRatio = cbCount / cbCheckCount;
var buildCheckCount = 0;
var c = document.getElementById('container');
for (var i=1; i <= cbCount; i++) {
// make a checkbox
var cb = document.createElement('input');
cb.type = 'checkbox';
test = i / cbRatio - buildCheckCount;
if (test >= 1) {
// check the checkbox we just made
cb.checked = 'checked';
buildCheckCount++;
}
c.appendChild(cb);
c.appendChild(document.createElement('br'));
}
</script>
</body></html>
根据一个问题的答案或本月早些时候的另一个答案改编代码。设置 N = x
= 复选框的数量和 M = y =
要检查的数字,并应用截面大小的公式。(另请参阅乔伊·亚当斯(Joey Adams)的回答。(N*i+N)/M - (N*i)/M
在 python 中,改编后的代码是:
N=100; M=33; p=0;
for i in range(M):
k = (N+N*i)/M
for j in range(p,k-1): print "-",
print "x",
p=k
它产生
where [...] 代表 25 次重复。
代码给出
了 where [...] 主要代表重复,中间有一个。- - x - - x - - x - - x - - [...] x - - x - - - x
--x
M=66
x - x x - x x - x x - x x - [...] x x - x x - x - x
xx-
x-
请注意,在 C 或 java 中:
用 代替 。
用 代替 。for (i=0; i<M; ++i)
for i in range(M):
for (j=p; j<k-1; ++j)
for j in range(p,k-1):
正确性:请注意,复选框被选中,因为打印“x”是
执行时间。M = x
M
类似 Bresenham 的算法适用于均匀分布复选框。“x”的输出对应于 Y 坐标的变化。可以选择初始错误作为范围 [0..places) 中的随机值,以避免偏差。
def Distribute(places, stars):
err = places // 2
res = ''
for i in range(0, places):
err = err - stars
if err < 0 :
res = res + 'x'
err = err + places
else:
res = res + '-'
print(res)
Distribute(24,17)
Distribute(24,12)
Distribute(24,5)
output:
x-xxx-xx-xx-xxx-xx-xxx-x
-x-x-x-x-x-x-x-x-x-x-x-x
--x----x----x---x----x--
使用 Fisher-Yates shuffle 怎么样?
创建数组,随机播放并选择前 n 个元素。你不需要把它们全部洗牌,只需要数组的前n个。在大多数语言库中都可以找到随机排序。
评论
上一个:为什么原位突变用“IO”表示?
下一个:号码分布
评论