C ++ Novato necesita ayuda para las combinaciones de impresión de números enteros

StackOverflow https://stackoverflow.com/questions/1876474

  •  18-09-2019
  •  | 
  •  

Pregunta

Supongamos que yo soy dado:

  1. Una gama de enteros iRange (es decir, desde 1 hasta iRange) y
  2. un número deseado de combinaciones

Quiero encontrar el número de todas las combinaciones posibles e imprimir todas estas combinaciones.

Por ejemplo:

Dada : iRange = 5 y n = 3

A continuación, el número de combinaciones es combinaciones iRange! / ((iRange!-n!)*n!) = 5! / (5-3)! * 3! = 10, y la salida es:

123 - 124 - 125 - 134 - 135 - 145 - 234 - 235 - 245 - 345

Otro ejemplo:

Dada : iRange = 4 y n = 2

A continuación, el número de combinaciones es combinaciones iRange! / ((iRange!-n!)*n!) = 4! / (4-2)! * 2! = 6, y la salida es:

12 - 13 - 14 - 23 - 24 - 34

Mi intento hasta ahora es:

#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;   
}

Mi problema: La parte de mi código relacionado con la impresión de las combinaciones sólo funciona para n = 2, iRange = 4 y no puedo hacer que funcione, en general, es decir, para cualquier n y iRange.

¿Fue útil?

Solución

A continuación, se edita el código: D: D con un recursiva Solución:

#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;
}

Otros consejos

Su solución será sólo trabajará para n = 2. Piense acerca del uso de una matriz (peines) con n enteros, entonces el bucle se tick hasta el último elemento de la matriz. Cuando ese elemento alcanza actualización max luego peina [n-2] artículo y establecer el último elemento al valor anterior 1.

Básicamente trabaja como un reloj, pero es necesario lógica para encontrar qué Uptick y lo que el siguiente valor mínimo es.

Parece un buen problema para la recursividad.

Definir un f(prefix, iMin, iMax, n) función, que imprime todas las combinaciones de dígitos n en el rango [iMin, iMax] y devuelve el número total de combinaciones. Para n = 1, se debe imprimir todos los dígitos de iMin a iMax y iMax - iMin + 1 volver.

Para su iRange = 5 y n = 3 caso, se llama a f("", 1, 5, 3). La salida debe ser 123 - 124 - 125 - 134 - 135 - 145 - 234 - 235 - 245 - 345.

Tenga en cuenta que el primer grupo de salidas simplemente se 1 prefijo sobre las salidas de f("", 2, 5, 2), es decir f("1", 2, 5, 2), seguido por f("2", 3, 5, 2) y f("3", 4, 5, 2). Ver cómo se haría eso con un bucle. Entre esto, en el caso de n = 1 anterior, y trampas para los malos entradas (mejor si se imprimen nada y devuelven 0, se debe simplificar su bucle), usted debe ser capaz de escribir f().

Estoy sin llegar porque esto parece una tarea. ¿Es esto suficiente para que pueda empezar?

EDIT: Sólo por diversión, escribí una versión de Python. Python tiene un tiempo más fácil lanzar alrededor de conjuntos y listas de cosas y permanecer legibles.

#!/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])

Tenga en cuenta que Combos() no se preocupa por los tipos de los elementos de la lista items.

Este es un ejemplo de una solución recursiva simple. Creo que existe una aplicación más óptima si se reemplaza la recursividad con ciclos. Podría ser su tarea:)

#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;
}

Esta es mi función de C ++ con interfaz diferente (basado en los pts :: set), sino que realiza la misma tarea:

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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top