根据位置计算组合

发布于 2024-11-06 10:32:10 字数 502 浏览 5 评论 0原文

我有这样的组合:

1,2,3,4 //index 0
1,2,3,5 //索引 1
1,2,3,6 //索引 2

依此类推,直到 7,8,9,10

所以这将是组合数学中的 n=10 k=4

如何通过索引计算组合

例如当我的索引==1
myCmb = func(索引)
返回 1,2,3,5

这是一个例子,我需要这个来获得最大的数字,并且需要更多的参数,并且没有(如果可能的话)很多循环,

我找到这样的东西来获取位置: http://answers.yahoo.com/question/index?qid=20110320070039AA045ib

我现在想扭转这个......

我用 C++ 编程 感谢您的任何建议或帮助

I have combinations like this:

1,2,3,4 //index 0
1,2,3,5 //index 1
1,2,3,6 //index 2

and so on until 7,8,9,10

So this will be n=10 k=4 from combinatorics

How calculate combination by index

For example when my index==1
myCmb = func(index)
returns 1,2,3,5

this is example i need this for bigest numbers, and for more params and without (if this possible) many loops

i find something like this to obtain position:
http://answers.yahoo.com/question/index?qid=20110320070039AA045ib

I want now reverse this...

I programming in C++
Thanks for any sugesstions or help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

早乙女 2024-11-13 10:32:10

似乎您想要查找给定数字的 k 组合。

按照示例,以下是应该有效的内容:

#include <cstddef>
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
#include <boost/math/special_functions/binomial.hpp>


std::size_t Choose(double n, double k) {
  using boost::math::binomial_coefficient;
  if (n < k) return 0;
  return static_cast<std::size_t>(binomial_coefficient<double>(n, k));
}

// Returns the largest n such that Choose(n, k) <= pos.
int CombinationElement(int k, int pos) {
  int n = k;
  int coeff = 1, prev_coeff = 0;

  while (coeff <= pos) {
    coeff = Choose(++n, k);
    prev_coeff = coeff;
  }

  return n - 1;
}

// Returns an k-combination at position pos.
std::vector<int> Combination(int k, int pos) {
  std::vector<int> combination;
  for (; k > 0; --k) {
    int n = CombinationElement(k, pos);
    combination.push_back(n);
    pos -= Choose(n, k);
  }
  return combination;
}

int main(int argc, char** argv) {
  using std::cout;
  using std::endl;

  if (argc != 3) {
    cout << "Usage:  $ " << argv[0] << " K POS" << endl;
    cout << "Prints the K-combination at position POS." << endl;
    return 1;
  }

  int k = boost::lexical_cast<int>(argv[1]);
  int pos = boost::lexical_cast<int>(argv[2]);

  std::vector<int> combination = Combination(k, pos);

  for (int i = 0; i < k; i++)
    cout << combination[i] << " ";
  cout << std::endl;
}

请注意,为了方便起见,该代码依赖于 Boost 来计算二项式系数(boost::math::binomial_coefficient),并将字符串解析为整数 (boost::lexical_cast)。

It seems like you want to find the k-combination for a given number.

Following the example, here's something that should work:

#include <cstddef>
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
#include <boost/math/special_functions/binomial.hpp>


std::size_t Choose(double n, double k) {
  using boost::math::binomial_coefficient;
  if (n < k) return 0;
  return static_cast<std::size_t>(binomial_coefficient<double>(n, k));
}

// Returns the largest n such that Choose(n, k) <= pos.
int CombinationElement(int k, int pos) {
  int n = k;
  int coeff = 1, prev_coeff = 0;

  while (coeff <= pos) {
    coeff = Choose(++n, k);
    prev_coeff = coeff;
  }

  return n - 1;
}

// Returns an k-combination at position pos.
std::vector<int> Combination(int k, int pos) {
  std::vector<int> combination;
  for (; k > 0; --k) {
    int n = CombinationElement(k, pos);
    combination.push_back(n);
    pos -= Choose(n, k);
  }
  return combination;
}

int main(int argc, char** argv) {
  using std::cout;
  using std::endl;

  if (argc != 3) {
    cout << "Usage:  $ " << argv[0] << " K POS" << endl;
    cout << "Prints the K-combination at position POS." << endl;
    return 1;
  }

  int k = boost::lexical_cast<int>(argv[1]);
  int pos = boost::lexical_cast<int>(argv[2]);

  std::vector<int> combination = Combination(k, pos);

  for (int i = 0; i < k; i++)
    cout << combination[i] << " ";
  cout << std::endl;
}

Note, for convenience, the code depends on Boost to calculate binomial coefficients (boost::math::binomial_coefficient<T>), and to parse strings into integers (boost::lexical_cast).

遮了一弯 2024-11-13 10:32:10

下面是 Mathematica 中的一个实现,来自 Combinatorica 包。语义相当通用,所以我认为它很有帮助。如果您需要任何解释,请发表评论。

UnrankKSubset::usage = "UnrankKSubset[m, k, l] gives the mth k-subset of set l, listed in lexicographic order."

