generator kombinacji w języku C (jak zmodyfikować?)

0

Jak mam tablicę taką np.:
lista_pom[0]=12
lista_pom[1]=31
lista_pom[2]=17
lista_pom[3]=43

i chcę aby dla k=1,...n-1 gdzie n w tym przypadku to 4 wpisał mi do tablicy kolejne kombinacje czyli:

dla k=1
tab[0]=12
tab[1]=31
tab[2]=17
tab[3]=43

dla k=2
tab[0]=1231
tab[1]=1217
tab[2]=1243
tab[3]=3117
tab[4]=3143
tab[5]=1743

dla k=3
tab[1]=123117
tab[2]=123143
tab[3]=121743
tab[4]=311743

Coś takiego kombinuję:

void komb(int n, int k, int lista_pom[], int tabSize, int tab[], int j)
{
//przy czym przed wywołaniem funkcji użytkownik musi zadbać aby j=0 i tab[] była wyzerowana
//poza tym dla powyższego przykładu tabSize=4
  int i,o;
  if(k!=0)
  {
    for(i=0;i<n-k+1;i++)
    {
      o=tabSize-n;
      tab[j]=100*tab[j]+lista_pom[i+o];
      komb(n-i-1,k-1,lista_pom,tabSize,tab,j)
    }
  }
  else
  j=j+1;
}

Program dla k=1 działa dobrze (jak się rozpisze na kartce to wydaje się być ok). Dla k=2 zaczyna się knocić w momencie jak zapamiętuje mi tab[0]=1231 i potem mamy j=1 i tab[1]=17 a powinno być 1217. Jednak nie wiem jak spamiętać to 12. Może ktoś by wiedział jak zmodyfikować powyższy kod? 7 dni mi już tylko zostało do końca przedłużonej sesji i jest lekki dramat.
I też druga sprawa to potem będzie mi potrzebne rozwalanie na cyfry tych dużych liczb tzn. np. z 123117 będę musiał zrobić:
lista1[0]=1
lista2[0]=2
lista1[1]=3
lista2[1]=1
lista1[2]=1
lista2[2]=7
Może jest inna droga generowania kombinacji łatwiejsza ale ja jestem beznadziejny i inaczej nie umiem i dlatego to tak wygląda. Też ciężko mi wytłumaczyć po co mi takie coś, bo to jest jakby część pewnego większego projektu związanego z kolorowaniem odpornym. Muszę mieć w tab[] te liczby i potem rozwalać je na cyfry bo potem mam dla każdej kombinacji 300 linijek kodu i ciężko by to było zmieścić w jednej funkcji wszystko zwłaszcza że jestem cienki w programowaniu i nie radzę sobie z trudnymi rzeczami.

0

Albo może od razu by zapamiętywać w postaci tych list tzn. np. dla k=2:
zamiast tab[0]=1231 to:
lista1[0]=1
lista2[0]=2
lista1[1]=3
lista2[1]=1
zamiast tab[1]=1217 to:
lista1[2]=1
lista2[2]=2
lista1[3]=1
lista2[3]=7
itd. bo potem udałoby się w sumie wyselekcjonować grupy kombinacji tych list.
tylko jak teraz ten kod zmodyfikować.

0
#include <iostream>
#include <string>
#include <list>

//idea: dla k=1 zwracamy oryginalny zestaw
//dla k>1, najpierw generujemy zestaw k-1 i dalej..
//dla kazdej z oryginalnych czastek:
//  dla kazdego wyniku z zestawuK-1:
//    jesli ow wynik nie zawiera jeszcze tego fragmentu, to doklejamy fragment na jego poczatek
//    a jesli zawiera - wywalamy ten wynik z zestawuK-1 (zeby bylo bez powtorzen, tzn.
//    majac k-1: {..12.., ..31.., ..17.. } i aktualny prefix 12 wygeneruja sie 12..31.. i 12..17..,
//    a '..12..' wyrzucamy z wynikow k-1, zeby przy dalszym przegladaniu innych prefixow (np. 31 czy 17)
//    nie wygenerowac ponownie juz istniejacej pary (31..12../17..12.. -- bo 12+31 i 12+17 teraz doszlo)
//no i zwrocic kolekcje posklejanych nowych kombinacji
std::list<std::string> komb(std::list<std::string> const & parts, size_t k)
{   using namespace std;

    if(k==1)
        return parts;

    list<string> sub_kombs = komb(parts, k-1);
    list<string> result;
    for(list<string>::const_iterator it_prefix = parts.begin(); it_prefix!=parts.end(); ++it_prefix)
    {   for(list<string>::iterator it_sub = sub_kombs.begin(); it_sub!=sub_kombs.end(); )
            if( (*it_sub).find(*it_prefix) == string::npos)
                result.push_back(*it_prefix + *it_sub++);
            else
                it_sub = sub_kombs.erase(it_sub);
    }

    return result;
}

//idea: przejrzec wszystkie otrzymane napisy
//z kazdego napisu brac po kolei po dwie cyfry
//pierwsza wrzucac na liste1, druga - na liste2
//zwrocic obie listy
std::pair<std::list<char>, std::list<char> > split(std::list<std::string> const & numbers)
{   using namespace std;

    pair<list<char>, list<char> > digits;
    for(list<string>::const_iterator it_number = numbers.begin(); it_number!=numbers.end(); ++it_number)
        for(string::const_iterator it_digit = (*it_number).begin(); it_digit!=(*it_number).end(); )
        {   digits.first.push_back(*it_digit++);
            digits.second.push_back(*it_digit++);
        }

    return digits;
}

