Jak wylosować 4 liczby bez powtórzeń?

0

Jak wylosować 4 liczby bez powtórzeń? Napisałem taki kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LosowanieBezPowtorzen
{
    class Program
    {
        static void Main(string[] args)
        {
            Random losuj = new Random();
            int[] Liczby = new int[4];
            int wylosowana;
          
            List<string> listaSlow = new List<string>();
            listaSlow.Add("A");
            listaSlow.Add("B");
            listaSlow.Add("C");
            listaSlow.Add("D");
            listaSlow.Add("E");
            listaSlow.Add("F");
            listaSlow.Add("G");

            int maxPrzedzial = listaSlow.Count;

            for (int i = 0; i < 4; i++)
            {
                do
                {
                    wylosowana = losuj.Next(0, maxPrzedzial);
                    Liczby[i] = wylosowana;
                }
                while (Liczby[i] == wylosowana);
            }

            for (int i = 0; i < Liczby.Length; i++)
            {
                Console.WriteLine(Liczby[i]);
            }
            Console.ReadLine();
        }
    }
}
 

Program chyba nie losuje tych liczb, ponieważ jak włączę program to na oknie konsoli nic się nie pojawia.

0

to ja nnn

Ja to chyba bym to robił tak że mam jakąś długą pętlę for( może nieskończoną) w której robię random() liczb i wrzucam je do kontenera Set<Integer>.
W zbiorze - Set<Integer> - liczby nie mogą się powtarzać wiec wszystkie powtórzenia zostaną automatycznie wyrzucone. Kontener Set należy w tym przypadku napełnić do rozmiaru 4.

0

to ja nnn

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LiczbyBezPowtorek
{
    class Program
    {
        static void Main(string[] args)
        {
            int liczba = 0;
            int przedzial = 50;
            Random r = new Random();
            ISet<Int32> iset = new SortedSet<Int32>();
            while (true)
            {
                liczba = r.Next(1, przedzial);
                iset.Add(liczba);
                if (iset.Count == 4)
                {
                    break;
                }
            }
            foreach( Int32 i in iset )
            {
                Console.WriteLine(i);
            }
        }
    }
}
0
  • zapełnić jakiś kontener losowymi liczbami
  • w pętli (u Ciebie 4 razy) wylosować liczbę z przedziału (0;kontener.size())
  • zapamiętać do jakiejś tablicy liczbę spod wylosowanego indeksu tego kontenera
  • usunąć wylosowaną liczbę z kontenera

W skrócie - losować indeksy a nie liczby, bo inaczej może losować w nieskończoność

0

@up,
A jak zrealizować pierwszy punkt? tzn. jak wypełnić kontener losowymi niepowtarzającymi się liczbami? Wygląda, że Twój algorytm, to nieskończona rekurencja.

0

Najpierw dlaczego nic się nie działo:

 do
                {
                    wylosowana = losuj.Next(0, maxPrzedzial);
                    Liczby[i] = wylosowana;
                }
                while (Liczby[i] == wylosowana);

Ponieważ wpisywałeś do Liczby[i] jakąś liczbę, a następnie sprawdzałeś czy taka liczba jest w Liczby[i], co oznacza, że warunek był zawsze prawdziwy i pętla zrobiła się nieskończona.

Praktycznie każda kolekcja w .NET 3.5 posiada metodę Contains, którą możesz sprawdzić czy dany element znajduje się w kolekcji (tablica może być) przed dodaniem nowego. Jest to najprostsze rozwiązanie.

Pozdrawiam.

0

Napisałem teraz tak, ale czasem 2 razy jest losowana liczba zero;/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Losowanie2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> listaSlow = new List<string>();
            List<int> mozliweIndeksy = new List<int>();
            int[] Liczby = new int[4];
            Random losuj = new Random();
            int wylosowana;

            listaSlow.Add("A");
            listaSlow.Add("B");
            listaSlow.Add("C");
            listaSlow.Add("D");
            listaSlow.Add("E");
            listaSlow.Add("F");
            listaSlow.Add("G");

            int maxPrzedzial = listaSlow.Count;
            for (int i = 0; i < 4; i++)
            {
                wylosowana = losuj.Next(0, maxPrzedzial);
                if (!Liczby.Contains(wylosowana))
                {
                    Liczby[i] = wylosowana;
                }
            }

            for (int i = 0; i < Liczby.Length; i++)
            {
                Console.WriteLine(Liczby[i] + " ");
            }
            Console.ReadKey();
        }
    }
}

 
0

