Losowe łączenie w pary tekstu z pliku

0

Witam,

Piszę program który ma za zadanie pobrać listę osób z pliku txt, dobrać dla każdej osoby losowego (unikalnego) partnera i zapisać wynik również w pliku txt. Natrafiłem jednak na pewien problem. Otóż nie mam bladego pojęcia w jaki sposób zmusić program aby nie wybierał znów tych samych osób.

Dane wejściowe są w takiej postaci:

  1. Imie1 Nazwisko1
  2. Imie2 Nazwisko2
  3. Imie3 Nazwisko3
  4. Imie4 Nazwisko4
  5. Imie5 Nazwisko5

A wyjściowe powinny wyglądać tak:

Imie1 Nazwisko1 - Imie4 Nazwisko4
Imie2 Nazwisko2 - Imie5 Nazwisko5

Do tej pory udało mi się naskrobać to:

 private void button1_Click(object sender, EventArgs e)
        {
            StreamReader liczba = new StreamReader("number.txt");
            int licz = 2 * (int)((char)(liczba.Read()));
           
            StreamReader f1 = new StreamReader("lista1.txt");
            string[] tab = new string[licz];
            string[] tab1 = new string[licz];
            for (int i = 0; i < licz; i++)
            {
                tab[i] = f1.ReadLine();
                tab1[i] = f1.ReadLine();
            }
            f1.Close();

            StreamWriter sw1 = new StreamWriter("generate.txt");

            licz = (licz / 10) + 1;
            int zakres = licz / 2;
           

            Random los = new Random();
            int losowa;
            for (int z = 0; z < zakres; z++)
            {
                losowa = los.Next(((int)(zakres)), licz);
                sw1.WriteLine(tab[z] + " " + tab1[z] + " - " + tab[losowa] + " " + tab1[losowa]);
            }
            sw1.Close();

            StreamReader f2 = new StreamReader("generate.txt");
            textBox1.Text = f2.ReadToEnd();
            f2.Close();
        }

Małe objaśnieni:

  • plik "lista1.txt" zawiera listę osób na wejściu,
  • plik "number.txt" zawiera liczbę osób,
  • plik "generate.txt" zawiera dane po połączeniu w pary.

Wiem że kod jest pewnie pełen błędów i obchodzenia wszystkiego naokoło, ale dopiero zaczynam moją przygodę z C# :)

Byłbym bardzo wdzięczny gdyby ktoś podrzucił mi kod który sprawi że wszyscy (nie tylko druga połowa) będą brani do losowania oraz nikt nie zostanie wylosowany dwa razy.

Z góry dziękuje :)

0

Wersja z poprawkami, niestety nie działa jeszcze tak jak powinna... :(

 private void button1_Click(object sender, EventArgs e)
        {
            StreamReader liczba = new StreamReader("number.txt");
            int licz = 2 * (int)((char)(liczba.Read()));
            licz = (licz / 10) + 1;
            
            StreamReader f1 = new StreamReader("lista1.txt");
            string[] tab = new string[licz];
            string[] tab1 = new string[licz];
            for (int i = 0; i < licz; i++)
            {
                tab[i] = f1.ReadLine();
                tab1[i] = f1.ReadLine();
            }
            f1.Close();

            StreamWriter sw1 = new StreamWriter("generate.txt");

            bool[] ch = new bool[licz];
            for (int i = 0; i < licz; i++)
                ch[i] = false;

            Random los = new Random();
            int losowa, losowa1;
            bool ch1 = false;
            for (int i = 0; i < (licz / 2); i++)
            {
                do
                {
                    ch1 = false;
                    losowa1 = los.Next(0, licz);
                    losowa = los.Next(0, licz);
                    if (losowa == licz || losowa1 == licz)
                        licz--;
                    if (ch[losowa] == true || ch[losowa1] == true)
                    {
                        ch1 = true;
                    }
                } while (losowa1 == losowa || ch1 == true);
                
                sw1.WriteLine(tab[losowa1] + " " + tab1[losowa1] + " - " + tab[losowa] + " " + tab1[losowa]);
            }
            sw1.Close();

            StreamReader f2 = new StreamReader("generate.txt");
            textBox1.Text = f2.ReadToEnd();
            f2.Close();
        }
0

No cóż, rozwiązanie jest dosyć proste, chociaż może czegoś nie zauważyłem.

  1. Robisz sobie listę klasy Osoba (new List<Osoba>()), do której wczytujesz wszystkie linie z pliku na wejściu. Przedtem można zrobić jeszcze np. klasę Para, która będzie przechowywać dwa obiekty typu Osoba (a klasa Osoba niech ma dwa pola, Osoba.Imie i Osoba.Nazwisko).
  2. Robisz listę obiektów Para, tj. new List<Para>();
  3. Po wczytaniu pliku wejściowego do listy z osobami, rozpoczynasz pętlę, przy czym warunkiem jej działania jest to, że w liście osób jeszcze jest co najmniej dwóch do wybrania (.Count >= 2), a w tej pętli wybierasz losowo jednego gościa, wrzucasz go do pary, usuwasz gościa z listy osób. Szukasz kolejny raz, dorzucasz go do istniejącej pary (czyli Para będzie już "gotowa"), następnie tego drugiego usuwasz z listy osób.
  4. Wrzucasz tę jedną parę do listy par.
  5. Powtarzasz cały proces do momentu, gdy już nie będzie osób do wczytania (tzn Lista<Osoba> będzie pusta, albo z jednym gościem bez pary)
  6. Po zakończeniu pętli iterujesz po gotowej liście par, wyrzucając po prostu do konsolki albo do pliku wyjściowego Para.Osoba1.Imie + Para.Osoba1.Nazwisko + ' ' + Para.Osoba2.Imie + Para.Osoba2.Nazwisko

Powodzenia : P

Zapomniałem dodać, że losowy numer wybierasz za pomocą klasy Random, gdzie Min to 0, a Max to ilość obiektów w liście-1 (a więc Random.Next(1, Lista<Osoba>.Count() - 1); i dostajesz sie do tego obiektu: Lista<Osoba>[wylosowany_numer]

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