int main()
{   using namespace std;

    list<string> parts;
    parts.push_back("12");
    parts.push_back("31");
    parts.push_back("17");
    parts.push_back("43");

    list<string> tab = komb(parts, 1);

    for(list<string>::const_iterator it = tab.begin(); it!=tab.end(); ++it)
        cout << *it << endl;

    pair<list<char>, list<char> > digits = split(tab);

    {   size_t i = 0;
        for(list<char>::const_iterator it = digits.first.begin(); it!=digits.first.end(); ++it)
            cout << "lista1[" << i++ << "] = " << *it << endl;
    }

    {   size_t i = 0;
        for(list<char>::const_iterator it = digits.second.begin(); it!=digits.second.end(); ++it)
            cout << "lista2[" << i++ << "] = " << *it << endl;
    }
}

pisane w C++ dla mojej wygody, przerobienie na C jest banalne, milej zabawy;)
disclaimer: ani to male pamieciowo, ani to szybkie, ani ladne. ale dziala i latwo zrozumiec jak dziala.

0

Niestety c++ nie umiem (tylko co to cout wiem co to jest ale jakieś std:: czy jakieś cośtam.begin w ogóle ten kod to dla mnie jak po chińsku napisane) ale i tak dzięki, może sie komuś przyda kiedyś, wysiłek nie poszedł na marne żeby Cie nie denerwować, że się napracowałeś a nic z tego nie wykorzystam. Następnym razem będę zamieszczał dokładniej informacje, że czy ktoś umie zrobić za pomocą prostych, typowych funkcji a nie jakichś kosmosów.:)

//q:przypiecie do autora

0

Kurcze ale sam nie wymyślę to jak możesz to napisz co znaczą poniższe zwroty:
std::liststd::string komb(std::liststd::string const & parts, size_t k)
using namespace std
list<string> sub_kombs = komb(parts, k-1)
list<string> result
for(list<string>::const_iterator it_prefix = parts.begin(); it_prefix!=parts.end(); ++it_prefix)
for(list<string>::iterator it_sub = sub_kombs.begin(); it_sub!=sub_kombs.end(); )
( (*it_sub).find(*it_prefix) == string::npos)
result.push_back(*it_prefix + *it_sub++)
it_sub = sub_kombs.erase(it_sub)
chociaż nie no to nic nie da, bo napiszesz tak, że pewnie i tak nie zrozumiem o co chodzi. A nie da się tego powyższego kodu jakoś sprowadzić to zapisu gdzie będą występowały tylko proste funkcje np. for, tabele jakieś, jakieś takie rzeczy proste co na poziomie gimnazjum są bo na takim poziomie jest u mnie znajomość języka C. Z trudniejszych rzeczy to znam tylko malloc czy struktury.

//q:przypiecie do autora

0

std::list<std::string> komb(std::list<std::string> const & parts, size_t k)
sygnaturka funkcji.
pobiera liste ciagow znakow oraz liczbe
zwraca liste ciagow znakow

using namespace std
nie istotne.

list<string> sub_kombs = komb(parts, k-1)
tymczasowa lista ciagow znakow = komb(parts, k-1).. wywolanie rekurencyjne funkcji i zwrot, rozumiesz..

list<string> result
druga tymczasowa lista ciagow znakow -- ta ktora bezdie zwrocona z funkcji

for(list<string>::const_iterator it_prefix = parts.begin(); it_prefix!=parts.end(); ++it_prefix)
to jest petla przegladajaca kolejno wszystkie elementy z listy "PARTS". zmienną IT_PREFIX mozesz rozumiec jako wskaznik-na-aktualnie-ogladany-element-tej-listy. ++/-- na IT_PREFIX sluzy do przewijania w przod/wtyl

for(list<string>::iterator it_sub = sub_kombs.begin(); it_sub!=sub_kombs.end(); )
analogiczna petla przegladajaca zawartosc listy "SUB_KOMBS". zmienną IT_SUB mozesz rozumiec jako wskaznik-na-aktualnie-ogladany-element-tej-listy. ++/-- na IT_SUB sluzy do przewijania w przod/wtyl. zwroc uwage na brak auto-przesuniecia (3czlon for)

( (*it_sub).find(*it_prefix) == string::npos)
wez aktualny element z SUB_KOMBS (napis, wskazywany przez IT_SUB) i sprawdz na jakim w nim miejscu wystepuje aktualny element z PARTS (napis, wskazywany przez IT_PREFIX). string::npos oznacza nieodnalezienie pozycji, czyli lacznie to jest test czy *itsub NIE ZAWIERA *itprefix

result.push_back(*it_prefix + *it_sub++)
wsadz na koniec listy RESULTS wynik sklejenia aktualnego elementu PARTS oraz aktualnego elementu SUB_KOMBS. przesun 'wskaznik' IT_SUB o oczko do przodu

it_sub = sub_kombs.erase(it_sub)
wywal z listy SUB_KOMBS element aktualnie ogladany, po operacji ustaw IT_SUB na element ktory byl na liscie tuz-po tym usunietym

hym.. szczerze mowiac, da sie to przetlumaczyc na same tablice i malloc'i.. ale mimo wszystko radzil bym uzyc przynajniej list.. jesli chesz tlumaczyc na tablice, to:
list<string> ---> char * * [dyna.-dyna. tablica ciagow znakow]
list<char> ---> char* [dyna. tablica znakow]
pair<list<char>, list<char>> ---> struct {char*; char*};
*it_prefix, *it_sub --> int i, j; a potem parts[i], subkombs[j]
begin, end ---> 0 i aktualna dlugosc tablicy
find ---> strstr
npos --> -1 (chyba, sprawdz w manualu strstr)
pushback --> powieksz tablice o 1, dopisz na koniec
erase --> usun z tablicy, zmiejsz tablice o 1

0

