Losowanie niepowtarzających się liczb

0

@n0name_l: mnie nie chodzi o optymalizację. Gdy zobaczyłem Twoje rozwiązanie, to mnie w ogóle nie ruszyło. Widziałem je wczęsniej, uważam że jest "sprytne" i krótkie. Może być. Zdecydowałem się napisać, po tym jak przeczytałem Twoją odpowiedź do @puk czyli To akurat najgorsze rozwiazanie.. Żadnego argumentu. Żadnej konstruktywnej krytyki jak poprawić kod.

Napisałem głównie żeby pokazać co może poprawić i że jego rozwiązanie wcale nie jest takie złe. Ba! Jest najnaturalniejsze (co potwierdził @bogdans) i co śmieszne... wydajniej wykonuje zadanie (losowanie lotto) od Twojego kodu. :) Jego rozwiązanie jest bardzo proste i wystarczające. Na pewno nie jest "najgorsze".

Po drobnych modyfikacjach dla większości zakresu będzie miało zdecydowanie wyższą wydajność od Twoejgo rozwiązania, które swoją drogą wcale nie jest oczywiste. :)

@_13th_Dragon: proszę napisz kod "według siebie" i wklej go tutaj, jestem cieakwy o ile jest szybszy i go zapiszesz. :) To tylko 2 minuty roboty.

0

mnie nie chodzi o optymalizację.

Ciezko mi bylo to wywnioskowac, skoro caly czas o tym i w gruncie rzeczy tylko o tym wspominasz.

wcale nie jest takie złe.

Wcale. Co z tego, ze dla polowy danych sie nigdy nie skonczy.

które swoją drogą wcale nie jest oczywiste.

Jak ktos nie rozumie czym jest mieszanie tablicy, to faktycznie moze sprawiac klopot. W sumie, ciezko o to winic kogos, skoro pierwszy material jaki znalazlem przedstawia taka definicje.

Zadanie mieszania, tasowania (ang. shuffle) zawartości tablicy sprowadza się do wykonywania w pętli zamiany miejscami dwóch elementów tablicy o wylosowanych indeksach. Pętla musi być wykonana tyle razy, aby tasowanie objęło wszystkie elementy – w praktyce wystarcza ilość wykonań równa 3n, gdzie n jest ilością elementów.

2

Ten yield ci spowalnia kod i fałszuje wynik. Dlaczego? Dlatego, że wykonuje się leniwie, czyli dopiero w tej pętli wewnątrz metody TestPerformance:

            foreach (var item in range)
                ;

następuje, w każdej iteracji tej „pustej” pętli, wejście do metody Dragon i wykonanie jednej iteracji tej pętli:

        for (int i = 0; i < howMany; ++i)
            yield return allnumbers[i];

Obie pętle wykonują się jednocześnie na przemian po jednym kroku na raz.

yield jest fajne, ale do generowania danych w locie, a nie kiedy masz już gotową tablicę - zwróć po prostu tę tablicę, ewentualnie rzutowaną na IEnumerable, a nie iterujesz bez sensu po tablicy uruchamiając całą skomplikowaną maszynerię kryjącą się pod yield.

0

@Azarien: tak, zwróć uwagę że on ma tablicę wszystkich możliwych liczb, a chcemy tylko n-pierwszych. Nie wiem jak to zapisać żeby go zadowoliło. Nawet zwrwacając całą tablicę i w TestPerformance zamiast foreach zrobić ToArray(), to i tak jego kod przyśpieszy tylko o 30%.

Jak ktos nie rozumie czym jest mieszanie tablicy, to faktycznie moze sprawiac klopot. W sumie, ciezko o to winic kogos, skoro pierwszy material jaki znalazlem przedstawia taka definicje.

Przedstawia definicję:

Zadanie mieszania, tasowania (ang. shuffle) zawartości tablicy sprowadza się do wykonywania w pętli zamiany miejscami dwóch elementów tablicy o wylosowanych indeksach.

A Ty tworzysz zakres liczb, później parujesz go z losową wartością i następnie tę tablicę sortujesz według losowej wartości. :) To rozwiązanie które zaprezentowałeś można wrzucić do kategorii "ładnie wyglądające, najkrótsze, działające", ale nie jest najbardziej naturalnym czy wydajnym. W moim mówię "losuj dopóki nie masz zbioru n liczb", inni piszą "sprawdź czy wylosowana liczba była wcześniej wylosowana, powtarzaj dopóki masz n liczb na liście", a Ty? ;).

2

on ma tablicę wszystkich możliwych liczb, a chcemy tylko n-pierwszych.

jeśli Framework 4.5 to

return new ArraySegment(allnumbers, 0, howMany);

w starszych wersjach ArraySegment jest ale nie dziedziczy po IEnumerable<T>, co czyniło go raczej mało użytecznym.

0

A Ty tworzysz zakres liczb, później parujesz go z losową wartością i następnie tę tablicę sortujesz według losowej wartości. :)

W moim mowie "Wez kolekcje i posortuj wedlug losowej kolejnosci".
W twoim mowisz "Dopoki zbior nie osiagnie pewnego rozmiaru, powtarzaj losowanie i probe umieszczenia tam elementu".
W innym mowia "Dopoki lista nie osiagnie pewnego rozmiaru, powtarzaj losowanie, sprawdzaj czy element juz wystepuje i jesli nie wystepuje umiesc go w liscie"

Mozemy sie tez inaczej pobawic.
Jesli masz 10 klocow, ponumerowanych rosnaco i masz je pomieszczac, co zrobisz?
a) Zaczniesz ukladac klocki w losowy sposob.
b) Wrzucisz klocki do woreczka. Wylosujesz pojedynczy klocek. Zapiszesz na kartce jego indeks, a nastepnie wrzucisz go z powrotem, zeby powtorzyc operacje.
c) Wrzucisz klocki do woreczka. Wylosujesz klocek i umiescisz go od razu na odpowiednim miejscu

0

Jesli masz 10 klocow, ponumerowanych rosnaco i masz je pomieszczac, co zrobisz?
a) Zaczniesz ukladac klocki w losowy sposob.
b) Wrzucisz klocki do woreczka. Wylosujesz pojedynczy klocek. Zapiszesz na kartce jego indeks, a nastepnie wrzucisz go z powrotem, zeby powtorzyc operacje.
c) Wrzucisz klocki do woreczka. Wylosujesz klocek i umiescisz go od razu na odpowiednim miejscu

Z tych trzech opcji tylko odpowiedź a) jest sensowna, bo pozostałe nie mieszają klocków tylko robią inne operacje.

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