Randomize string in C# - c#

I am trying to randomize string elements, but my code is repeating strings. Can someone explain what is wrong with my code?
string[] words = Console.ReadLine().Split();
//input = "Welcome and have fun learning programming"
Random number = new Random();
for (int i = 0; i < words.Length; i++)
{
int currRandomNumber = number.Next(0, words.Length);
words[i] = words[currRandomNumber];
}
Console.WriteLine(string.Join(' ', words));
//output = "have learning learning learning learning programming"
I am facing problems with the words repeating, and it is not randomized? If you don't understand what I mean, see the comments which I added in the code. Any help will be appreciated!

The words are repeating because you are doing this:
words[i] = words[currRandomNumber];
The line means "copy the word at index currRandomNumber to the index i". As long as i and currRandomNumber are different, you are guaranteed to have a duplicate word.
What you meant to do was probably to swap the words at currRandomNumber and i:
var temp = words[i];
words[i] = words[currRandomNumber];
words[currRandomNumber] = temp;
// in C# 7, you could swap two values very easily by:
// (words[currRandomNumber], words[i]) = (words[i], words[currRandomNumber]);
Alternatively, you could use a Fisher Yates shuffling algorithm, which makes sure that each permutation have equal chances of occurring:
static void Shuffle<T>(T[] array)
{
int n = array.Length;
for (int i = 0; i < n; i++)
{
int r = i + _random.Next(n - i);
T t = array[r];
array[r] = array[i];
array[i] = t;
}
}
// Shuffle(words);

Alternatively, you can put each of the words into a new list in a random order:
List<string> words = Console.ReadLine().Split().ToList();
//input = "Welcome and have fun learning programming"
Random number = new Random();
var newwords = new List<string> ();
while (words.Count > 0)
{
int currRandomNumber = number.Next(0, words.Count);
newwords.Add( words[currRandomNumber]);
words.RemoveAt(currRandomNumber);
}
Console.WriteLine(string.Join(' ', newwords));

Related

How can I search strings inside an array using wild cards? C#

