Losowa kolejność liter w stringu

0

Witam.
Zaczynam przygodę z programowaniem i proszę o pomoc.

Funkcja ta wedle planu powinna pobierać string i mieszać litery w losowej kolejności
ta linijka ma za zadanie zamianę wylosowanej litery na ostatnią w stringu żeby litery pojawiały się tylko raz

wejscie[r] = wejscie[wejscie.Length - 1];

niestety wywala mi błąd "Nie można przypisać wartości do właściwości indeksatora "string.this[int]" jest on tylko do odczytu".

Jako totalny amator proszę o pomoc i najlepiej informacje co muszę doczytać.

      static string NieOgarniam(string wejscie)
      {
          
          
          string b = "";
          Random rnd = new Random();

          for (int i = 0; i < wejscie.Length; i++)
          {
              

              int r = rnd.Next(wejscie.Length);
              b += wejscie[r];


              wejscie[r] = wejscie[wejscie.Length - 1];

            

          }
          return b;
0

Użyj String.Replace.


wejscie= wejscie.Replace(wejscie[r], wejscie[wejscie.Length - 1]);

0

Obiekty klasy string są niezmienne (immutable), więc nie możesz operować na obiekcie wejscie. Zamień najpierw string na tablicę char za pomocą metody ToCharArray(), na niej wykonaj swój algorytm, a potem zwróć nowy obiekt typu string. (Jeden z konstruktorów przyjmuje jako argument tablicę char.)

0

Jakbyś chciał, to jest jeszcze taki sposób:

string input = "T E S T";
Random rnd = new Random();
char[] output = input.ToArray().OrderBy(x => rnd.Next()).ToArray();    
Console.WriteLine(output);

// "TT ES  "
// "E  S TT"
// "T  TS E"
// "  TSE T"
// "  TT SE"
// " E  TTS"
// "TS   ET"
// "ET S  T"
// "ESTT   "
// "S T T E"
0

Ewentualnie, bez LINQ, jeszcze tak

private static string NieOgarniam(string wejscie)
        {
            string b = "";
            Random rnd = new Random();

            while (wejscie.Length>0)
            {
                int r = rnd.Next(wejscie.Length);
                b += wejscie[r];
                wejscie = wejscie.Remove(r, 1);
            }          
            return b;
        }

0

A co do dobrych praktyk - to obiekt klasy Random powinieneś mieć tylko jeden w całej aplikacji. Nie powinieneś go tworzyć za każdym razem.

0

Ja podam jeszcze inne rozwiązanie, lecz takie same jak poprzednie, ale lustrzane odbicie wcześniejszych rozwiązań.

Losujemy jedną liczbę, o wielkości silni z ilości znaków w tablicy.

reszta z dzielenia tej liczby przez liczbę wielkości silni(nie wartość silni), modulo wynik daje element, który ma być pierwszy w tablicy.
Potem liczba -1, losowa liczba podzielona przez ostatnią liczbę silni n! losowa/n-1 i modulo daje element jaki ma być drugi w tablicy, i tak dążymy do 0 tą zmienną n.

Otrzymujemy posortowaną randomowo tablicę, przy wylosowaniu zaledwie jednej liczby, która ma wielkość silni z N, czyli wszystkie możliwe kombinacje tej tablicy.

Jako, że ostatni daje 0 element, a pierwszy 1, można przenieść ostatni element na początek, ale mimo to i tak wyjdzie losowo w jednym i drugim przypadku.

0

Po przeczytaniu odpowiedzi zrobiłem to w taki sposób.

    class Program
    {
        static void Main(string[] args)
        {
          

                string[] wyrazyDoOdgadniecia = new string[] { "67890", "12345"  };

                Random rnd = new Random();

                int LosowanyWyraz = rnd.Next(wyrazyDoOdgadniecia.Length);



                Console.WriteLine(Mieszadlo(wyrazyDoOdgadniecia[LosowanyWyraz]));

            }
            
            Console.ReadKey();
            
        }
        
        //Ta funkcja ma za zadanie przestawić litery w słowie w losowej kolejności
        static string Mieszadlo(string slowo)
        {

            //zamieniam string slowo na tablice char[] znaki
            //żeby móc operować na pojedyńczych znakach
            char[] znaki = new char[slowo.Length];
            znaki = slowo.ToCharArray();

            string zmieszane = "";
            int n = znaki.Length;

            
            for (int i = 0; i < slowo.Length; i++)

            {
                //W pętli losuje liczbę z zakresu od 0 do długości tablicy znaki
                Random rnd = new Random();

                int r = rnd.Next(n);

                //dodaję znak o wylosowanym indeksie do stringa zmieszane
                zmieszane += znaki[r];

                /*aby uniknąć powtarzania się znaków wylosowany znak zastępuje 
                 * ostatnim znakiem tablicy*/
                znaki[r] = znaki[n - 1];

                /*a następnie skracam tablicę dzięki czemu przeniesiony znak 
                 * nie bierze udziału w następnej iteracji*/
                n--;

               

            }

            return zmieszane;


        }

    }
        
}

Niby wszystko działa ale po kilkakrotnym uruchomieniu okazuje że wynik mieszania powtarza się znacznie częściej jak powinien
po uruchomieniu programu 12 razy wyniki były takie:

60987 45321
87960 35241
70968 45321
60987 35241
60987 35241
60987 43251

Jak widać wyniki są raczej dalekie od losowości
Proszę o sugestie dlaczego tak się dzieje i jak poprawić algorytm.

0

@Juhas już odpowiedział na Twoje pytanie, dzień wcześniej zanim je zadałeś. Jeden Random ma być.

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