No dajcie spokój, kolejne kombinacje przecież banalnie wygenerować. Idea jest tak jak przedstawił quetzalcoatl, jednak nie musi być taka zagmatwana: dla każdego z pierwszych n-k-1 elementów zbioru wykonuj: dołóż ten element na koniec kombinacji i generuj kombinacje dalej dla podzbioru elementów leżących za tym elementem. Dzięki temu 'za' automatycznie unikniemy powtórzeń. Dzięki rekurencji unikniemy dodatkowych list.
Podam przykład dla zbioru kolejnych liczb naturalnych od 0, w praktyce trzeba będzie je użyć jako indeksy tablicy.

#include <stdio.h>
#include <stdlib.h>

int *kombinacja;

//'podzbior' - indeks podzbioru, okresla ile
//elementów kombinacji zostalo juz przydzilone
//'pozycja' - indeks ostatnio przydzielonego do kombinacji elementu + 1,
//okresla wielkosc podzbioru pozostalych elementow rowna 'n-pozycja'

void nastepna(int n, int k, int podzbior, int pozycja)
{
   int stop;

   if(podzbior == k) 
   {
      //tutaj mamy juz cala kombinacje gdyz zostalo do niej przydzilone 'k' elementow,
      //dla przykładu wypisze ja na ekran, jednak ty bedziesz musial uzyc tych liczb jako 
      //indeksy tablicy z lancuchcami i zlozyc wskazywane lancuchy w jeden
      for(int i = 0; i < k; i++) printf("%d ", kombinacja[i]);
      printf("\n");
   }
   else
   {
      //wybieramy jeden z elementow podzbioru tak, aby za nim pozostalo przynajmniej
      //'k-poziom-1' elementow, tak aby nie zabraklo elementow dla kombinacji
      stop = n-(k-podzbior);
      for(int i = pozycja; i <= stop; )
      {
         //przydzielamy wybrany element do kombinacji
         kombinacja[podzbior] = i;
         //i rekurencyjnie kontynuujemuy 'kombinowanie' ;) dla dalszych elementow
         nastepna(n, k, podzbior + 1, ++i);
      }
}

void kombinacje(int n, int k)
{
   kombinacja = malloc(sizeof(int) * k);
   nastepna(n, k, 0, 0);
   free(kombinacja);
}

int main(int argc, char* argv[])
{
   kombinacje(5, 3);
   system("PAUSE");
   return 0;
}
0

jesli dobrze widze, to generalnie robisz to ta sama metoda, tylko ja robie od tylu i na listach i ciagach, a Ty od przodu i na liczbach i tablicy:) napisalem tak jak jest zgodnie z disclaimerem: mialo byc maksymalnie łopatologicznie;p

0

Dzięki za pomoc ale i tak nic z tego nie rozumiem, jakoś będę kombinował chociaż najchętniej to bym samobójstwo popełnił bo już mam tego [CIACH!] programu <ort>pod tąd</ort>.

//q:przypiecie do autora, cenzura

0

Masz wszystko na tacy. Mam nadzieje, że potrafisz fragment wyświetlający kombinację

for(int i = 0; i < k; i++) printf("%d ", kombinacja[i]);

zamienić na to co potrzebujesz ?

Co do samego algorytmu przedstawię jego przebieg jednej z kombinacji. Np. dla n=6, k=3, kobinujemy liczby 0,1,2,3,4, przedstawię przebieg dla kombinacji 2,4,5

Na początku wywołane jest

nastepna(n, k, 0, 0);

podzbior=0 czyli nie mamy jeszcze żadnych liczb w naszej docelowo 3 elementowej kombinacji,
pozycja=0 czyli nasz podzbiór z którego wybieramy liczby obejmuje cały zbiór.
stop=n-(k-podzbior)=n-k=3, czyli wybieramy sobie jedną z liczb 0,1,2 lub 3. Dlaczego tak ? a no dla tego, że za każdą z tych liczb stoją przynajmniej jeszcze 2 (za 3 stoi 4 i 5). Muszą zostać przynajmniej 2 liczby bo tyle liczb jeszcze brakuje do pełnej 3 elementowej kombinacji.
W pętli od i=0 do 3 liczba 'i' jest wybierana jako pierwszy element kombinacji

kombinacja[podzbior] = i;

Krok wykonywany jest dla każdego 'i', my prześledźmy przebieg dla 'i'=2, czyli na początek tablicy 'kombinacja' wskakuje dwójka (kombinacja[0]=2).
I w tym momencie musimy zrobić takie coś: nasza kombinacja składa się już z jednego elementu (dwójki), dokładamy do niej 2-elementowe kobinacje z pozostałych elementów (3, 4, 5).
Teraz jest wywoływane

nastepna(n, k, podzbior + 1, ++i);

podzbior=podzbior+1 (=1) oznacza, że wybraliśmy już jeden element i pozostało do wybrania jeszcze k-podzbior=3-1=2
pozycja=++i (=3) oznacza, że ostatnio wybraliśmy dwójkę i do dalszego wybierania zostały liczby >=3
teraz gdy dobierzemy drugi element do kombinacji zostanie jeszcze jeden, dlatego teraz stop=n-(k-podzbior)=6-2=4, za 4 stoi już tylko jeden element 5 - wystarczy.
Pętla przebiega od i=3 do 5, przykładowo prześledźmy co się stanie przy i=4.
Czwórka zostanie dołożona na drugie miejsce kombinacji

kombinacja[podzbior] = i;

czyli kombinacja[1]=4. Tablica kombinacji jest wypełniona 2 liczbami: 2 i 4. Zostało dołożyć jeszcze jedną liczbę z pozostałych. Wywoływane jest nastepna(n, k, podzbior + 1, ++i);