The parameter is a string that has a number in each word. I need to search that word for the number. My solution so far is to split the string up into a string array, and use Array.IndexOf to find the matching index of my search. However I haven't been able to find a way to successfully use wildcards. Using string.Contains seems to work, but searching with Array.IndexOf doesn't.
How can I search a string array element for a word that contains a number and return it's index? 1-9.
public static string Order(string words)
{
string[] wordArr = words.Split(' ');
string[] wordsOrdered = new string[words.Length];
int k;
for (int i = 0, j = 1; i < wordsOrdered.Length; i++, j++)
{
if (words.Contains($"{j}"))
{
k = Array.IndexOf(wordArr, $"{j}");
if (k != -1)
wordsOrdered[i] = wordArr[k];
}
}
return words = wordsOrdered.ToString();
}
A Regular Expression that looks for the presence of digits in your words seems the most simple solution
public static string Order(string words)
{
string[] wordArr = words.Split(' ');
string[] wordsOrdered = new string[wordArr.Length];
Regex r = new Regex(#"\d+");
for (int i = 0; i < wordArr.Length; i++)
{
var m = r.Match(wordArr[i]);
if(m.Success)
{
int index = Convert.ToInt32(m.Value);
wordsOrdered[index-1] = wordArr[i];
}
}
return string.Join(" ", wordsOrdered);
}
This code assumes that all your words have at least one number internally and the lowest number start at 1. (A 0 will result in an index out of range exception) and also you shouldn't have numbers that are greater than then count of the input words.

How to add pattern to random? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
How to add like number or character pattern to my random keygen?
and is it hard becuse im new to coding :) Thx for Help!
it took me alot of time to get to this and been stuck here for 1 and half day and can't find way to add patterns to this
Like This :
D4B6C5604E26-4F1198-44C1
EA3705694B8A-478E83-2D01
D3B8E2DE7BFC-49CF95-68E6
A6CD996B352A-48B89A-8C69
After - 4 Numbers and After second - 3 Numbers
static void Main(string[] args)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var stringChars = new char[12];
var stringChars4 = new char[6];
var stringChars7 = new char[4];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
for (int i = 0; i < stringChars4.Length; i++)
{
stringChars4[i] = chars[random.Next(chars.Length)];
}
for (int i = 0; i < stringChars7.Length; i++)
{
stringChars7[i] = chars[random.Next(chars.Length)];
}
var finalString = new String(stringChars);
var finalString4 = new String(stringChars4);
var finalString7 = new String(stringChars7);
var chars2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var stringChars2 = new char[12];
var stringChars5 = new char[6];
var stringChars8 = new char[4];
var randoms = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars2[i] = chars2[random.Next(chars.Length)];
}
for (int i = 0; i < stringChars5.Length; i++)
{
stringChars5[i] = chars2[random.Next(chars.Length)];
}
for (int i = 0; i < stringChars8.Length; i++)
{
stringChars8[i] = chars2[random.Next(chars.Length)];
}
var finalString2 = new String(stringChars2);
var finalString8 = new String(stringChars8);
var finalString5 = new String(stringChars5);
var chars3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var stringChars3 = new char[12];
var stringChars6 = new char[6];
var stringChars9 = new char[4];
var randomss = new Random();
for (int i = 0; i < stringChars3.Length; i++)
{
stringChars3[i] = chars3[random.Next(chars3.Length)];
}
for (int i = 0; i < stringChars6.Length; i++)
{
stringChars6[i] = chars3[random.Next(chars3.Length)];
}
for (int i = 0; i < stringChars9.Length; i++)
{
stringChars9[i] = chars3[random.Next(chars3.Length)];
}
var finalString3 = new String(stringChars3);
var finalString6 = new String(stringChars6);
var finalString9 = new String(stringChars9);
Console.WriteLine("Keys:");
Console.WriteLine();
Console.ReadKey();
Console.WriteLine(finalString + "-" + finalString4 + "-" + finalString7);
Console.WriteLine();
Console.ReadKey();
Console.WriteLine(finalString2 + "-" + finalString5 + "-" + finalString8);
Console.WriteLine();
Console.ReadKey();
Console.WriteLine(finalString3 + "-" + finalString6 + "-" + finalString9);
Console.WriteLine();
Console.ReadKey();
}
Assuming you are looking for "get string of random characters (from given set of characters) that formatted to given specification like 'xxx-xx-xxxx!xxx' where 'x' is random character".
Regex.Replace is a nice way to construct such string - it let you run arbitrary code to construct replacement - so replacing every 'x' with randomly selected character will produce result you seem to be looking for:
var r = new Random();
// convert string to array of strings for individual characters as Replace wants strings
var charsAsStrings = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
.Select(x=>x.ToString()).ToArray();
var result = Regex.Replace("xxx-xxx", "x",
m => charsAsStrings[r.Next(charsAsStrings.Length)]));
Notes:
make sure to read Random number generator only generating one random number to properly instantiate Random.
random numbers/strings are not unique. Presumably you will store them in some sort of list/database and re-generate the once that are not unique
using similarly-looking symbols like 'O' and '0' (or 'I', 'l','1') in strings that may need to be read by humans is not the best idea.
Create a function for the code generation, it makes the main method more readable.
private static readonly Random _random = new Random();
private static string CreateCode()
{
var bytes = new byte[11];
_random.NextBytes(bytes);
string s = BitConverter.ToString(bytes).Replace("-", "");
string result = new StringBuilder(s)
.Insert(18, '-')
.Insert(12, '-')
.ToString();
return result;
}
static void Main(string[] args)
{
const int N = 3;
var codes = new string[N];
for (int i = 0; i < N; i++) {
codes[i] = CreateCode();
Console.WriteLine(codes[i]);
}
}
I use the Random.NextBytes method to generate random bytes. We need 11 of them, because one byte is represented by 2 hex positions.
Your codes are in hexadecimal format, i,e, they contain only the letters A - F and digits. This solution uses the BitConverter to format a byte array as hexadecimal string. It produces strings like ""BD-EB-1F-0C-9B-9E-0C-F5-6E-2E-46". Therefore it is necessary to remove the "-" first.
Then I convert the string into a StringBuilder. The latter one has a Insert method that we can use to insert dashes at the required places. I insert the second one first, so that the index of the other one is not shifted.
You could also simply call Console.WriteLine(CreateCode()); three times and not create the codes array. But if you want to do other things with the codes, like saving them to a file or copy them to the cilpboard, it's better to store them somewhere.