Poprawiłem.

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Losowanie3
{
    class Program
    {
        static void Main(string[] args)
        {
            Random losuj = new Random();
            int[] Liczby = new int[4];
            int wylosowana;

            List<string> listaSlow = new List<string>();
            listaSlow.Add("A");
            listaSlow.Add("B");
            listaSlow.Add("C");
            listaSlow.Add("D");
            listaSlow.Add("E");
            listaSlow.Add("F");
            listaSlow.Add("G");

            int maxPrzedzial = listaSlow.Count;

            for (int i = 0; i < 4; i++)
            {
                do
                {
                    wylosowana = losuj.Next(0, maxPrzedzial);
                    if(!Liczby.Contains(wylosowana))
                        Liczby[i]=wylosowana;
                }
                while (Liczby[i] == wylosowana);
            }

            for (int i = 0; i < Liczby.Length; i++)
            {
                Console.WriteLine(Liczby[i]);
            }
            Console.ReadLine();
        }
    }
}

Czy ten kod jest poprawny?? Pytam, bo tutaj rzadziej się powtarzają dwa zera, ale jednak się powtarzają. Pytanie dlaczego.

0

Nie. Poza tym, że robisz to jakoś dziwnie, to przemyśl warunek pętli do..while oraz pomyśl jakie wartości znajdują się w tablicy Liczby zaraz po utworzeniu.

0
cysiej napisał(a)
  • zapełnić jakiś kontener losowymi liczbami
  • w pętli (u Ciebie 4 razy) wylosować liczbę z przedziału (0;kontener.size())
  • zapamiętać do jakiejś tablicy liczbę spod wylosowanego indeksu tego kontenera
  • usunąć wylosowaną liczbę z kontenera

W skrócie - losować indeksy a nie liczby, bo inaczej może losować w nieskończoność

stosuję bardzo podobny algorytm:

  • mam zbiór "n" elementowy w jakiejsc kolekcji
  • losuje jeden element z tej kolekcji po indexach z obszaru od 0 do "n" tej kolekcji (nie po wartosciach tylko po indexach)
  • wylosowanay element zapamiętuje w innej zmiennej i zamieniam miejscami z ostatnim elementem kolekcji
  • losuje drugi raz z całej kolekcji ale tym razem z obaszru od 0 do "n-1" (na pozycji "n" w kolekcji ustawilem poprzednio, wczesniej wylosowany element takze losuje z tych samych elementow co ostatnio tylko bez ostatnio wylosowanego elementu)
  • po raz drugi zapamietuje wylosowany element i dodaje do zmiennej juz wylosowanych elementow i znow zamieniam go miejscami z elementem "n-1"
  • i tak dalej, nie ma pustych przebiegow i losowanie przebiega w tylku krokach ile liczb chcesz losowac

w przypadku gdy skupiasz się na tym ze najpierw losujesz cokolwiek i potem porownujesz czy juz wczesniej cos takiego wlosowales a jezeli tak to znow losujesz - tworza sie puste przebiegi petli, wlasnie dlatego na większych zbiorach np. 4500 losowych ze zbioru 5 000 elementów teoretycznie moze powstac petla nieskonczona, jezeli Twój obiekt "losuj" typu Random bedzie miał pecha i bedzie losowal non stop liczby ktore juz wczesniej wylosowal.

0

np. 4500 losowych ze zbioru 5 000 elementów

Rozsądny programista nigdy tak nie losuje. Losuje te 500 elementów, które maja być pominięte.

0

Gdy chcemy losować CZTERY liczby (spośród ponad 4 miliardów) to prawdopodobieństwo dodatkowych przebiegów pętli jest bardzo małe i taki sposób można zastosować.
Co innego będzie, gdy chcemy wylosować 99 ze stu.

0

Przypomnę konkurs sprzed kilku lat, liczby bez powtórzeń można uzyskać jednym losowaniem. Żadna bardzo długa pętla nie grozi (prawdopodobieństwo, że pętla będzie nieskończona wynosi 0).
http://4programmers.net/Forum/Delphi_Pascal/134543-KONKURS_lotto_bez_tablic?start=40

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