Losowanie niepowtarzalnych liczb

0

Witam,
Przejrzałem kilka tematów i nie znalazłem podobnego przypadku. Chcę wylosować kilka niepowtarzalnych liczb, np 3, sposobem który chce to zrobić mam problem. Od razu zakładam, że wiem że jest wiele innych sposobów i jeżeli nikt mi nie wyjaśni dlaczego mój sposób nie działa to pewnie sobie skorzystam z innego, ale moje pytanie i prośba zarazem brzmi następująco: dlaczego ten algorytm nie funkcjonuje dobrze? Gdzie jest błąd?

	do
	{
		l1 = rand()%5+1;  
        l2 = rand()%5+1;  
        l3 = rand()%5+1;  
		
	} while ((l1 == l2) && (l2 == l3));

Jeżeli l1 i l2 będą takie same oraz l2 będzie równe l3 to pętla się wykonuje. Jeżeli będą różne (wszystkie 3) to następuje fałsz i pętla zostaje zakończona. Gdzie robię błąd?
Pozdrawiam

1
janemba napisał(a):

Jeżeli l1 i l2 będą takie same oraz l2 będzie równe l3 to pętla się wykonuje.

No właśnie: „oraz”. To znaczy, że pętla się wykonuje dalej tylko, jeśli wszystkie trzy liczby są takie same.

A jeżeli np. l1 jest równe l2, ale l3 jest już różne od tych dwóch, to warunek tego nie wychwyci: wszak nie jest prawdą, że l2 == l3, więc i cała koniunkcja (cokolwiek && (l2 == l3)) też jest nieprawdziwa; pętla się więc przerywa,.

Wydaje mi się, że powinieneś napisać raczej: while ((l1 == l2) || (l2 == l3) || (l1 == l3))

0

cała koniunkcja (cokolwiek && (l2 == l3)) też jest nieprawdziwa; pętla się więc przerywa
No tak, zawsze stosowałem podobne rozwiązanie i z automatu tak poszło... Ale dzięki za wyjaśnienie. Generalnie ma być 5 nie powtarzalnych liczb, ale w tym temacie chodziło mi zrozumienie danej istoty. Dzięki za wyjaśnienie.

ps. moderatorze wybacz :D

1

Jeśli zakres liczb jest niewielki dla komputera to lepiej jest wpakować wszystkie wartości do wektora, wymieszać go, a potem po prostu wziąć kilka pierwszych elementów.

Np. dziesięć losowych liczb z zakresu [101,150] bez powtórzeń:

	vector<int> vec(50);
	iota(vec.begin(), vec.end(), 101);
	shuffle(vec.begin(), vec.end(), std::random_device{});
	vector<int> bez_powtorzen(vec.begin(), vec.begin() + 10);

http://melpon.org/wandbox/permlink/VfwHtgaXtjk6TNd7

0

@kq generalnie co to pisze to pisze na Androida. Pętla do while i for są identyczne zarówno jak Javie (Android) jak i C++, więc jeśli z czymś takim mam problem to czasami sprawdzam to na c++ właśnie, lubię ten język (od strony że tak powiem strukturalnej). Ale dziękuję za ten kod.
@kmph mój temat nie oznacza, że wrzucę do warunku 10 opcji by uzyskać 5 nie powtarzalnych liczb. Ja po prostu nie rozumiałem dlaczego mój kod nie działa, nie zastanowiłem się nad nim wystarczająco długo :) teraz kontynuuje swoje wypociny więc pomyślę nad rozwiązaniem.

0

@kq

Rozwiązanie problemu znalezienia trzech różnych liczb pseudolosowych w zakresie od 1 do 5:

#include <iostream>
#include <unordered_set>
#include <deque>
#include <random>
#include <chrono>
#include <cstdint>
#include <cassert>
using namespace std;

using integer = uint_least8_t;
using results_set = unordered_set<integer>;
using results_queue = deque<integer>;

ostream &operator << (ostream &os, results_queue const &q)
{
  for(auto i : q)
    os << +i << '\t';
  
  return os;
}

int main()
{
  integer a=1u, b=5u;
  
  results_set s;
  results_set::size_type n=3u;
  assert(n<=b-a+1);
  
  results_queue q;
  
  auto seed = chrono::system_clock::now().time_since_epoch().count();
  default_random_engine gen(seed);
  uniform_int_distribution<integer> dist(a,b);
  
  while(s.size() < n)
  {
    integer prop(dist(gen));
    if(!s.count(prop))
    {
      s.emplace(prop);
      q.push_back(prop);
    }
  }
  
  cout << q << '\n';
}

--- joke mode off ---

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