UnrankKSubset[m_Integer, 1, s_List] := {s[[m + 1]]}
UnrankKSubset[0, k_Integer, s_List] := Take[s, k]
UnrankKSubset[m_Integer, k_Integer, s_List] := 
       Block[{i = 1, n = Length[s], x1, u, $RecursionLimit = Infinity}, 
             u = Binomial[n, k]; 
             While[Binomial[i, k] < u - m, i++]; 
             x1 = n - (i - 1); 
             Prepend[UnrankKSubset[m - u + Binomial[i, k], k-1, Drop[s, x1]], s[[x1]]]
       ]

用法如下:

UnrankKSubset[1, 4, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}]
   {1, 2, 3, 5}

正如您所看到的,该函数在集合上运行。


下面是我尝试解释上面的代码。

UnrankKSubset 是一个具有三个参数的递归函数,称为 (m, k, s):

  1. m 是一个整数,是按字典顺序排列的组合的“排名”,从零开始。
  2. k 一个整数,每个组合中的元素数量
  3. s 一个列表,从中组装组合的元素

递归有两个边界条件:

  1. 对于任何排名m,以及任何列表s,如果每个组合k中的元素数量为1,则:

    返回列表sm + 1元素,它本身在列表中。

    (+ 1 是必需的,因为 Mathematica 从 1 开始索引,而不是从零开始。我相信在 C++ 中这将是 s[m] )

  2. 如果排名 m0 那么对于任何 k 和任何 s

    返回 s

    的前 k 个元素

主递归函数,对于除上面指定的:

局部变量:(i, n, x1, u)

二项式 是二项式系数: Binomial[7, 5] = 21

执行:

i = 1
n = Length[s]
u = Binomial[n, k]
While[Binomial[i, k] < u - m, i++];
x1 = n - (i - 1);

然后返回:

Prepend[
  UnrankKSubset[m - u + Binomial[i, k], k - 1, Drop[s, x1]], 
  s[[x1]]
]

即“前置”列表 sx1 元素code> (记住 Mathematica 索引从 1 开始,所以我相信这将是 C++ 中的 x1 - 1 索引)到递归调用 UnrankKSubset 函数返回的列表,参数为:

  • m - u + Binomial[i, k]
  • k - 1
  • Drop[s, x1]

Drop[s, x1] 是其余的列表 s 中删除了第一个 x1 元素。


如果以上任何内容无法理解,或者如果您想要的是算法的解释,而不是代码的解释,请发表评论,我会再试一次。

Here is an implementation in Mathematica, from the package Combinatorica. The semantics are fairly generic, so I think it is helpful. Please leave a comment if you need anything explained.

UnrankKSubset::usage = "UnrankKSubset[m, k, l] gives the mth k-subset of set l, listed in lexicographic order."

UnrankKSubset[m_Integer, 1, s_List] := {s[[m + 1]]}
UnrankKSubset[0, k_Integer, s_List] := Take[s, k]
UnrankKSubset[m_Integer, k_Integer, s_List] := 
       Block[{i = 1, n = Length[s], x1, u, $RecursionLimit = Infinity}, 
             u = Binomial[n, k]; 
             While[Binomial[i, k] < u - m, i++]; 
             x1 = n - (i - 1); 
             Prepend[UnrankKSubset[m - u + Binomial[i, k], k-1, Drop[s, x1]], s[[x1]]]
       ]

Usage is like:

UnrankKSubset[1, 4, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}]
   {1, 2, 3, 5}

As you can see this function operates on sets.


Below is my attempt to explain the code above.

UnrankKSubset is a recursive function with three arguments, called (m, k, s):

  1. m an Integer, the "rank" of the combination in lexigraphical order, starting from zero.
  2. k an Integer, the number of elements in each combination
  3. s a List, the elements from which to assemble combinations

There are two boundary conditions on the recursion:

  1. for any rank m, and any list s, if the number of elements in each combination k is 1, then:

    return the m + 1 element of the list s, itself in a list.

    (+ 1 is needed because Mathematica indexes from one, rather than zero. I believe in C++ this would be s[m] )

  2. if rank m is 0 then for any k and any s:

    return the first k elements of s

The main recursive function, for any other arguments than ones specified above:

local variables: (i, n, x1, u)

Binomial is binomial coefficient: Binomial[7, 5] = 21

Do:

i = 1
n = Length[s]
u = Binomial[n, k]
While[Binomial[i, k] < u - m, i++];
x1 = n - (i - 1);

Then return:

Prepend[
  UnrankKSubset[m - u + Binomial[i, k], k - 1, Drop[s, x1]], 
  s[[x1]]
]

That is, "prepend" the x1 element of list s (remember Mathematica indexes from one, so I believe this would be the x1 - 1 index in C++) to the list returned by the recursively called UnrankKSubset function with the arguments:

  • m - u + Binomial[i, k]
  • k - 1
  • Drop[s, x1]

Drop[s, x1] is the rest of list s with the first x1 elements removed.


If anything above is not understandable, or if what you wanted was an explanation of the algorithm, rather than an explanation of the code, please leave a comment and I will try again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文