How to randomize the word that been get on the textfile

I want to ask if how can I randomize a word that I've get from the textfile data I made.
I already have the word actually from the textfile and stored into an array of character.
Here's what I have so far
I created a method called Shuffle
void Shuffle(string[] chArr)
{
//Shuffle
for (int i = 0; i < chArr.Length; i++)
{
string tmp = chArr[i].ToString();
int r = Random.Range(i, chArr.Length);
chArr[i] = chArr[r];
chArr[r] = tmp;
}
Debug.Log(chArr);
}
and use it like this
string temp = textArray[rowsToReadFrom[0]];
temp = System.Text.RegularExpressions.Regex.Replace(temp, #"\s", "");
char[] chArr = temp.ToCharArray();
string s = chArr.ToString();
string[] ss = new string[] { s };
Shuffle(ss);
foreach (char c in chArr)
{
testObject clone = Instantiate(prefab.gameObject).GetComponent<testObject>();
clone.transform.SetParent(container);
charObjects.Add(clone.Init(c));
//Debug.Log(c);
}
It still doesn't randomize that word I get from the textfile data.
EDITTED
So far here's what I did
string temp = textArray[rowsToReadFrom[0]];
temp = System.Text.RegularExpressions.Regex.Replace(temp, #"\s", "");
char[] chArr = temp.ToCharArray();
string charResult = "";
for(int i = 0; i < chArr.Length; i++)
{
int ran = Random.Range(0, chArr.Length);
charResult += chArr[ran];
}
Debug.Log(charResult);
foreach (char c in charResult)
{
testObject clone = Instantiate(prefab.gameObject).GetComponent<testObject>();
clone.transform.SetParent(container);
charObjects.Add(clone.Init(c));
//Debug.Log(c);
}
But instead of giving me for example the word "Abandon" it would give me sometimes a randomize word "aaaabn" could someone help me out why?
I will be using Fisher–Yates_shuffle
public static string Shuffle(string str)
{
System.Random random = new System.Random();
var array = str.ToCharArray();
for (int i = 0; i < array.Length; i++)
{
int j = random.Next(i, array.Length);
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return String.Join("", array);
}
and to use it simply do
var f = "hello";
Console.WriteLine(Shuffle(f));
Your code is just getting random letters from that word but does not exclude duplicate. What you want instead is randomize the array of chars and convert it back to a string
System.Random rnd = new System.Random();
Char[] randomCharArray = chArr.OrderBy(x => rnd.Next()).ToArray();
string charResult = randomCharArray.ToString();
Unity has its own implementation of Random so be sure you use System.Random
it's most easier if you use a list (let call it initial list), (it may have some performance overheat do to shifts on remove, but i'm wonder if using a linked list would solve that...
Here what you can do if you do as i said:
Fill the list, with your words, or char, or any data which you want to randomize
Create another list or array to store randomized data in (result)
create a while loop, and check while, your initial list Has Item (count > 0)
use Random, and performe rand.Next(0, initialList.Count)
take the item within the index of random number and append it to the result list, (or replace free slot if you are using array)
List<string> initial = new List<string>();
initial.AddRange(data);
Random rand = new Random();
List<string> result = new List<string>();
while (initial.Count > 0) // LINQ: initial.Any()
{
int index = rand.Next(0, initial.Count);
result.Add(initial[index]);
initial.RemoveAt(index);
}
return result;

How to populate two separate arrays from one comma-delimited list?

I have a comma delimited text file that contains 20 digits separated by commas. These numbers represent earned points and possible points for ten different assignments. We're to use these to calculate a final score for the course.
Normally, I'd iterate through the numbers, creating two sums, divide and be done with it. However, our assignment dictates that we load the list of numbers into two arrays.
so this:
10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85
becomes this:
int[10] earned = {10,20,30,40,45,50,20,45,85};
int[10] possible = {10,20,35,50,50,50,20,90,85};
Right now, I'm using
for (x=0;x<10;x++)
{
earned[x] = scores[x*2]
poss [x] = scores[(x*2)+1]
}
which gives me the results I want, but seems excessively clunky.
Is there a better way?
The following should split each alternating item the list into the other two lists.
int[20] scores = {10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85};
int[10] earned;
int[10] possible;
int a = 0;
for(int x=0; x<10; x++)
{
earned[x] = scores[a++];
possible[x] = scores[a++];
}
You can use LINQ here:
var arrays = csv.Split(',')
.Select((v, index) => new {Value = int.Parse(v), Index = index})
.GroupBy(g => g.Index % 2,
g => g.Value,
(key, values) => values.ToArray())
.ToList();
and then
var earned = arrays[0];
var possible = arrays[1];
Get rid of the "magic" multiplications and illegible array index computations.
var earned = new List<int>();
var possible = new List<int>();
for (x=0; x<scores.Length; x += 2)
{
earned.Add(scores[x + 0]);
possible.Add(scores[x + 1]);
}
This has very little that would need a text comment. This is the gold standard for self-documenting code.
I initially thought the question was a C question because of all the incomprehensible indexing. It looked like pointer magic. It was too clever.
In my codebases I usually have an AsChunked extension available that splits a list into chunks of the given size.
var earned = new List<int>();
var possible = new List<int>();
foreach (var pair in scores.AsChunked(2)) {
earned.Add(pair[0]);
possible.Add(pair[1]);
}
Now the meaning of the code is apparent. The magic is gone.
Even shorter:
var pairs = scores.AsChunked(2);
var earned = pairs.Select(x => x[0]).ToArray();
var possible = pairs.Select(x => x[1]).ToArray();
I suppose you could do it like this:
int[] earned = new int[10];
int[] possible = new int[10];
int resultIndex = 0;
for (int i = 0; i < scores.Count; i = i + 2)
{
earned[resultIndex] = scores[i];
possible[resultIndex] = scores[i + 1];
resultIndex++;
}
You would have to be sure that an equal number of values are stored in scores.
I would leave your code as is. You are technically expressing very directly what your intent is, every 2nd element goes into each array.
The only way to improve that solution is to comment why you are multiplying. But I would expect someone to quickly recognize the trick, or easily reproduce what it is doing. Here is an excessive example of how to comment it. I wouldn't recommend using this directly.
for (x=0;x<10;x++)
{
//scores contains the elements inline one after the other
earned[x] = scores[x*2] //Get the even elements into earned
poss [x] = scores[(x*2)+1] //And the odd into poss
}
However if you really don't like the multiplication, you can track the scores index separately.
int i = 0;
for (int x = 0; x < 10; x++)
{
earned[x] = scores[i++];
poss [x] = scores[i++];
}
But I would probably prefer your version since it does not depend on the order of the operations.
var res = grades.Select((x, i) => new {x,i}).ToLookup(y=>y.i%2, y=>y.x)
int[] earned = res[0].ToArray();
int[] possible = res[1].ToArray();
This will group all grades into two buckets based on index, then you can just do ToArray if you need result in array form.
here is an example of my comment so you do not need to change the code regardless of the list size:
ArrayList Test = new ArrayList { "10,10,20,20,30,35,40,50,45,50,45,50,50,50,20,20,45,90,85,85" };
int[] earned = new int[Test.Count / 2];
int[] Score = new int[Test.Count / 2];
int Counter = 1; // start at one so earned is the first array entered in to
foreach (string TestRow in Test)
{
if (Counter % 2 != 0) // is the counter even
{
int nextNumber = 0;
for (int i = 0; i < Score.Length; i++) // this gets the posistion for the next array entry
{
if (String.IsNullOrEmpty(Convert.ToString(Score[i])))
{
nextNumber = i;
break;
}
}
Score[nextNumber] = Convert.ToInt32(TestRow);
}
else
{
int nextNumber = 0;
for (int i = 0; i < earned.Length; i++) // this gets the posistion for the next array entry
{
if (String.IsNullOrEmpty(Convert.ToString(earned[i])))
{
nextNumber = i;
break;
}
}
earned[nextNumber] = Convert.ToInt32(TestRow);
}
Counter++
}

generating string from exited characters

I have a character array as shown below :
char[] pwdCharArray = "abcdefghijklmnopqrstuvwxyzABCDEFG" +
"HIJKLMNOPQRSTUVWXYZ0123456789`~!##$%^&*()-_=+[]{}\\|;:'\",<" +
".>/?".ToCharArray();
and from this char array, i want to generate a string of minimum length 7 and all the characters in the string should be from the above char array.
How to do this operation?
What's the maximum length? (You may want to parameterize the methods below to specify a minimum and maximum length.) Here's a simple way of doing it for exactly 7 characters:
Here's the C# version:
public string GeneratePassword(Random rng)
{
char[] chars = new char[7];
for (int i = 0; i < chars.Length; i++)
{
chars[i] = pwdCharArray[rng.Next(pwdCharArray.Length)];
}
return new string(chars);
}
Note that the Random instance should be passed in to avoid the common problem of creating many instances of Random. I have an article describing this problem and ways around it. In essence, you should use one instance of Random per thread - don't create a new instance every time you want to use one, and don't reuse the same instance across multiple threads.
In fact, for a genuine password which is guarding sensitive information, you probably shouldn't be using Random at all, but rather something like RNGCryptoServiceProvider (or less directly, the results of RandomNumberGenerator.Create()). This can be somewhat harder to use, but will give you much more secure random numbers.
In Java it would be pretty similar, but then I'd use SecureRandom (which is fortunately rather easier to use than its .NET counterpart). In this case, you can create a new instance each time:
public String generatePassword() {
char[] chars = new char[7];
SecureRandom rng = new SecureRandom();
for (int i = 0; i < chars.length; i++) {
chars[i] = pwdCharArray[nextInt(pwdCharArray.length)];
}
return new String(chars);
}
Generate 7 random numbers between 0 and yourArray.length -1.
Pick the corresponding char in the array and put it in your final String.
Here is the code with a StringBuilder:
StringBuilder sb = new StringBuilder();
Random random = new Randdom();
for(int i=0; i<7; i++) {
sb.append(pwdCharArray[random.nextInt(0, pwdCharArray.length -1)]);
}
return sb.toString();
(C# example)
Random rand = new Random();
char[] arr = new char[rand.Next(7,15)];
for(int i = 0 ; i < arr.Length ; i++) {
arr[i] = pwdCharArray[rand.Next(pwdCharArray.Length)];
}
string pwd = new string(arr);
Here is a solution in Java, with variable length of the word, and test of working:
import java.util.*;
public class RandomWord {
// Valid characters
private static String VALID_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFG" +
"HIJKLMNOPQRSTUVWXYZ0123456789`~!##$%^&*()-_=+[]{}\\|;:'\",<.>/?";
// Minimal length thw word can have
private static int MIN_LENGTH = 7;
// Maximal length will be MIN_LENGTH + THRESHOLD - 1
private static int THRESHOLD = 10;
// Generate a random number generator.
// The time in millis is used as seed prevents the numbers to be always the same in same order
Random randomGenerator = new Random(System.currentTimeMillis());
public String generateWord () {
// Actual length of the word (from MIN_LENGTH to MIN_LENGTH + THRESHOLD - 1)
int length = MIN_LENGTH + randomGenerator.nextInt(THRESHOLD);
// Loop for every character
StringBuilder word = new StringBuilder();
for (int i = 0; i < length; i++) {
// Appends one more random char
word.append(VALID_CHARACTERS.charAt(randomGenerator.nextInt(VALID_CHARACTERS.length())));
}
// Returns the random word
return word.toString();
}
// Test the class
public static void main (String[] args) {
// Instantiates and tests the class
RandomWord randomWord = new RandomWord();
for (int i = 0; i < 30; i++) {
String word = randomWord.generateWord();
System.out.println(word + " (" + word.length() + ")");
}
}
}

Categories