号码分发

时间:2011-11-28 16:09:35

标签: algorithm language-agnostic

问题:我们有x个复选框,我们想要均匀地检查它们。

示例1:选择50个总共100个复选框。

[-]
[x]
[-]
[x]
...

示例2:选择总共100个的33个复选框。

[-]
[-]
[x]
[-]
[-]
[x]
...

示例3:选择总共100个的66个复选框:

[-]
[x]
[x]
[-]
[x]
[x]
...

但我们很难想出一个公式来检查代码,特别是一旦你去了11/111或类似的东西。有人有想法吗?

6 个答案:

答案 0 :(得分:4)

我们首先假设y可以被x整除。然后我们表示p = y/x,解决方案很简单。浏览列表,每个p个元素,标记其中的一个。

现在,让我们说r = y%x不为零。仍为p = y/x,其中/为整数分割。所以,你需要:

  • 在第一个p-r元素中,标记1个元素
  • 在最后的r元素中,标记2个元素

注意:这取决于您如何定义均匀分布。您可能希望在r个部分之间使用x+1元素展开p-r个部分和x元素,这确实是同样的问题,可以递归解决。

好吧所以它实际上并不正确。我想这会做到:

无论可分性如何:

  • 如果y > 2*x,则每p = y/x个元素标记1个元素,x次。
  • 如果y < 2*x,则标记全部,然后执行上一步操作y-x y复选框{与前一种情况相同,但x被替换为y-x p

注意:这取决于您如何定义均匀分布式。您可能希望在p+1和{{1}}元素之间进行更改,例如更好地分发它们。

答案 1 :(得分:2)

这是使用整数运算的直接解决方案:

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项的空间,我们可以证明:

  • 没有复选标记会重叠。每次迭代时i * total_count / check_count至少增加一次,因为total_count >= check_count

  • 这不会溢出缓冲区。下标i * total_count / check_count

    • 将是>= 0itotal_countcheck_count都是>= 0

    • 将是< total_count。当n > 0d > 0

      (n * d - 1) / d < n
      

      换句话说,如果我们取n * d / d并向下推动分子,那么商也会下降。

      因此,(check_count - 1) * total_count / check_count将小于total_count,具有上述假设。不会发生除零,因为如果check_count为0,则所讨论的循环将具有零迭代。

答案 2 :(得分:1)

Bresenham - 类似算法适合均匀分配复选框。 'x'的输出对应于Y坐标变化。可以在范围[0..places]中选择初始err作为随机值,以避免偏差。

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--

答案 3 :(得分:0)

快速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>

答案 4 :(得分:0)

从本月早些时候开始调整one question's answeranother answer的代码。设置 N = x = 数量的复选框以及要检查的 M = y = 数字,并为部分尺寸应用公式(N*i+N)/M - (N*i)/M。 (另见Joey Adams的回答。)

在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

产生
- - x - - x - - x - - x - - [...] x - - x - - - x
其中[...]代表25 --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):

正确性:请注意M = x框被选中,因为 print "x", 执行M次。

答案 5 :(得分:0)

如何使用Fisher–Yates shuffle

制作数组,随机播放并选择前n个元素。你不需要将它们全部洗牌,只需要数组的前n个。在大多数语言库中都可以找到改组。