czyli nastepna(n, k, 2, 5).
stop=n-(k-poziom)=6-(3-2)=5
Pętla od i=5 do 5. Wybieramy piątkę i dokładamy na koniec kombinacji, która składa teraz się z liczb 2,4,5.
Wywoływana jest rekurencja nastepna(n, k, 3, 6), gdzie podzbior=3=k co oznacza, że mamy pełną 3-elementową kombinację i możemy z niej skorzystać: 
```cpp
if(k==podzbior) ...
0

Chciałbym stworzyć funkcję w JĘZYKU Cktóra będzie takim jakby generatorem kombinacji tzn. np. będzie robiła to:
dla k=1:
lista3[0]=lista1[0]
lista4[0]=lista2[0]

lista3[1]=lista1[1]
lista4[1]=lista2[1]

lista3[2]=lista1[2]
lista4[2]=lista2[2]

lista3[3]=lista1[3]
lista4[3]=lista2[3]

dla k=2:
lista3[0]=lista1[0]
lista4[0]=lista2[0]
lista3[1]=lista1[1]
lista4[1]=lista2[1]

lista3[2]=lista1[0]
lista4[2]=lista2[0]
lista3[3]=lista1[2]
lista4[3]=lista2[2]

lista3[4]=lista1[0]
lista4[4]=lista2[0]
lista3[5]=lista1[3]
lista4[5]=lista2[3]

lista3[6]=lista1[1]
lista4[6]=lista2[1]
lista3[7]=lista1[2]
lista4[7]=lista2[2]

lista3[8]=lista1[1]
lista4[8]=lista2[1]
lista3[9]=lista1[3]
lista4[9]=lista2[3]

lista3[10]=lista1[2]
lista4[10]=lista2[2]
lista3[11]=lista1[3]
lista4[11]=lista2[3]

dla k=3
lista3[0]=lista1[0]
lista4[0]=lista2[0]
lista3[1]=lista1[1]
lista4[1]=lista2[1]
lista3[2]=lista1[2]
lista4[2]=lista2[2]

lista3[3]=lista1[0]
lista4[3]=lista2[0]
lista3[4]=lista1[1]
lista4[4]=lista2[1]
lista3[5]=lista1[3]
lista4[5]=lista2[3]

lista3[6]=lista1[1]
lista4[6]=lista2[1]
lista3[7]=lista1[2]
lista4[7]=lista2[2]
lista3[8]=lista1[3]
lista4[8]=lista2[3]

czyli lista1[] i lista2[] to parametry wejściowe funkcji a lista3[] i lista4[] to jakby wyjściowe.
lista1[],lista2[],lista3[],lista4[] to są zadeklarowane na początku domyślnie z pewnym zapasem jako int listax[100]. Broń boże nie przez żadne malloci.
No i coś takiego stworzyłem, ale nie działa za bardzo, jak sobie na kartce rozpisuje to dla k>3 zaczyna się knocić:(

void komb(int n, int k, int y, int lista1, int lista2, int j, int c, int p, int r)
{
  int i,o;

  if(k!=0)
  {
    for(i=0;i<n-k+1;i++)
    {
      o=y-n;
      lista3[j]=lista1[i+o];
      lista4[j]=lista2[i+o];
      j=j+1;
      if((c!=0)&&(k!=1))
      {
        lista3[j]=lista3[r];
        lista4[j]=lista4[r];
        j=j+1;
      }
      if((k!=1)&&(p==0))
      {
        c=1;
        r=i;
        p=1;
      }
      komb(n-i-1,k-1,y,lista1,lista2,j,c,p,r)
      if(k>1)
      {
        c=0;
        p=0;
        j=j-1;
      }
    }
  }

}

ale czy ktoś mógłby podążyć moją ideą i tak tą powyższą funkcję zmodyfikować, aby przynajmniej do k=8 działało? i też za bardzo nie wiem jak nazwę funkcji zrobić, bo tam trzeba jeszcze lista3 i lista4 wstawić, również c,p,r to chyba zwracane argumenty, również jak zapisać jako argument lista1 czy *lista1 jak to w gruncie rzeczy tabela 1-wymarowa??? Od pół roku dopiero programuję w C i mam taki głupi przedmiot co gość cudów wymaga, bo myśli, że my umiemy programować w C. Ta funkcja jest mi potrzebna bo bez niej nie mogę ukończyć programu w C, który już mam na jakieś 700 linijek (kolorowanie odporne)i aż płakać się chce bo tyle godzin się siedziało i nie da rady zrobić bo nie mogę sobie z generetorem kombinacji poradzić, więc wszystko na marne, bo też nie pójdę do niego z tym co mam, bo jemu ciężko zrozumieć że można po prostu w czymś nie dać rady, siedzieć i nie dać rady, taki to oporny człowiek.

edit: skleilem watki..

0

parametry 'zwracajace' wartosc z powrotem musisz przekazac poprzez wskaznik, czyli np. int*j i wszedzie pisac j zeby odczytac/zapisac do nich
'listy', czyli tablice 1D, przekazesz tez jako int
.. ogolnie, o ile dobrze zrozumialem opis:

void komb(int n, int k, int y, int* lista1, int* lista2, int* j, int* c, int* p, int* r, int* lista3, int* lista4)

a teraz do rzeczy..

co oznacza n?
co oznacza k?
co oznacza y?
co oznacza j?
co oznacza c?
co oznacza p?
co oznacza r?

bo wróżkami nie jestesmy..
..poza tym sprobowalbys zrozumiec co adf88 napisal..

0

Zaczaiłem tą pętlę tylko teraz jak dostosować ją do moich potrzeb z lista1,lista2,lista3,lista4 czyli to o czym pisałem w ostatnim moim poście, przypomnę:
np. niech dane wejściowe będą:
lista1[0]=1
lista2[0]=1
lista1[1]=2
lista2[1]=9
lista1[2]=5
lista2[2]=2
lista1[3]=4
lista1[3]=6
to chcę np. dla k=2 dostać:
lista3[0]=1
lista4[0]=1
lista3[1]=2
lista4[1]=9

lista3[2]=1
lista4[2]=1
lista3[3]=5
lista4[3]=2

lista3[4]=1
lista4[4]=1
lista3[5]=4
lista4[5]=6

lista3[6]=2
lista4[6]=9
lista3[7]=5
lista4[7]=2

lista3[8]=2
lista4[8]=9
lista3[9]=4
lista4[9]=6

lista3[10]=5
lista4[10]=2
lista3[11]=4
lista4[11]=6

Przerobiłem do swoich potrzeb tą funkcję, ale nie wiem jak teraz w nazwie funkcji postapić z parametrami takimi jak lista1,lista2,lista3,lista4,y??? y oznacza wzrastający indeks (np. w przykładzie wyżej byłby od 0 do 11) Czy tak jest dobrze jak poniżej?

void nastepna(int n, int k, int podzbior, int pozycja, int y, int *lista1, int *lista2, int *lista3, int *lista4)
{
int kombinacja1[100], kombinacja2[100],i; //z zapasem pewnym deklaruję zmienną tablicową
   
  if(podzbior == k) 
   {
    for(i=0;i<k;i++)
       {
        lista3[y]=kombinacja1[i];
        lista4[y]=kombinacja2[i];
        y=y+1;
       }
   }

   int stop = n-(k-podzbior);
   for(i = pozycja; i <= stop; )
   {
       kombinacja1[podzbior]=lista1[i];
       kombinacja2[podzbior]=lista2[i];
       nastepna(n, k, podzbior + 1, ++i,y, *lista1, *lista2, *lista3, *lista4);
   }
}

przed pierwszym wywołaniem funkcji zakłada się że uzytkownik sam musi zadbać o to, aby y=0 było.

0

Pisałem żebyś użył liczb z tablicy 'kombinacja' jako indeksy innej tablicy, broń boże nie można do niej nic innego wpisywać:

void nastepna(int n, int k, int podzbior, int pozycja, int *y, int *lista1, int *lista2, int *lista3, int *lista4)
{
   //'y' okreslia odstep od ostatniej kombinacji, tj. y = 0, k, 2k, 3k, ...
   //kolejne kombinacje zapisywane sa za 'y', tak aby nie nalozly sie na siebie
   //algorytm nie tylko idzie rekurencyjnie w glab, ale rowniez kozysta 
   //z powrotow (tzw. backtrack) i po takim powrocie y nie moze wrocic do swojej 
   //dawnej wartosci, dlatego musi byc przekazywane przez referencje (tu 
   //dokladnie przez wskaznik). Raz zmodyfikowane 'y' musi zostac zapamietane. 

   //'y' zamiast byc przekazywane przez referencje moze byc zmienna globalna
   //identycznie jak komorki tablicy 'kombinacja', które też mogą być 
   //przekazywane przez referencje (wskaźnik)

   int i;
   if(podzbior == k)
   {
      for(i = 0; i < k; i++)
      {
         //bierzemy liczby z tablicy 'kobinacja' i, uzywamy je jako indeksy 
         //dla innych tablic. kombinacja zapisywana jest z odstepem '*y'
         lista3[*y + i] = lista1[kombinacja[i]];
         lista4[*y + i] = lista2[kombinacja[i]];
      }
      //po zapisaniu kobinacji zwiekszamy '*y' o 'k', aby 
      //nastepna kombinacja byla zapisana za poprzednia
      *y = *y + k;
      
      //nie opuszczaj 'return' !, zamiast niego może byc 'else' po if'ie                  
   }
   else
   { 
      int stop = n-(k-podzbior);
      for(i = pozycja; i <= stop; )
      {
         kombinacja[podzbior] = i;
         nastepna(n, k, podzbior + 1, ++i);
      }
   }
}

//...

int y = 0;
nastepna(..., &y, ...);
0

Masa błędów mi do funkcji wyskakuje no więc zmieniłem postać mojej funkcji na taką (dodałem wszędzie znak "_" myśląc że może to coś zmieni:

 void TSDIAppForm::void nastepna(int n_, int k_, int podzbior, int pozycja, int *y_, int *lista1_, int *lista2_, int *lista3_, int *lista4_)
{
   int i,kombinacja[100];
   if(podzbior == k_)
   {
      for(i = 0; i < k_; i++)
      {
         lista3[*y_ + i] = lista1[kombinacja[i]];
         lista4[*y_ + i] = lista2[kombinacja[i]];
      }
      *y_ = *y_ + k_;
   }
   else
   {
      int stop = n_-(k_-podzbior);
      for(i = pozycja; i <= stop; i++)
      {
         kombinacja[podzbior] = i;
         nastepna(n_, k_, podzbior + 1, ++i, *y_,*lista1_,*lista2_,*lista3_,*lista4_);
      }
   }
}

tak aby żadna ze zmiennych co są w parametrach nie pokryła się ze zmiennymi występującymi w programie. No a w programie wywołuję funkcję tak:
nastepna(y,k,0,0,&h,*lista1,*lista2,*lista3,lista4);
gdzie zmienne poszególne są jako globalne i są tak zadeklarowane:
int y, k, lista1[100], lista2[100], lista3[100], lista4[100]; //y pełni rolę n_
int h=0; //h tu pełni role y_
no i takie błędy się pojawiają:
1.)cannot convert int to int

2.)type mismatch in parameter lista1_ in call to 'TSDIAppForm::nastepna(int,int,int,int,int *,int *,int *,int *)'
i takie same 2 kominikaty się powtarzają jeszcze 3 razy odpowiednio do "lista2_", "lista3_" i "lista4_". No i w sumie się nie dziwie bo to nie są wskaźniki u mnie tylko tablice a nie wskaźniki, więc jakoś inaczej je chyba trzeba.
No i jeszcze jeden błąd wyskakuje do tego:
void TSDIAppForm::void nastepna(int n_, int k_, int podzbior, int pozycja, int *y_, int *lista1_, int *lista2_, int *lista3_, int *lista4_)
taki:
Identifier expected.
No a tu nie wiem co jest nie tak. Musi być void TSDIAppForm:: bo np. przy definicji silni jak dałem:
int TSDIAppForm::silnia(int liczba) to było ok. Chyba że może jak jest typ void to u góry zauważyłem że jest zawsze np.:
void __fastcall TSDIAppForm::OpenItemClick(TObject *Sender)
czyli występuje słowo __fastcall cokolwiek ono znaczy (to nie ja tworzyłem tylko borlanda buildera używam i on automatycznie tworzy takie funkcje) no i zawsze jak jest void to jest i potem __fastcall. Więc może by ten __fastcall dać i będzie ok.

Aha i w SDIMain.h dodałem funkcję do publicznych:

//----------------------------------------------------------------------------
#ifndef SDIMainH
#define SDIMainH
//----------------------------------------------------------------------------
#include <vcl\ComCtrls.hpp>
#include <vcl\ExtCtrls.hpp>
#include <vcl\Buttons.hpp>
#include <vcl\StdCtrls.hpp>
#include <vcl\Dialogs.hpp>
#include <vcl\Menus.hpp>
#include <vcl\Controls.hpp>
#include <vcl\Forms.hpp>
#include <vcl\Graphics.hpp>
#include <vcl\Classes.hpp>
#include <vcl\Windows.hpp>
#include <vcl\System.hpp>
//----------------------------------------------------------------------------

class TSDIAppForm : public TForm
{
__published:
	TMainMenu *MainMenu;
	TMenuItem *FileMenu;
	TMenuItem *OpenItem;
	TMenuItem *SaveItem;
	TMenuItem *ExitItem;
	TMenuItem *N1;
	TOpenDialog *OpenDialog;
	TSaveDialog *SaveDialog;
	TMenuItem *Help1;
	TMenuItem *About1;
	TPanel *SpeedPanel;
	TSpeedButton *OpenBtn;
	TSpeedButton *SaveBtn;
	TSpeedButton *ExitBtn;
	TStatusBar *StatusBar;
	TMemo *Memo1;
	TMenuItem *Autor1;
	void __fastcall ShowHint(TObject *Sender);
	void __fastcall ExitItemClick(TObject *Sender);
	void __fastcall OpenItemClick(TObject *Sender);
	void __fastcall SaveItemClick(TObject *Sender);

	void __fastcall FormCreate(TObject *Sender);



	void __fastcall Autor1Click(TObject *Sender);

private:
public:
	virtual __fastcall TSDIAppForm(TComponent *AOwner);
    int silnia(int liczba);
    void nastepna(int n_, int k_, int podzbior, int pozycja, int *y_, int *lista1_, int *lista2_, int *lista3_, int *lista4_);
};
//----------------------------------------------------------------------------
extern TSDIAppForm *SDIAppForm;
//----------------------------------------------------------------------------
#endif
0

Zapomniałem tu znaczka dodać "_" ale i tak to nic nie zmieniło, takie same komunikaty:

lista3_[*y_ + i] = lista1_[kombinacja[i]];
lista4_[*y_ + i] = lista2_[kombinacja[i]];

I wie może ktoś czy da się tą pętle naprawić czy może od nowa trzeba tworzyć inny sposób generacji kombinacji? W poniedziałek musze oddać cały projekt i coś czuję, że skończy się na tym, że sobie sam wpisze do lista3 i lista4 kolejne kombinacje i nauczycielowi pokarzę tą funkcję i powiem, że po prostu niby powinna działać, wydaje się byc ok, a nie działa.
Powiem, że na forach się pytałem różnych, bo i na elektrodzie też i tam też nikt nie wie , w ogóle to nikt w Polsce nie wie jak zrobić generator kombinacji, więc dlatego żeby pokazać, że program jest ok tylko brakuje fragmentu z generowaniem kombinacji, no to sam pouzupełniam dla jakiegoś szczególnego przypadku te listy3 i listy4 no i może uzna jakoś. A ten niedziałający fragment z ta funckją też zamieszczę w sprawozdaniu. Ale to jest naprawdę żenada, że w języku C nie da się zrobić czegoś takiego. Język C jest po prostu beznadziejny. W tym nie da się programować nic. Może wymyslą jakieś cos kiedyś przystępniejszego, ale programiści zrobia wreszcie jakieś kompilatory w miare dobre chociaz jak tyle lat i nie zrobili to raczej trzeba nowe programowanie stworzyć, bo widocznie C jest już wyczerpane i nic więcej się nie da wycisnąć. Żenada.:(

0

zamiar opierdalac jezyk istniejacy na rynku, zacznij myslec. adf88 juz Ci podal rozwiazanie, ktore tylko lekko trzeba przerobic. Ja Ci podalem rozwiazanie nieladne, ale proste i dzialajace, wystarczylo przetlumaczyc.. nawet mowilismy jak to zrobic. W C da sie zrobic wszystko, nie jest wyczerpany. Cos przystepniejszego? juz jest! nazywa sie C++ i w tym wlasnie moj kod napisalem. I sa nawet jeszcze bardziej przystepne jezyki! dlaczego do ciemnej śrubki uparłes sie na łatanie tej kaszany która tutaj zamiesciles na poczatku? wszyscy Ci od razu powiedzieli: nie tedy droga. Zmarnowales kupe czasu na łatanie tego, zamiast pomyslec nad rozwiazaniami ktore dostales na tacy. UPS. Przewaliles. I co teraz? chcesz nas wziac na litosc zeby ktos dał Ci gotowca?

edit:

anderson21 napisał(a)

class TSDIAppForm : public TForm

poza tym do jasnej cholery TY PISZESZ W C++ A NIE W C !!!!!!!!!!!!!!!!!!!!!!!!

0
anderson21___________ napisał(a)

Może wymyslą jakieś cos kiedyś przystępniejszego, ale programiści zrobia wreszcie jakieś kompilatory w miare dobre chociaz jak tyle lat i nie zrobili to raczej trzeba nowe programowanie stworzyć, bo widocznie C jest już wyczerpane i nic więcej się nie da wycisnąć. Żenada.:(

Chwala za to, ze nowe jezyki nie powstaja za kazdym razem, kiedy ktos nie umie czytac ze zrozumiem badz woli gotowca, bo bysmy mieli zatrzesienie klonow C/C++, ktore i tak dzialalaby jak oryginaly :P

0

Heh toteż zaprzestałem roboty nad moim sposobem i wziąłem sposób adf88 i nie działa. I dlatego uważam, że programowanie w C jest porażkowe i trzeba nowych języków, bo wydaje się, że wszystko jest dobrze w funkcji, którą adf88 zrobił a mimo to nie działa. Toteż przerobiłem troszkę sposób adf88 (potraktowałem argumenty jako nie wskaźniki tylko zmienne), ale nie też nie działa. Nawet oddzielny program jakiś prosty zrobiłem w wx-dev żeby wykluczyć że może jakis błąd spowodowany konfliktem jakichś oznaczeń z resztą kodu w moim programie a funkcja jest ok, ale nie, jednak coś jest nie tak już nie wiem z czym, bo wydaje się, że w funkcji jest wszystko dobrze, to pewnie jakiś grymas języka C - czegoś się czepia.
W C+ nie programuje bo nie umiem tego języka i dlatego się nie zabieram, ale dotychczas 700 linijek które napisałem to w języku C działało to tej funkcji nagle nie może w języku C Borland Builder zinterpretować? jak dotychczas wszystko dobrze zinterpretował.

Jak tak wywołuję funkcję w programie:

nastepna(y,k,0,0,&h,lista1,lista2,lista3,lista4);

przy tych wszystkich oznaczeniach o których pisałem wcześniej czyli deklaracji zmiennych:

int lista1[100], lista2[100], lista3[100], lista4[100];
int h=0;

to przy definicji funkcji, która Adf88 podał:

void TSDIAppForm::void nastepna(int n_, int k_, int podzbior, int pozycja, int *y_, int *lista1_, int *lista2_, int *lista3_, int *lista4_)
{
   int i,kombinacja[100];
   if(podzbior == k_)
   {
      for(i = 0; i < k_; i++)
      {
         lista3_[*y_ + i] = lista1_[kombinacja[i]];
         lista4_[*y_ + i] = lista2_[kombinacja[i]];
      }
      *y_ = *y_ + k_;
   }
   else
   {
      int stop = n_-(k_-podzbior);
      for(i = pozycja; i <= stop; i++)
      {
         kombinacja[podzbior] = i;
         nastepna(n_, k_, podzbior + 1, ++i, *y_,*lista1_,*lista2_,*lista3_,*lista4_);
      }
   }
}

a ja dopisałem tylko: "void TSDIAppForm::" oraz pododawałem znaczki "_" to wyskakuje tylko błąd:

void TSDIAppForm::void nastepna(int n_, int k_, int podzbior, int pozycja, int *y_, int *lista1_, int *lista2_, int *lista3_, int *lista4_)
identifier expected  i
declaration termineted incorrectly

a tamte, które poprzednio wyskakiwały z niemożnością przerobienia int na int* już nie wyskakują. Aczkolwiek czuję, że nawet jak się jakims cudem usunie te błędy, nie będą wyskakiwały to i tak może nie działać nawet jak przejdzie kompilację, bo przy stworzonym oddzielnie pewnym prostym programie, żeby zobaczyć czy funkcja działa, no to mimo przejścia kompilacji nie wykonywał się program no ale tym to bym chciał się martwić jak się z powyższym bieżącym problemem by udało uporać.

0
anders21 napisał(a)

Ale to jest naprawdę żenada, że w języku C nie da się zrobić czegoś takiego. Język C jest po prostu beznadziejny. W tym nie da się programować nic. Może wymyslą (...blablabla)
I dlatego uważam, że programowanie w C jest porażkowe i trzeba nowych języków, bo wydaje się, że wszystko jest dobrze w funkcji (...blablabla)

"A bad workman allways blames his tools"

http://pastebin.4programmers.net/3719
http://pastebin.4programmers.net/3718

anders21 napisał(a)

void TSDIAppForm::void nastepna(int n....

a to tylko potwierdza mądrość przyslowia..

0

No rzeczywiście 2x void tam było. Teraz przeszło kompilację przy takiej funkcji:

void TSDIAppForm:: nastepna(int n_, int k_, int podzbior, int pozycja, int *y_, int *lista1_, int *lista2_, int *lista3_, int *lista4_)
{
   int i,kombinacja[100];
   if(podzbior == k_)
   {
      for(i = 0; i < k_; i++)
      {
         lista3_[*y_ + i] = lista1_[kombinacja[i]];
         lista4_[*y_ + i] = lista2_[kombinacja[i]];
      }
      *y_ = *y_ + k_;
   }
   else
   {
      int stop = n_-(k_-podzbior);
      for(i = pozycja; i <= stop; i++)
      {
         kombinacja[podzbior] = i;
         nastepna(n_, k_, podzbior + 1, ++i, y_, lista1_, lista2_, lista3_, lista4_);
      }
   }
}

oraz takim wywoływaniu funkcji w programie:
nastepna(y,k,0,0,&h,lista1,lista2,lista3,lista4);

Niestety program podczas wykonywania się zawiesza. Podejrzałem w debugerze i jest tam odwołanie do linijki:
lista3_[*y_ + i] = lista1_[kombinacja[i]];
i pisze:
push 0x00415646
call Controls::16492 i przy tej linijce jest znacznik że błąd.
Pewnie ta informacja nic nie daje.

Próbowałem dojść po Twoich funkcjach do rozwiązania problemu ale Ty masz tam lista3, lista4 jako char i w ogóle jakieś takie trudne rzeczy:
unsigned char const * const lista1, unsigned char const * const lista2, unsigned long n, unsigned long k, unsigned char*& lista3, unsigned char*& lista4, unsigned long& ilosc
jakiś wskaźnik do adresu. To może u mnie trzeba zastosowac jakiś wskaźnik do adresu? Bo mimo, że przeszło kompilacje to wyraźnie widać, że jakieś nieporozumienie:

nastepna(n_, k_, podzbior + 1, ++i, y_, lista1_, lista2_, lista3_, lista4_);
nastepna(y,k,0,0,&h,lista1,lista2,lista3,lista4);

bo tu &h a tu y_ więc raz adres a raz zmienna, więc troche bezsensu. Może adf88 zajrzy na forum to się wypowie:)

0

mam nadzieje ze obejrzales zalaczniki pastebinowe.. jak dla mnie temat zakonczony

0

Przejrzałem, ale tam nic nie ma ciekawego. Jutro rano wstanę i cały dzień mam na kombinowanie jak sobie poradzić z tą wydawałoby się prostą rzeczą ale wiadomo jakie kompilatory są (bug na bugu) i trzeba kombinować jak koń pod górę.:) Raczej wątpię żeby kiedyś im się udało zrobić wersję finalną to mogliby lepiej nowy język wymyslić niż męczyć się z tworzeniem nowych wersji kompilatorów. Że tez jeszcze im się chce.:) Mi to tam zwisa, bo ja ten program skończę i mam nadzieję, że już nigdy w życiu z programowaniem w C nie będę miał do czynienia.

0
anderson21____________________ napisał(a)

ale wiadomo jakie kompilatory są (bug na bugu)

Taaa? Skad takie wnioski? Prowadziles badania? Przeprowadziles miarodajne testy? Napisales jakis kompilator, ze wiesz, ze stworzenie dobrego jest niemozliwe? Daruj sobie... Popisz chwile w zero-jedynkach a docenisz cala dobroc kompilatorow...

anderson21____________________ napisał(a)

Raczej wątpię żeby kiedyś im się udało zrobić wersję finalną to mogliby lepiej nowy język wymyslić niż męczyć się z tworzeniem nowych wersji kompilatorów.

Nowe kompilatory do c/c++ nie powstaja juz dobrych pare lat zdaje sie. Nowe jezyki za to jak najbardziej. Co ciekawe zaden nie powstal by zdetronizowac c/c++ - ciekawe czemu...

0

Udało się!
Oto postać tej funkcji:

void TSDIAppForm:: nastepna(int n_, int k_, int podzbior, int pozycja, int *lista1_, int *lista2_, int *lista3_, int *lista4_)
{
   int i;
   if(podzbior == k_)
   {
      for(i = 0; i < k_; i++)
      {
         lista3_[h+i] = lista1_[kombinacja[i]];
         lista4_[h+i] = lista2_[kombinacja[i]];
      }
      h = h + k_;
   }
   else
   {
      int stop = n_-(k_-podzbior);
      for(i = pozycja; i <= stop; i++)
      {
         kombinacja[podzbior] = i;
         nastepna(n_, k_, podzbior + 1, i+1, lista1_, lista2_, lista3_, lista4_);
      }
   }
}

Założenia:
trzeba globalnie zadeklarować:
int h=0;
oraz
int kombinacja[100];

Podejrzewam również, że jak mam globalnie zadeklarowane tablice lista1,lista2,lista3,lista4 to mógłbym je pewnie również wyciąć z parametrów funkcji.
Jeszcze pomiar czasu mi został to jak to poniżej nie zadziała:

DWORD start, koniec;
start = GetTickCount();
// kod
koniec = GetTickCount();
DWORD czas_w_ms = koniec-start;

to jeszcze co napisze a jak nie to cóż żegnam i dziękuję za wszelką pomoc, bo już z języka C mam nadzieje, że korzystał nie będę nigdy.:P

0
anderson21 napisał(a)

Przejrzałem, ale tam nic nie ma ciekawego

widzisz.. jakbys zajrzal i poswiecil 5 minut chocby na zrozumienie pierwszego pliku i przeczytanie komentarzy w nim zawartych, oswiecilo by Cie, ze dostales gotowy generator, dzialajacy na takiej zasadzie jak chciales, ktory wystarczy przekleic do twojego kodu, lacznie z instrukcja uzycia, dzialajcego bez globalnych paskudztw w stylu globalne zmienne.. i ktorego uzycie sprowadza sie do, wlasciwie, jednej linijki, a cala Twoja robocizna - do 10minut. over.

anderson21 napisał(a)

to jeszcze co napisze a jak nie to cóż żegnam i dziękuję za wszelką pomoc, bo już z języka C mam nadzieje, że korzystał nie będę nigdy.:P

przykro mi to mowic, ale ja tez

1 użytkowników online, w tym zalogowanych: 0, gości: 1