[英]C++ Newbie needs helps for printing combinations of integers
Suppose I am given:假设我得到:
iRange
(ie from 1
up to iRange
) andiRange
(即从1
到iRange
)和I want to find the number of all possible combinations and print out all these combinations.我想找到所有可能组合的数量并打印出所有这些组合。
For example:例如:
Given : iRange = 5
and n = 3
给定:
iRange = 5
和n = 3
Then the number of combinations is iRange! / ((iRange!-n!)*n!) = 5! / (5-3)! * 3! = 10
那么组合数就是
iRange! / ((iRange!-n!)*n!) = 5! / (5-3)! * 3! = 10
iRange! / ((iRange!-n!)*n!) = 5! / (5-3)! * 3! = 10
iRange! / ((iRange!-n!)*n!) = 5! / (5-3)! * 3! = 10
combinations, and the output is: iRange! / ((iRange!-n!)*n!) = 5! / (5-3)! * 3! = 10
组合,输出为:
123 - 124 - 125 - 134 - 135 - 145 - 234 - 235 - 245 - 345
Another example:另一个例子:
Given : iRange = 4
and n = 2
给定:
iRange = 4
且n = 2
Then the number of combinations is iRange! / ((iRange!-n!)*n!) = 4! / (4-2)! * 2! = 6
那么组合数就是
iRange! / ((iRange!-n!)*n!) = 4! / (4-2)! * 2! = 6
iRange! / ((iRange!-n!)*n!) = 4! / (4-2)! * 2! = 6
iRange! / ((iRange!-n!)*n!) = 4! / (4-2)! * 2! = 6
combinations, and the output is: iRange! / ((iRange!-n!)*n!) = 4! / (4-2)! * 2! = 6
组合,输出为:
12 - 13 - 14 - 23 - 24 - 34
My attempt so far is:到目前为止,我的尝试是:
#include <iostream>
using namespace std;
int iRange= 0;
int iN=0;
int fact(int n)
{
if ( n<1)
return 1;
else
return fact(n-1)*n;
}
void print_combinations(int n, int iMxM)
{
int iBigSetFact=fact(iMxM);
int iDiffFact=fact(iMxM-n);
int iSmallSetFact=fact(n);
int iNoTotComb = (iBigSetFact/(iDiffFact*iSmallSetFact));
cout<<"The number of possible combinations is: "<<iNoTotComb<<endl;
cout<<" and these combinations are the following: "<<endl;
int i, j, k;
for (i = 0; i < iMxM - 1; i++)
{
for (j = i + 1; j < iMxM ; j++)
{
//for (k = j + 1; k < iMxM; k++)
cout<<i+1<<j+1<<endl;
}
}
}
int main()
{
cout<<"Please give the range (max) within which the combinations are to be found: "<<endl;
cin>>iRange;
cout<<"Please give the desired number of combinations: "<<endl;
cin>>iN;
print_combinations(iN,iRange);
return 0;
}
My problem: The part of my code related to the printing of the combinations works only for n = 2, iRange = 4
and I can't make it work in general, ie, for any n
and iRange
.我的问题:我的代码中与组合打印相关的部分仅适用于
n = 2, iRange = 4
并且我无法使其在一般情况下工作,即对于任何n
和iRange
。
Your solution will only ever work for n=2.您的解决方案仅适用于 n=2。 Think about using an array (combs) with n ints, then the loop will tick up the last item in the array.
考虑使用具有 n 个整数的数组(梳子),然后循环将勾选数组中的最后一项。 When that item reaches max update then comb[n-2] item and set the last item to the previous value +1.
当该项目达到最大更新时,comb[n-2] 项目并将最后一个项目设置为先前的值 +1。
Basically working like a clock but you need logic to find what to uptick and what the next minimum value is.基本上像时钟一样工作,但您需要逻辑来找到要上升的内容以及下一个最小值是什么。
Looks like a good problem for recursion.看起来是递归的一个好问题。
Define a function f(prefix, iMin, iMax, n)
, that prints all combinations of n
digits in the range [ iMin
, iMax
] and returns the total number of combinations.定义一个函数
f(prefix, iMin, iMax, n)
,它打印 [ iMin
, iMax
] 范围内n
位数字的所有组合并返回组合的总数。 For n
= 1, it should print every digit from iMin
to iMax
and return iMax - iMin + 1
.对于
n
= 1,它应该打印从iMin
到iMax
每个数字并返回iMax - iMin + 1
。
For your iRange = 5
and n = 3
case, you call f("", 1, 5, 3)
.对于
iRange = 5
和n = 3
情况,您调用f("", 1, 5, 3)
。 The output should be 123 - 124 - 125 - 134 - 135 - 145 - 234 - 235 - 245 - 345
.输出应该是
123 - 124 - 125 - 134 - 135 - 145 - 234 - 235 - 245 - 345
。
Notice that the first group of outputs are simply 1
prefixed onto the outputs of f("", 2, 5, 2)
, ie f("1", 2, 5, 2)
, followed by f("2", 3, 5, 2)
and f("3", 4, 5, 2)
.请注意,第一组输出只是
1
前缀到f("", 2, 5, 2)
,即f("1", 2, 5, 2)
,然后是f("2", 3, 5, 2)
和f("3", 4, 5, 2)
。 See how you would do that with a loop.看看你会如何用循环来做到这一点。 Between this, the case for
n
= 1 above, and traps for bad inputs (best if they print nothing and return 0, it should simplify your loop), you should be able to write f()
.在此之间,上面
n
= 1 的情况,以及错误输入的陷阱(最好是不打印任何内容并返回 0,它应该可以简化您的循环),您应该能够编写f()
。
I'm stopping short because this looks like a homework assignment.我停了下来,因为这看起来像是一项家庭作业。 Is this enough to get you started?
这足以让你开始吗?
EDIT: Just for giggles, I wrote a Python version.编辑:只是为了傻笑,我写了一个 Python 版本。 Python has an easier time throwing around sets and lists of things and staying legible.
Python 可以更轻松地处理事物的集合和列表并保持清晰易读。
#!/usr/bin/env python
def Combos(items, n):
if n <= 0 or len(items) == 0:
return []
if n == 1:
return [[x] for x in items]
result = []
for k in range(len(items) - n + 1):
for s in Combos(items[k+1:], n - 1):
result.append([items[k]] + s)
return result
comb = Combos([str(x) for x in range(1, 6)], 3)
print len(comb), " - ".join(["".join(c) for c in comb])
Note that Combos()
doesn't care about the types of the items in the items
list.请注意,
Combos()
不关心items
列表中项目的类型。
Here's an example of a plain recursive solution.这是一个简单的递归解决方案的例子。 I believe there exists a more optimal implementation if you replace recursion with cycles.
我相信如果您用循环替换递归,则存在更优化的实现。 It could be your homework :)
这可能是你的家庭作业:)
#include <stdio.h>
const int iRange = 9;
const int n = 4;
// A more efficient way to calculate binomial coefficient, in my opinion
int Cnm(int n, int m)
{
int i;
int result = 1;
for (i = m + 1; i <= n; ++i)
result *= i;
for (i = n - m; i > 1; --i)
result /= i;
return result;
}
print_digits(int *digits)
{
int i;
for (i = 0; i < n; ++i) {
printf("%d", digits[i]);
}
printf("\n");
}
void plus_one(int *digits, int index)
{
int i;
// Increment current digit
++digits[index];
// If it is the leftmost digit, run to the right, setup all the others
if (index == 0) {
for (i = 1; i < n; ++i)
digits[i] = digits[i-1] + 1;
}
// step back by one digit recursively
else if (digits[index] > iRange) {
plus_one(digits, index - 1);
}
// otherwise run to the right, setting up other digits, and break the recursion once a digit exceeds iRange
else {
for (i = index + 1; i < n; ++i) {
digits[i] = digits[i-1] + 1;
if (digits[i] > iRange) {
plus_one(digits, i - 1);
break;
}
}
}
}
int main()
{
int i;
int digits[n];
for (i = 0; i < n; ++i) {
digits[i] = i + 1;
}
printf("%d\n\n", Cnm(iRange, n));
// *** This loop has been updated ***
while (digits[0] <= iRange - n + 1) {
print_digits(digits);
plus_one(digits, n - 1);
}
return 0;
}
Here is your code edited :D :D with a recursive solution:这是您使用递归解决方案编辑的代码 :D :D :
#include <iostream>
int iRange=0;
int iN=0; //Number of items taken from iRange, for which u want to print out the combinations
int iTotalCombs=0;
int* pTheRange;
int* pTempRange;
int find_factorial(int n)
{
if ( n<1)
return 1;
else
return find_factorial(n-1)*n;
}
//--->Here is another solution:
void print_out_combinations(int *P, int K, int n_i)
{
if (K == 0)
{
for (int j =iN;j>0;j--)
std::cout<<P[j]<<" ";
std::cout<<std::endl;
}
else
for (int i = n_i; i < iRange; i++)
{
P[K] = pTheRange[i];
print_out_combinations(P, K-1, i+1);
}
}
//Here ends the solution...
int main()
{
std::cout<<"Give the set of items -iRange- = ";
std::cin>>iRange;
std::cout<<"Give the items # -iN- of iRange for which the combinations will be created = ";
std::cin>>iN;
pTheRange = new int[iRange];
for (int i = 0;i<iRange;i++)
{
pTheRange[i]=i+1;
}
pTempRange = new int[iN];
iTotalCombs = (find_factorial(iRange)/(find_factorial(iRange-iN)*find_factorial(iN)));
std::cout<<"The number of possible combinations is: "<<iTotalCombs<<std::endl;
std::cout<<"i.e.the combinations of "<<iN<<" elements drawn from a set of size "<<iRange<<" are: "<<std::endl;
print_out_combinations(pTempRange, iN, 0);
return 0;
}
This is my C++ function with different interface (based on sts::set) but performing the same task:这是我的 C++ 函数,具有不同的接口(基于 sts::set)但执行相同的任务:
typedef std::set<int> NumbersSet;
typedef std::set<NumbersSet> CombinationsSet;
CombinationsSet MakeCombinations(const NumbersSet& numbers, int count)
{
CombinationsSet result;
if (!count) throw std::exception();
if (count == numbers.size())
{
result.insert(NumbersSet(numbers.begin(), numbers.end()));
return result;
}
// combinations with 1 element
if (!(count - 1) || (numbers.size() <= 1))
{
for (auto number = numbers.begin(); number != numbers.end(); ++number)
{
NumbersSet single_combination;
single_combination.insert(*number);
result.insert(single_combination);
}
return result;
}
// Combinations with (count - 1) without current number
int first_num = *numbers.begin();
NumbersSet truncated_numbers = numbers;
truncated_numbers.erase(first_num);
CombinationsSet subcombinations = MakeCombinations(truncated_numbers, count - 1);
for (auto subcombination = subcombinations.begin(); subcombination != subcombinations.end(); ++subcombination)
{
NumbersSet cmb = *subcombination;
// Add current number
cmb.insert(first_num);
result.insert(cmb);
}
// Combinations with (count) without current number
subcombinations = MakeCombinations(truncated_numbers, count);
result.insert(subcombinations.begin(), subcombinations.end());
return result;
}
I created a next_combination()
function similar to next_permutation()
, but valid input is required to make it work我创建了一个类似于
next_permutation()
的next_combination()
函数,但需要有效的输入才能使其工作
//nums should always be in ascending order
vector <int> next_combination(vector<int>nums, int max){
int size = nums.size();
if(nums[size-1]+1<=max){
nums[size-1]++;
return nums;
}else{
if(nums[0] == max - (size -1)){
nums[0] = -1;
return nums;
}
int pos;
int negate = -1;
for(int i = size-2; i>=0; i--){
if(nums[i]+1 <= max + negate){
pos = i;
break;
}
negate --;
}
nums[pos]++;
pos++;
while(pos<size){
nums[pos] = nums[pos-1]+1;
pos++;
}
}
return nums;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.