Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Kombinacje bez powtórzeń

Ostatnio zmodyfikowano 2020-07-07 21:58
Autor Wiadomość
Yumox
Temat założony przez niniejszego użytkownika
Kombinacje bez powtórzeń
» 2020-07-05 20:49:14
Czytając temat w kursie o zagnieżdżonych pętlach chciałem napisać program, który wypisuje wszystkie możliwe kombinacje liczb bez powtórzeń i żeby dla (przykładowego) zbioru {0,1,2,3} program wypisywał kombinacje: {0,1,2,3} ale też {3,2,1,0}, czyli chce aby liczby się nie powtarzały, ale żeby kolejność miała znaczenie. Wyszedł mi taki program:
C/C++
#include <iostream>
int main()
{
    for( int i = 0; i < 4; i++ )
    {
        for( int j = 0; j < 4; j++ )
        {
            if( i == j )
                 continue;
           
            for( int k = 0; k < 4; k++ )
            {
                if( i == j || i == k || j == k )
                     continue;
               
                for( int l = 0; l < 4; l++ )
                {
                    if( i == j || i == k || j == k || i == l || j == l || k == l )
                         continue;
                   
                    std::cout << i << " " << j << " " << k << " " << l << std::endl;
                }
            }
        }
    }
    return 0;
}
Ale zdaje sobie sprawe, że przy dodaniu jeszcze kilku liczb do tego zbioru, musiałbym dopisywać kolejne porównania w if'ie, a to trochę bezsensowne. Stąd moje pytanie, jak to zrobić łatwiej/krócej?
P-177303
pekfos
» 2020-07-05 21:20:47
Rozważałeś użycie tablicy zamiast nazwanych zmiennych?
P-177304
Yumox
Temat założony przez niniejszego użytkownika
» 2020-07-06 22:32:07
Użyłem tablicy zamiast nazwanych zmiennych i stworzyłem funkcje, przez co program jest uniwersalny:
C/C++
#include <iostream>
bool czyPowtorzono( int tab[], int i )
{
    for( int j = 0; j < i; j++ )
    {
        if( tab[ j ] == tab[ i ] )
             return true;
       
    }
    return false;
}
int main()
{
    int tablica[ 4 ] = { 12, 4, 66, 8 };
    int tab[ 4 ];
    for( tab[ 0 ] = 0; tab[ 0 ] < 4; tab[ 0 ] ++ )
    {
        for( tab[ 1 ] = 0; tab[ 1 ] < 4; tab[ 1 ] ++ )
        {
            if( czyPowtorzono( tab, 1 ) )
                 continue;
           
            for( tab[ 2 ] = 0; tab[ 2 ] < 4; tab[ 2 ] ++ )
            {
                if( czyPowtorzono( tab, 2 ) )
                     continue;
               
                for( tab[ 3 ] = 0; tab[ 3 ] < 4; tab[ 3 ] ++ )
                {
                    if( czyPowtorzono( tab, 3 ) )
                         continue;
                   
                    std::cout << tablica[ tab[ 0 ] ] << " " << tablica[ tab[ 1 ] ] << " " << tablica[ tab[ 2 ] ] << " " << tablica[ tab[ 3 ] ] << std::endl;
                }
            }
        }
    }
    return 0;
}
P-177309
pekfos
» 2020-07-06 23:07:41
Jak chcesz to bardziej skrócić, to sama długość ciągu też może być określana parametrem. Zmienną ilość zagnieżdżeń można uzyskać funkcją rekurencyjną.
P-177310
Yumox
Temat założony przez niniejszego użytkownika
» 2020-07-07 19:43:41
Zrobiłem funkcje rekurencyjną i dodałem możliwość podawania ciągu przez użytkownika dzięki alokacji pamięci, działa dobrze tylko zastanawia mnie czy nie dałoby się zmniejszyć ilości argumentów?
C/C++
#include <iostream>
bool czyPowtorzono( int tab[], int i )
{
    for( int j = 0; j < i; j++ )
    {
        if( tab[ j ] == tab[ i ] )
             return true;
       
    }
    return false;
}
void wypisz( int tablica[], int tab[], int i, int j )
{
    if( j == i )
    {
        for( int k = 0; k < i; k++ )
        {
            std::cout << tablica[ tab[ k ] ] << " ";
        }
        std::cout << std::endl;
        return;
    }
    for( tab[ j ] = 0; tab[ j ] < i; tab[ j ] ++ )
    {
        if( czyPowtorzono( tab, j ) )
             continue;
       
        wypisz( tablica, tab, i, j + 1 );
    }
}
int main()
{
    std::cout << "Wpisz liczby ktorych kombinacje chcesz otrzymac, litera konczy wczytywanie:" << std::endl;
    int i = 0, liczba;
    int * wskaznik = nullptr;
    while( std::cin >> liczba )
    {
        i++;
        int * wsk = new int[ i ];
        for( int j = 0; j < i - 1; j++ )
        {
            wsk[ j ] = wskaznik[ j ];
        }
        wsk[ i - 1 ] = liczba;
        delete[] wskaznik;
        wskaznik = wsk;
    }
    int * tab = new int[ i ];
    wypisz( wskaznik, tab, i, 0 );
    delete[] tab;
    return 0;
}
P-177337
pekfos
» 2020-07-07 19:57:28
Z ilością argumentów się tu nic sensownego nie zrobi. Możesz najwyżej ukryć ostatni z użyciem dodatkowej funkcji, bo to szczegół implementacyjny.
C/C++
void wypisz( int tablica[], int tab[], int i )
{
    wypisz_impl( tablica, tab, i, 0 );
}
P-177339
Yumox
Temat założony przez niniejszego użytkownika
» 2020-07-07 21:58:12
Ok, dzięki :)
P-177344
« 1 »
  Strona 1 z 1