[C] zliczanie powtarzających się w losowaniu liczb


(A1231497) #1

Napisz program, który przyjmie z klawiatury szesc liczb (od 1 do 49) i dokona losowania równiez szesciu

liczb z tego samego przedziału, po czym okresli, ile dokładnie liczb sie powtórzyło.

Początek jest dla mnie oczywisty ale kiedy dochodze do zliczania wylosowanych licz to nie bardzo mi idzie :smiley: znalazłem rozwiązania ktore wykonuja polecenia z pomoca tabelek, jednak ja musze sobie poradzic bez nich(na zajeciach jeszcze ich nie poznalismy). Moglby ktos podpowiedziec jak to zrobic?


(Grzelix) #2

mógłbyś podać co już masz - kod

użyj znaczników code i podaj co już napisałeś i zaznacz gdzie masz problem.

tak będzie o wiele łatwiej.


(A1231497) #3
#include 

#include 

#include 



int main()

{

    int x1, x2, x3, x4, x5, x6;

    printf("Podaj 6 liczb z zakresu od 1 do 49\n");

    scanf("%d%d%d%d%d%d", &x1, &x2, &x3, &x4, &x5, &x6);


    srand(time(NULL));


    int a=rand()%49 + 1;

    int b=rand()%49 + 1;

    int c=rand()%49 + 1;

    int d=rand()%49 + 1;

    int e=rand()%49 + 1;

    int f=rand()%49 + 1;


    printf("Wylosowane liczby to:\n a=%d\n b=%d\n c=%d\n d=%d\n e=%d\n f=%d\n", a, b, c, d, e, f);

mam tylko poczatek


(Copycona) #4

Możesz zrobić dużo warunków sprawdzając po kolei, czy każda z liczb a-f jest równa którejś x1-x6.

Jeżeli znajdzie się taka zwiększasz ilość znalezionych powtórzeń, oraz zmieniasz wartość x[1-6] na taką, która na pewno nie wstąpi (np. -1) - zapewni to, że liczba nie zostanie użyta do ustalenie powtórzenia po raz drugi.

powt = 0; // powtórzyło sieif(a == x1) { powt++; x1 = -1; }else if(a == x2) { powt++; x2 = -1; }else if(a == x3) { powt++; x3 = -1; }else if(a == x4) { powt++; x4 = -1; }else if(a == x5) { powt++; x5 = -1; }else if(a == x6) { powt++; x6 = -1; }

(A1231497) #5

Elegancko, troche roboty ale sie dobrze sprawdzi, dziekuje. dla liczby b wziac sobie np powt1 czy bedzie dobrze jak zostawie powt?


(Copycona) #6

Jeżeli potrzebujesz informacji ile się powtórzyło, bez wypisywania które (tak zrozumiałem treść zadania), to przecież w zupełności wystarczający jest jeden licznik i kod (metoda) podany wcześniej.


(Pablo_Wawa) #7

Pamiętaj jeszcze o tym, że jak sobie losujesz te 6 liczb, to mogą się one niestety powtórzyć (np. wylosujesz 1,5,14,28, 5 ,34)! To dodatkowo komplikuje kod programu (jak tego nie trzymasz w tablicy). :frowning:

Jeśli planujesz uwzględnić to w swoim kodzie, to sugeruję, byś napisał sobie osobną funkcję do sprawdzenia czy dana liczba występuje w grupie 6 liczb:

int compare(int x,x1,x2,x3,x4,x5,x6)

{

  if (x==x1) return 1;

  if (x==x2) return 2;

  if (x==x3) return 3;

  if (x==x4) return 4;

  if (x==x5) return 5;

  if (x==x6) return 6;

  return 0;

}

Funkcja zwróci 0 jak liczba x nie występuje wśród x1..x6 lub >0 jak występuje (i masz numer liczby - to bonus, możesz zwracać zawsze 1). Wywoływać możesz taką funkcję w następujący sposób (mówię o sprawdzeniu 6 losowanych przez Ciebie liczb, czy się któraś nie powtórzyła):

while compare(x1,0,x2,x3,x4,x5,x6)

  x1=rand()%49+1;

while compare(x2,x1,0,x3,x4,x5,x6)

  x2=rand()%49+1;

...

while compare(x6,x1,x2,x3,x4,x5,0)

  x6=rand()%49+1;

Oczywiście to robisz już po wylosowaniu początkowym tych 6 liczb. Podobnie możesz potem sprawdzić liczby wprowadzone przez użytkownika. EDIT: powyższy kod (z sześcioma pętlami while) nie jest dobry (jak dwie ostatnie liczby będą takie same, pierwsza pętla while nigdy się nie skończy), oto poprawny kod (jest tylko 5 pętli while, pierwszej liczby x1 nie m sensu zmieniać):

while compare(x2,x1,0,-1,-2,-3,-4,-5)

  x2=rand()%49+1;

while compare(x3,x1,x2,0,-1,-2,-3,-4)

  x3=rand()%49+1;

while compare(x4,x1,x2,x3,0,-1,-2)

  x4=rand()%49+1;

while compare(x5,x1,x2,x3,x4,0,-1)

  x5=rand()%49+1;

while compare(x6,x1,x2,x3,x4,x5,0)

  x6=rand()%49+1;

Po prostu porównujemy kolejną liczbę z dotychczas porównanymi (a nie wszystkimi), stąd dodatkowe "zamienniki" takich liczb (nie mogą się powtarzać, a liczby mniejsze lub równe zero nie są losowane).


([alex]) #8

Można to zrobić za pomocą maski bitowej na liczbie:

long long X;

losowanie: r=1+rand()%49; if(!(x&(1<

wczytywanie - tak samo

sprawdzenie ile:

XX=X&X1;

licznik=0;

while(XX) { XX&=XX-1; ++licznik; }


(Pablo_Wawa) #9

Pozwolę sobie wyjaśnić algorytm przedstawiony przez [alex] - bardzo sprytny zresztą:

otóż long long X to bitowa reprezentacja liczb od 1 do 49 (49 bitów) - na liczbie 64-bitowej się to zmieści. To coś jak zbiór (set of 1..49) w Pascalu. :slight_smile:

I teraz mamy losowanie liczb, zapamiętywanie ich polega na ustawieniu właściwego bitu równego wylosowanej liczbie (bit o nr n to liczba 2^n czyli 1 << n - rotacja bitu w lewo o n pozycji). Potem robimy bitowe OR (suma bitów) i gotowe. Sprawdzanie czy liczba n występuje to sprawdzenie n-tego bitu w X.

P.S. Brakuje wyzerowania bitów w X (X=0L; lub w deklaracji long long X=0L;) na początku algorytmu. Sprawdzenie według mnie powinno wyglądać inaczej (XX=X & X1 jest błędne, poprawnie powinno być XX = X & (1<


([alex]) #10

W X wylosowane liczby w X1 wczytane liczby, X&X1 wspólne bity (liczby)

dalej liczymy ile tych wspólnych.


(Pablo_Wawa) #11

No tak, tego z X1 nie "załapałem", myślałem że w X1 masz jedną liczbę (jako wartość). Teraz już wszystko jasne. :slight_smile: