Tablice - korelacja język C

gogi000

Nowicjusz
Dołączył
27 Luty 2016
Posty
5
Punkty reakcji
0
Witam. Mam pewien problem. Zadanie jest związane z korelacją. Zadanie polega na tym, że wprowadzam liczby z klawiatury do listy. Lista np { 2,3,4,5,6} i wprowadzam np drugą listę mniejszą od tej pierwszej np [4,5] . I ma wyglądać to tak:

{2,3,4,5,6}
{4,5} -> w pętli przesuwam tą tablice o krok w prawo

Funkcja ma zwracać indeks najlepszego dopasowania liczb.. Czyli w tym wypadku zwróci indeks 2 jeżeli liczę od zera.

Ktoś ma jakiś pomysł jak się za to zabrać?

to ma działać tak długo aż tak lista mniejsza znajdzie taką samą wartość w tej większej liści i wtedy zwrócić indeks :
podaję jeszcze raz przykład bardziej opisany
wprowadzam pierwszą listę z klawiatury, która ma być sygnałem w formie liczb:
czyli np do tablicy wprowadzam takie liczby jak {1,2,3,4,5,6,7,8,9} i to jest moja pierwsza tablica.
następnie wprowadzam drugą tablice tylko, że krótszą od tej pierwszej bo to ma być ten sam sygnał tylko że przesunięty w czasie (korelacja)
czyli wprowadzam np {3,4} - gdzies te liczby musza sie pojawić w tej pierwszej tablicy bo to jest ten sam sygnał
no i teraz funkcja ma działać tak że zwróci mi indeks przesunięcia
przykład
{1,2,3,4,5,6,7,8,9}
{3,4}
porównuje 1,2 z 3,4 - nie zgadza się
przesunięcie
{1,2,3,4,5,6,7,8,9}
{3,4}
nie zgadza się
przesunięcie
{1,2,3,4,5,6,7,8,9}
{3,4}
zgadza i zwraca mi indeks tego przesunięcia czyli tam gdzie jest 3 w jednej i drugiej tablicy . Indeks będzie wynosił 2 bo 1 to indek zerowy 2 to indeks 1 , a 3 to indeks 2

Taka funkcja ma być uniwersalna nie zależnie ile wprowadze liczb do pierwszej tablicy i drugiej ( trzeba pamietać że ta tablica druga zawsze jest mniejsza)
 

seba211

Stały bywalec
Dołączył
2 Lipiec 2010
Posty
331
Punkty reakcji
219
Brakuje mi kilku testów, bo te powyższe nie są zbyt specyficzne. Podałeś kolejno liczby, a w Twojej specyfikacji nie widzę, czy one są malejąco, czy też ciąg krótszy jest zawsze wyciętą częścią ciągu dłuższego. Sprecyzujesz, to poprawię.

int indeksKrotszejTablicy=0;
for(int i=0;i<dlugoscDluzszejTablicy;i++){
if(dluzszaTablica==krotszaTablica[indeksKrotszejTablicy]){
i++;
int licznik=1;
for(int j=i;licznik<dlugoscKrotszejTablicy;j++, licznik++){
if(dluzszaTablica[j]!=krotszaTablica[licznik])
break;
}
if(licznik==dlugoscKrotszejTablicy)
return --i;
}
}

Generalnie zrobiłem to tak, że przechodzę po dłuższej tablicy i sprawdzam, czy zaczyna się ciąg krótszy. Jeśli pierwszy znak z krótszego i któryś i-ty z dłuższego się zgadzają, to wchodzę do pętli i sprawdzam, czy on rzeczywiście tam jest. Jeśli był break, to if nie wejdzie i nic nie zwróci. Jeśli nie było, to pętla przejdzie do końca, a licznik będzie równy długości krótszej tablicy. To tak z grubsza. Bardzo możliwe, że niepoprawnie zrozumiałem treść, więc w takim wypadku proszę o ciekawsze przykłady.
 

gogi000

Nowicjusz
Dołączył
27 Luty 2016
Posty
5
Punkty reakcji
0
Ciąg krótszy jest zawsze wyciętą częścią ciągu dłuższego, ponieważ ciąg krótszy jest tym samym sygnałem tylko, przesuniętym w czasie.
Czyli nie zależnie jakie liczby dodam do tablicy dłuższej to jakaś ich część pojawi się w krótszej.
Czyli Np:
tab1 = {2,3,4,5,6,7}
tab2= {3,4} jeżeli tutaj są dwie liczby to porównuje z dwoma pierwszymi powyższej tablicy czyli z 3,4 z 2,3 ( 3,4 nie zgadza się z 2,3) . Więc teraz przesuwa 3,4 z małej tablicy o indeks w prawo i teraz patrzy czy 3,4 z małej tablicy = 3,4 z dużej tablicy . Tak zgadza się zwraca indeks czyli 1 bo są porównywane dwie liczby więc w dużej tablicy bieże pod uwagę 3 i 4 więc indeks tej 3 a trzy jest na indeksie 1.

lub
tab1={7,3,4,5,6}
tab2= { 4,5,6}
porównuje 4,5,6 z 7,3,4 ( nie zgadza się )
przesunięcie tab2 o jeden w prawo, czyli teraz porównuje 4,5,6 z 3,4,5 nie zgadza się , przesunięcie tab2 o jeden w prawo , porównuje 4,5,6 z 4,5,6 zgadza się zwraca indeks 2 bo 4,5,6 zaczyna się na indeksie 2 .
Zawsze bierzemy tą mniejszą tablice i przyrównujemy do tej większej . i patrzymy czy sie zgadza jak nie to mniejszą tabele przesuwamy w prawo tak długo aż znajdziemy to taką samą tablice jak mała tablica.

Liczby dużej tablicy moga być przypadkowe bo wprowadzam je z klawiatury , Natomiast liczby małej tablicy również wprowadzam z klawiatury lecz musze pamiętać ze musi być to ciąg liczb tak jak jest dodane do dużej tablicy.

tab1 = { 3,2,1,3,4,5,6,7,8,9,1}
tab2 = { 7,8,9,1}
Ciąg tab2 znajduje się w tab1 więc szukamy indeksu tab2 w tab1
 

seba211

Stały bywalec
Dołączył
2 Lipiec 2010
Posty
331
Punkty reakcji
219
W tym wypadku moja rozwiązanie powinno działać, aczkolwiek nie sprawdzałem tego w środowisku. Gdybyś miał pytania, to pisz.
Nie twierdzę też, że to jest najoptymalniejsze rozwiązanie, chociaż nie sądzę by się znalazło lepsze.
 

gogi000

Nowicjusz
Dołączył
27 Luty 2016
Posty
5
Punkty reakcji
0
Jest super i wszystko działa ! :) dzięki wielkie za pomoc
Zostaje jeszcze mały problem :
a co w przypadku gdy:
tab1={1,2,3,4,5,5,6} dam dodatkową 5 przed ten ciąg poszukiwany
tab2= {5,6}
Jeszcze nad tą ostatnią opcją sie zastanawiam żeby jakoś to obejść.
 

seba211

Stały bywalec
Dołączył
2 Lipiec 2010
Posty
331
Punkty reakcji
219
for(int i=0;i<rozmiarDluzszej;i++){
if(tablicaDluzsza==tablicaKrotsza[0]){
for(int j=i,licznik=0;licznik<rozmiarKrotszej;j++,licznik++){
if(tablicaDluzsza[j]!=tablicaKrotsza[licznik]){
j=i;
break;
}
else if(licznik==rozmiarKrotszej-1)
return i;
}
}
}

Zrobiłem przeróbkę, bo to co wczoraj w nocy napisałem jest straszne. Tu masz wersję czytelniejszą i bez Twojego przypadku. Przeanalizuj proszę i bez kopiuj-wklej,.
 

gogi000

Nowicjusz
Dołączył
27 Luty 2016
Posty
5
Punkty reakcji
0
Nie do końca mogę zrozumieć co dzieje się w tym miejscu
for(int j=i,licznik=0;licznik<rozmiarKrotszej;j++,licznik++){
if(tablicaDluzsza[j]!=tablicaKrotsza[licznik]){
j=i;
 

seba211

Stały bywalec
Dołączył
2 Lipiec 2010
Posty
331
Punkty reakcji
219
Usuń to j=i. Kombinowałem z czymś innym i niechcący nie zauważyłem, bo nie powodowało błędów.
 

gogi000

Nowicjusz
Dołączył
27 Luty 2016
Posty
5
Punkty reakcji
0
for(j=i,licznik=0;licznik<rozmiarKrotszej;j++,licznik++){
if(tablicaDluzsza[j]!=tablicaKrotsza[licznik]){
break;
}
else if(licznik==rozmiarKrotszej-1)
a dokładnie co robi ten kod , jakbyś mógł opisać słownie żebym mógł to lepiej zrozumieć ?
 

seba211

Stały bywalec
Dołączył
2 Lipiec 2010
Posty
331
Punkty reakcji
219
Jeśli widzi, że w ciągu dłuższym natrafiono na początek krótszego, czyli ten warunek:

if(tablicaDluzsza==tablicaKrotsza[0])

to musi sprawdzić, czy ten krótszy właśnie tam jest. Czyli idziemy równolegle po tych dwóch tablicach:

for(j=i,licznik=0;licznik<rozmiarKrotszej;j++,licznik++){

j=i, bo to jest właśnie ten moment w dłuższego gdzie może zacząć się krótszy ciąg (wcale nie musi). Licznik jest, bo krótsza tablica musi mieć własny. Przechodzi sobie po tych tablicach i sprawdza:

if(tablicaDluzsza[j]!=tablicaKrotsza[licznik])

Jeśli wejdzie w niego przed przejściem po całym krótszym ciągu, to wtedy wiemy, że to nie jest ten ciąg i wychodzimy na zewnątrz przez użycie break. Bierzemy jego kolejną liczbę dłuższego i znów sprawdzamy z krótszym. Gdyby się jednak okazało, że ten krótszy tam jest, to wtedy ten if się nie wywoła ani razu podczas przejścia pętli, ale za to na samym końcu odezwie się ten warunek:

else if(licznik==rozmiarKrotszej-1)

Czyli widzi, że jest koniec krótszego ciągu i ostatnia liczba się zgadzała, bo warunek wyżej przeszedł. W tym wypadku zwraca odpowiedni indeks ciągu dłuższego.
 
Do góry