【问题标题】:Program to solve Circular Combinatorics Program Problem解决循环组合程序问题的程序
【发布时间】:2020-06-28 15:16:31
【问题描述】:

我了解如何通过手工解决问题,但我想创建一个 Javascript 程序来为 (c,r) 完成此操作,其中 c 是容器,r 是岩石。

设置 您有 4 块相同类型的无法区分的岩石。您还有 10 个容器。每个容器可以容纳 0 块石头或 1 块石头。每次排列都需要使用所有 4 块石头,每次排列留下 6 个 0。

我相信基于组合生成器应该有大约 210 种可能性 (10!)/ (4! * (10-4)!)。

例如,这些是可能性的示例:

1111000000
1110100000
1110001000
0000001111
0101010100

我正在寻找的是一个 javascript 函数,它将吐出 210 个数组,使得它是 [1,1,1,1,0,0,0,0,0,0] 并输入一些岩石和容器。

【问题讨论】:

  • 基本上,您正在寻找 0 - 1023 ( 2 ^ 10 个数字 - 1 ) 中设置了 4 位的所有二进制数。快速而肮脏的方法是从 0 循环到 1023,将此数字转换为二进制(即 toString(2) )并计算 1 的数量。如果有四个 1,则保留结果,否则继续下一个数字。
  • @JonTrent 我根据您的想法发布了一个答案,我觉得这太棒了。如果您想自己发布此答案作为答案,请这样做!这是你的主意
  • @blex,全是你!你做了繁重的工作。另外,您将 1 拆分以计算 1 的方法是一种巧妙的方法。

标签: javascript node.js algorithm math combinatorics


【解决方案1】:

我尝试了@JonTrent 的方法(从0 计数到2^c - 1),这是一个非常聪明的方法:

function getCombinations(c, r) {
  const max = Math.pow(2, c);
  const res = [];
  for (let i = 0; i < max; i++) {
    const binary = i.toString(2);
    if (binary.split("1").length - 1 === r) {
      res.push(
        binary.padStart(c, '0')
              .split('')
              .map(n => parseInt(n, 10))
      );
    }
  }
  return res;
}

const res = getCombinations(10, 4);
// [
//  [0,0,0,0,0,0,1,1,1,1],
//  [0,0,0,0,0,1,0,1,1,1],
//  [0,0,0,0,0,1,1,0,1,1]
//  ...
// ]

document.body.innerHTML = `<pre>${res.map(x => x.join('')).join('\n')}</pre>`;
console.log(`${res.length} combinations found!`);

【讨论】:

    【解决方案2】:

    我只是从这里复制了答案,Permutations in JavaScript?

    然后在输入数组中添加任意数量的空间。然后尝试从该帖子中获得的任何解决方案。

    function permutator(inputArr) {
      var results = [];
    
      function permute(arr, memo) {
        var cur, memo = memo || [];
    
        for (var i = 0; i < arr.length; i++) {
          cur = arr.splice(i, 1);
          if (arr.length === 0) {
            results.push(memo.concat(cur));
          }
          permute(arr.slice(), memo.concat(cur));
          arr.splice(i, 0, cur[0]);
        }
    
        return results;
      }
    
      return permute(inputArr);
    }
    
    console.log(permutator(['a', ' ', 'b', 'c']))

    【讨论】:

    • 然而,这并不能解决问题。如果我们想象有 3 个容器和 2 个岩石,(permutator(['1', '1', '0'])),我们会得到重复的组合
    • 哦,然后用唯一的结果搜索permutation。试试stackoverflow.com/questions/40264376/…
    【解决方案3】:

    你可以寻找下一个元素来交换和重新排列右边的左边值到最右边。

    function perm(string) {
        var array = [...string],
            l = array.length - 1,
            r = array.length - 1;
        
        // either starts with zero from end or with one and get only ones
        while (array[l] === '0') l--;
        while (array[l] === '1') l--;
        if (l < 0) return;
        [array[l], array[l + 1]] = [array[l + 1], array[l]];
        while (r > ++l) {
            if (array[l] === '1') {
                [array[l], array[r]] = [array[r], array[l]];
                r--;
            }
        }
        return array.join('');
    }
    
    var string = '0000001111',
        i = 0,
        log = document.getElementById('out');
        
    do out.innerHTML += `${(++i).toString().padStart(3, ' ')} ${string}\n`;
    while (string = perm(string));
    &lt;pre id="out"&gt;&lt;/pre&gt;

    【讨论】:

      【解决方案4】:
      function circular(c, r) {
          let arrs = [[]];
          for (let i = 0; i < c; i++) {
              let len = arrs.length;
              for (let j = 0; j < len; j++) {
                  arr = arrs.shift();
                  if (arr.filter((el) => el === 0).length < c - r) {
                      arrs.push(arr.concat([0]));
                  }
                  if (arr.filter((el) => el === 1).length < r) {
                      arrs.push(arr.concat([1]));
                  }
              }
          }
          return arrs;
      }
      
      console.log(circular(3, 1));
      console.log(circular(10, 4).length);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-22
        • 1970-01-01
        • 1970-01-01
        • 2020-08-20
        • 1970-01-01
        • 1970-01-01
        • 2021-01-20
        相关资源
        最近更新 更多