Witam serdecznie!
Sandbox to po polsku piaskownica. Będę tu w miarę wolnego czasu zamieszczał tutoriale z rozwiązaniami bardzo banalnych, acz ciekawych logicznie problemów, z którymi sam się kiedyś przecież borykałem. Może to będzie przyczynkiem do powstania nowego działu na forum - czas pokaże.
Zatem Sandbox 1: problem LOTTO :-)
Każdy wie co to i pewnie potrafi za pomocą kilku(nastu) linijek kodu wygenerować pojedynczy zakład 6 losowych liczb, prawda? Całkiem proste. Kopmy dalej - te liczby nie mogą się powtórzyć - wszak losujemy jak w LOTTO :-)
Co trzeba zatem zrobić - ano trzeba po wylosowaniu każdej kolejnej liczby,najlepiej w pętli sprawdzić, czy aby taka już się nie powtórzyła. Jeśli tak,to kolejne losowanie ... i kolejne sprawdzanie powtórzeń - tak długo aż żadna z wylosowanych 6 liczb się nie powtórzy.
Można to rozwiązać na kilka sposobów, teoretycznie najlepsza jest rekurencja... ale może się zaraz okazać, że to jednak nie jest najlepszy pomysł. Dlaczego? o tym potem,na końcu tego tutoriala.
Drugi sposób to zagnieżdżone pętle, przynajmniej dwie. ja wybrałem for dla generacji 6-ciu liczb i while dla sprawdzania warunku powtórzenia.
Uuuuppppsssss, własnie zdałem sobie sprawę z faktu, że być może ktoś z nas może się czuć dotknięty tym, że poruszam tu tak banalne tematy. Z góry przepraszam, ale to w końcu piaskownica jest - tak czy nie?
Dobra dość tego belferskiego tonu czas na kod:
I to by było na tyle.
Acha... jeszcze zdanie na temat wyższości rekurencji która się tu nie do końca sprawdza:-)
Otóż rekurencja jest trudna do przewidzenia w zakresie zajętości pamięci, bo wszystko to, co robi musi gdzieś odkładać na stosie, a ten jak wiemy nie jest zbyt duży. Wyobraźmy sobie na przykład, że losujemy nie 6 z 49 a 20 z 49 (albo dla testów 49 z 49 :-) Zobaczmy co się stanie. Na przykład udało się nam po ok 400 obiegach pętli w końcu wylosować 31 unikalnych liczb a 32 liczba znowu się powtórzyła, bo np. jest taka sama jak 12 liczba. Kurcze znowu skok i znowu kolejne losowanie....Ale w końcu i 49 z 49 da się wylosować :-)
A w rekurencji wszystko się odkłada na stosie i w pewnym momencie nasze arduino się zawiesi :-)
Pozdrawiam
proszę o ew. uwagi czy ma sens taka forma w piaskownicy?
Sandbox to po polsku piaskownica. Będę tu w miarę wolnego czasu zamieszczał tutoriale z rozwiązaniami bardzo banalnych, acz ciekawych logicznie problemów, z którymi sam się kiedyś przecież borykałem. Może to będzie przyczynkiem do powstania nowego działu na forum - czas pokaże.
Zatem Sandbox 1: problem LOTTO :-)
Każdy wie co to i pewnie potrafi za pomocą kilku(nastu) linijek kodu wygenerować pojedynczy zakład 6 losowych liczb, prawda? Całkiem proste. Kopmy dalej - te liczby nie mogą się powtórzyć - wszak losujemy jak w LOTTO :-)
Co trzeba zatem zrobić - ano trzeba po wylosowaniu każdej kolejnej liczby,najlepiej w pętli sprawdzić, czy aby taka już się nie powtórzyła. Jeśli tak,to kolejne losowanie ... i kolejne sprawdzanie powtórzeń - tak długo aż żadna z wylosowanych 6 liczb się nie powtórzy.
Można to rozwiązać na kilka sposobów, teoretycznie najlepsza jest rekurencja... ale może się zaraz okazać, że to jednak nie jest najlepszy pomysł. Dlaczego? o tym potem,na końcu tego tutoriala.
Drugi sposób to zagnieżdżone pętle, przynajmniej dwie. ja wybrałem for dla generacji 6-ciu liczb i while dla sprawdzania warunku powtórzenia.
Uuuuppppsssss, własnie zdałem sobie sprawę z faktu, że być może ktoś z nas może się czuć dotknięty tym, że poruszam tu tak banalne tematy. Z góry przepraszam, ale to w końcu piaskownica jest - tak czy nie?
Dobra dość tego belferskiego tonu czas na kod:
Kod:
// przykladowy programik lotto (generuje paczki po 5 zakładów) ...by wojtekizk
int z,i,j; // zmienne iteracyjne
int l[6]; // tablica 6 wylosowanych liczb w pojedynczym zakładzie
int err; // zmienna kontrolujaca czy wcześniej w tym samym zakladzie nie powtórzyła się już liczba
int k=0; // duża paczka po 100 zakladów, potem odstęp (na serialu)
void setup()
{
Serial.begin(9600);
Serial.println("Lotto 5 zakladow");
randomSeed(analogRead(0)); // inicjalizacja generatora liczb losowych
}
void loop()
{
for(z=0;z<5;z++) // losujemy 6 liczb dla każdego zakładu
{
l[0]=random(1,50); // losowo generujemy pierwszą liczbę, pierwsza bez problemu
Serial.print(l[0]); // wyświetlamy ją
Serial.print(" "); // spacja
for(i=1;i<6;i++) // pętla do losowania pozostałych 5-ciu liczb
{
err=1; // zmienna pomocnicza err=1 - tu celowo ustawiono na 1
// jeśli err=1 to oznacza że wylosowana liczba powtórzyła się
// jeśli err=0 to jest ok, można losować następną
l[i]=random(1,50); // losujemy kolejną, i-tą liczbę
while (err==1) // jak długo err==1 to wykonuj sprawdzanie liczb, czy się przypadkiem
// nie powtórzyły
{
err=0; // ustaw err=0, bo zakładamy wstępnie, że liczba się nie powtórzyła,
// a w pętli sprawdzimy czy mamy rację :-)
for(j=0;j<i;j++) // pętla do sprawdzania powtórzeń od 0 do itej - liczby, bo trzeba
// sprawdzić w pętli np. czy l[3]==l[0], potem czy l[3]==l[1]itd.
{
if(l[j]==l[i]) // jeśli właśnie wylosowana jest taka sama jak któraś poprzednia
{
l[i]=random(1,50); //to losuj ponownie
err=1; // i ustaw err=1 (bo wczesniej err było 0) i program nie wyjdzie
// z pętli while, czyli ponownie sprawdzi, co wylosowano :-)
} // koniec if-a
} // koniec pętli for, zatem wylosowano poprawną liczbę
} // koniec pętli while, bo po wylosowaniu kolejnej liczby err=0
Serial.print(l[i]); // wyświetlamy wylosowaną liczbę liczbę
Serial.print(" "); // spacja
}
Serial.println(" ");++k; // odstęp dla kolejnego zakładu
if(k%100==0) Serial.println(" "); // duże paczki zakładów - po 100 - i tak w nieskończoność :-)
if(k>32767) k=0; // aby nie przekroczyć max dla zmiennej typu int (32768)
}
}
I to by było na tyle.
Acha... jeszcze zdanie na temat wyższości rekurencji która się tu nie do końca sprawdza:-)
Otóż rekurencja jest trudna do przewidzenia w zakresie zajętości pamięci, bo wszystko to, co robi musi gdzieś odkładać na stosie, a ten jak wiemy nie jest zbyt duży. Wyobraźmy sobie na przykład, że losujemy nie 6 z 49 a 20 z 49 (albo dla testów 49 z 49 :-) Zobaczmy co się stanie. Na przykład udało się nam po ok 400 obiegach pętli w końcu wylosować 31 unikalnych liczb a 32 liczba znowu się powtórzyła, bo np. jest taka sama jak 12 liczba. Kurcze znowu skok i znowu kolejne losowanie....Ale w końcu i 49 z 49 da się wylosować :-)
A w rekurencji wszystko się odkłada na stosie i w pewnym momencie nasze arduino się zawiesi :-)
Pozdrawiam
proszę o ew. uwagi czy ma sens taka forma w piaskownicy?