Domanda

Supponiamo che ho dato:

  1. Un intervallo di numeri interi iRange (cioèda 1 fino a iRange) e
  2. Un numero di combinazioni

Voglio trovare il numero di tutte le possibili combinazioni e stampare tutte queste combinazioni.

Per esempio:

Dato: iRange = 5 e n = 3

Quindi il numero di combinazioni è iRange! / ((iRange!-n!)*n!) = 5! / (5-3)! * 3! = 10 combinazioni, e l'output è:

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

Un altro esempio:

Dato: iRange = 4 e n = 2

Quindi il numero di combinazioni è iRange! / ((iRange!-n!)*n!) = 4! / (4-2)! * 2! = 6 combinazioni, e l'output è:

12 - 13 - 14 - 23 - 24 - 34

Il mio tentativo, finora, è:

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

Il mio problema: La parte del mio codice in materia di stampa delle combinazioni funziona solo per n = 2, iRange = 4 e io non riesco a farlo funzionare in generale, ossia per qualsiasi n e iRange.

È stato utile?

Soluzione

Ecco il codice modificato :D :D con un ricorsiva soluzione:

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

Altri suggerimenti

La soluzione sarà sempre lavoro per n=2.Pensare di utilizzare un array (pettini) con n numeri interi, allora il ciclo barrare l'ultimo elemento dell'array.Quando la voce raggiunge la max di aggiornamento quindi pettinare[n-2] voce e impostare l'ultimo elemento al valore precedente +1.

Fondamentalmente lavorando come un orologio, ma avete bisogno di logica per trovare ciò che a di rialzo e di quello che la prossima valore minimo è.

Sembra un buon problema per ricorsione.

Definire una funzione f(prefix, iMin, iMax, n), che stampa tutte le combinazioni di n cifre nell'intervallo [iMin, iMax] e restituisce il numero totale di combinazioni.Per n = 1, si deve stampare ogni cifra da iMin per iMax e ritorno iMax - iMin + 1.

Per il vostro iRange = 5 e n = 3 caso, si chiama f("", 1, 5, 3).L'output dovrebbe essere 123 - 124 - 125 - 134 - 135 - 145 - 234 - 235 - 245 - 345.

Si noti che il primo gruppo di uscite sono semplicemente 1 prefisso sulle uscite di f("", 2, 5, 2), cioè f("1", 2, 5, 2), seguita da f("2", 3, 5, 2) e f("3", 4, 5, 2).Vedere come si farebbe con un loop.Tra questo, il caso di n = 1, e trappole per bad ingressi (meglio se si stampa nulla e ritorna 0, dovrebbe semplificare il ciclo), si dovrebbe essere in grado di scrivere f().

Sto fermando breve, perché questo appare come un compito a casa.Questo è sufficiente per iniziare?

EDIT:Solo per un sorriso, ho scritto una versione di Python.Python ha un tempo più facile gettare intorno set e liste di cose e rimanere leggibile.

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

Nota che Combos() non si cura di tipi di elementi in items elenco.

Ecco un esempio di una normale soluzione ricorsiva.Credo che non esiste più un'implementazione ottimale se si sostituisce la ricorsione con cicli.Potrebbe essere il vostro lavoro :)

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

Questa è la mia funzione di C++ con interfaccia diversa (base m::), ma eseguire lo stesso compito:

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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top