Replacing string with a series of randomly generated numbers [duplicate] - c#

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
I'm trying to create a scrubbing program and I'm stuck on a bit where I have to generate a set of random numbers to replace a string of numbers and while I can get the random number once, I can't seem to figure out how to make it replace the entire nine character string.
public static int GetRandomNumber()
{
Random rnd = new Random();
// creates a number between 0 and 9
int ranNum = rnd.Next(10);
return ranNum;
}
I know it has something to do with checking against the string length and repeating until it replaces the entire string but I can't for the life of me remember how and googling is a bit too non-specific. The string itself is being pulled from a text file and has been split into an array.
public static string[] ScrubData(string line)
{
string[] words = line.Split('|');
replaceData(words);
MessageBox.Show(words[0] + words[2]);
return words;
}
private static void replaceData(string[] words)
{
words[0] = Convert.ToString(GetRandomNumber());
}
I know someone already asked a similar question, but I have no idea what "lock" is or how to connect their question with mine.

Not sure I completely understood, but it sounds like you want a method that returns a string of random numbers that is the same length as th input string? If so, this should work:
private static Random _rnd = new Random();
public static string ReplaceCharactersWithRandomNumbers(string input)
{
if (input == null) return null;
var newString = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
newString.Append(_rnd.Next(10));
}
return newString.ToString();
}
Update
I modified the code to initialize the Random outside the method. This will ensure unique numbers each time you call it. If the object is initialized in the method, it may get seeded with the same value each time it's called, and will generate the same numbers each time.
If you want to be tricky, here's a one-line way to do it:
private static readonly Random Rnd = new Random();
public static string ReplaceCharactersWithRandomNumbers(string input)
{
return input == null ? null : string.Join("", input.Select(c => Rnd.Next(10)));
}

You need to enumerate the string and rebuild the entire string. It looks like your input string is a set of tokens separated with tee ("|") marks. I use the StringBuilder because concatenation of a lot of strings is slow in .NET.
Try this ... or something similar:
public static string ScrubData(string line)
{
string[] words = line.Split('|');
System.Text.StringBuilder sb = new StringBuilder();
for (int i = 0; i < words.Length; i++)
{
sb.Append(GetRandomNumber().ToString());
if (i + 1 < words.Length)
sb.Append("|");
}
return sb.ToString();
}

Related

C# Test Box Manipulation when reading from a File

I am trying to code a simple game where my program randomly selects a word from a dictionary and stores it in a text box/or label? (Not Sure of this part). Then I have another text box where the user enters his guess.
Now I want to give the user some hint.F or example the word:
'game' would look like '_ a m _' or 'g _ _ e'. I have no preference to how the characters are placed.
I have programmed all of the previous code including the random file handling method, all timers and counter etc. I am just stuck on this part.
The program undergoes the following code :
var lines = File.ReadAllLines(#"LOCATION");
textBox3.Text = lines[new Random().Next(lines.Length)];
to select a random word from the file. However the whole word is being shown in textbox 3 and not parts of it like i wish. I am at a complete loss for ideas on how to proceed. I could not find anything similar on the web.
Cheers,
R
Once you pick a random word from file, based on length of the word, decide on how many characters you'd want to hide and then randomly replace those many characters.
something like this-
public string GetPartialWord(string word)
{
if(string.IsNullOrEmpty(word))
{
return string.Empty;
}
char[] partialWord = word.ToCharArray();
int numberOfCharsToHide = word.Length / 2;
Random randomNumberGenerator = new Random();
HashSet<int> maskedIndices = new HashSet<int>();
for(int i=0;i<numberOfCharsToHide;i++)
{
int rIndex = randomNumberGenerator.Next(0, word.Length);
while(!maskedIndices.Add(rIndex))
{
rIndex = randomNumberGenerator.Next(0, word.Length);
}
partialWord[rIndex] = '_';
}
return new string(partialWord);
}
The code below will replace at least half of the characters with underscores. The code takes a word and keeps generating random numbers until it has replaced at least half of the characters with underscores.
public string ConvertToGuessWord(string word)
{
var guessWord = word;
int lastRandom = 0;
do
{
Random rand = new Random();
int thisRandom = 0;
do
{
thisRandom = rand.Next(0, guessWord.Length);
} while (lastRandom == thisRandom);
guessWord = guessWord.Replace(guessWord[thisRandom], '_');
lastRandom = thisRandom;
} while (guessWord.Count(x => x == '_') < (word.Length / 2));
return guessWord;
}

C# Guessing Game using a text file

I'm trying to create a word guessing game that uses a dictionary text file. The game is supposed to take input from the user on how long the word should be before asking them to guess the word. If the user fails to guess after 3 times then it reveals the answer. I used a list on recommendation from a friend to read from the dictionary as it is quite large.
My question is, how can I read the list to choose a word for the guessing game?
{
static int letterLength, LettersLeft, wrongGuess;
public static void Main(string[] args)
{
string input = System.IO.File.ReadAllText("dictionary.txt");
string[] terms = input.Split();
List<string> list = new List<string>();
for (int num = 0; num < terms.Length; num++)
list.Add(terms[num]);
int wordToGuess = GetLengthOfWordToGuess();
List<string> fixedlist = new List<string>();
for (int num = 0; num < list.Count; num++)
{
string tempword = list[num];
if (tempword.Length == wordToGuess)
fixedlist.Add(tempword);
}
for (int num = 0; num < fixedlist.Count; num++)
Console.WriteLine(fixedlist[num]);
Console.WriteLine("Welcome to the guessing game");
letterLength = GetLengthOfWordToGuess();
Console.Clear();
//Not Working from here on.
string wordGuess = GetWordToGuess();
char[] maskedWord = GetHiddenLetters(wordGuess, '-');
LettersLeft = wordGuess.Length;
char userGuess;
wrongGuess = 3;
while (wrongGuess > 0 && LettersLeft > 0)
{
DispayCharacters(maskedWord);
Console.WriteLine("Enter a Letter");
userGuess = char.Parse(Console.ReadLine());
maskedWord = CheckGuess(userGuess, wordGuess, maskedWord);
}
Console.WriteLine("Well done! Thanks for Playing.");
Console.ReadLine();
}
static string GetWordToGuess()
{
Random word = new Random();
int wordNumber = word.Next(0, 9);
string[] words = { "" };
string selectWord = words[wordNumber];
return selectWord;
}
static char [] GetHiddenLetters(string word, char mask)
{
char[] hidden = new char[word.Length];
for (int i = 0; i < word.Length; i++)
{
hidden[i] = mask;
}
return hidden;
}
static void DispayCharacters(char [] characters)
{
foreach(char letter in characters)
{
Console.Write(letter);
Console.WriteLine();
}
}
static int GetLengthOfWordToGuess()
{
Console.WriteLine("Input length of word to guess");
int selectWord = int.Parse(Console.ReadLine());
return selectWord;
}
static char [] CheckGuess (char letterToCheck, string word, char [] characters)
{
bool wrong = true;
if(wrongGuess > 0)
{
for (int i = 0; i < word.Length; i++)
{
if (word[i] == letterToCheck)
{
characters[i] = word[i];
LettersLeft--;
wrong = false;
}
}
}
}
}
One major problem I see up front is that your GetWordToGuess function is not functional and probably throws an IndexOutOfRangeException.
The reason for that is that you are instantiating the words array as an array with a single empty string in it, but you are then referencing an index between 0 and 9, which will not exist in that array unless the random number generated is 0.
To solve this you should pass the fixedlist List you already created and use that instead of the words array. You should make sure to generate a random number between 0 and fixedlist.Count-1 so that you don't hit that same out of range exception. Therefore that function should look something like this:
static string GetWordToGuess(List<string> fixedlist)
{
Random word = new Random();
int wordNumber = word.Next(0, 9);
string[] words = { "" };
string selectWord = words[wordNumber];
return selectWord;
}
Also, as it stands right now, your included code doesn't compile because the CheckGuess function doesn't return a char[] as it says it should. I believe what you meant to do was have a return characters; line at the end (this was probably just a copy paste issue when you put your code in your question, but I thought I'd mention it just in case).
As a side note there are a number of small issues with your code like declaring things you don't use, but since they don't break your program I didn't want to go through and fix them.

I want to use every single letter of a word and randomize it but it doesn't work in C#

Yes I have searched a lot for a solution and yes I am a beginner and this is the first time that I asked a question through this website. I usually ask it to my teacher but I have a holiday and I am spending my free time on learning C#.
I have a task which I made up by myself and the task is a game where you have to put a word into a console application and the console has to randomize every single letter of the word so that the other player has to guess what the word is.
example : the word is "programming" and after that the console will mix up the letters of the word, so it could be "ginamrmgorp" and the player has to guess what the word is.
string woord = Console.ReadLine();
Random random = new Random();
char[] woorden = woord.ToCharArray();
for (int i = 0; i < woorden.Length; i++)
{
kiesgetal = random.Next(0, woorden.Length);
char letter = woorden[kiesgetal];
Console.Write("letter: ");
Console.WriteLine(letter);
}
Console.ReadKey();
The problem is that the console isn't using every letter of the word but the console is using some letters (not all) of the word and it puts it in the length of the word so it isn't "ginamrmgorp" but "gimmmmoopra".
Basically you wanna shuffle the character array. You can do that easily using Fisher-Yates shuffle algorithm, as implemented in this answer. Here is the modified version for arrays:
public static void Shuffle<T>(this T[] list)
{
Random rng = new Random();
int n = list.Length;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
Then just use it like this:
char[] woorden = woord.ToCharArray();
woorden.Shuffle();
string shuffledWord = new string(woorden);
Random.Next will not necessarily return a different number each time. It's entirely likely that you will get the same number muptiple times.
What you want to do is shuffle the letters, which can be done by ordering by a random number:
char[] woorden = woord.ToCharArray();
var woordenShuffled = woorden.OrderBy(c => random.Next()).ToArray();
for (int i = 0; i < woordenShuffled.Length; i++)
{
char letter = woordenShuffled[i];
Console.Write("letter: ");
Console.WriteLine(letter);
}
or if you just want to create the whole string:
string woordShuffled = new string(woord.OrderBy(c => random.Next()).ToArray());

Taking certain string characters and returning the string

I asked this question yesterday but it wasn't well received mainly due to how I asked it so ill try do better this time.
I have a string variable called message. lets say message equals "ABCDABCDABCDABCD"
now I need to do some processing on the characters in the string but not all at the same time, I want to access characters [0][4][8][12] on the first pass of the function, put each of these characters in a string and return it which is easy done if I pass an integer to my function lets say 4 and with in a for loop do
if(i % int == 0)
{
string += message[i];
}
this should return "AAAA"
the next time I call the function ill need elements [0][1], [4][5], [8][9], [12][13] and the time after that ill need [0][1][2], [4][5][6], [8][9][10], [12][13][14].
I need the characters returned in a string in the order they were taken, I could do this by changing my int I pass the function but then id need to call the function several times and do work on the returned strings to get them into the order they were taken, which I have already tried and it slowed my program down when dealing with large messages > 10k characters.
Please don't delete or put my question on hold, im quite happy to give more information on my problem if its not clear, ill seldom post to this site and usually try and find a solution myself, there are too many acceptance junkies on here for my liking. but I would appreciate some help from some of them regarding this.Thanks
Edit
I understand its not easy to figure it out and I have to say im not the best at describing it, its a vigenere cracker in WPF, I have done the kasiski examination on a piece of text and graphed out all the data, it finds the key length 90% of the time or gives me the best clue to what the key might be, now im calculating the frequency of bi,tri and quad grams of the message based on the data from the kasiski exam, lets say the key is 5 and the message is "ABCDABCDABCDABCD" im calculating probability on only the characters of the key Im changing so when I try key AAAAA im only wanting to calculate monograms on elements [0][4][9][14] of the message, ill run through 26 characters up to ZAAAA and take the most probable then I move onto element [1] of the key, lets say FAAAA gave the best score on the first element of the key. now I need elements [0][1],[5][6],[9][10][13][14] as im calculating probability on 2 pieces on the key FCAAA, so the length of the key and what key character im working on will determine what elements of the message ill be taking.
One-liner with LINQ (I use Batch extension from MoreLINQ, but you can use your own) which selects all required chars from input string:
string message = "ABCDABCDABCDABCD";
int size = 4;
int charsToTake = 2;
var characters = message.Batch(size).SelectMany(b => b.Take(charsToTake));
If you need result as string, you can easily create one:
var result = new String(characters.ToArray());
// ABABABAB
More efficient way - create your own method which will split string by substrings of required length:
public static IEnumerable<string> ToSubstrings(this string s, int length)
{
int index = 0;
while (index + length < s.Length)
{
yield return s.Substring(index, length);
index += length;
}
if (index < s.Length)
yield return s.Substring(index);
}
I would also create method for safe getting substring from start of string (to avoid annoying string length check and passing zero as start index):
public static string SubstringFromStart(this string s, int length)
{
return s.Substring(0, Math.Min(s.Length, length));
}
Now its very clear what you are doing:
var substrings = message.ToSubstrings(size)
.Select(s => s.SubstringFromStart(charsToTake));
var result = String.Concat(substrings);
Here is a simple program which does what you want, if I understand correctly:
static void Main(string[] args)
{
string data = "ABCDABCDABCDABCD";
Console.WriteLine(StrangeSubstring(data,4, 1));
// "AAAA"
Console.WriteLine(StrangeSubstring(data,4, 2));
// "ABABABAB"
Console.WriteLine(StrangeSubstring(data,4, 3));
// "ABCABCABCABC"
}
static string StrangeSubstring(string input, int modulo, int length)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.Length; ++i)
{
if (i % modulo == 0)
{
for (int j = 0; j<length; ++j)
{
if (i+j < input.Length)
sb.Append(input[i+j]);
}
}
}
return sb.ToString();
}
My solution will be like this
static string MethodName(int range){
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < str.Length ; i++){
if(i % 4 == 0){
sb.Append(str[i]);
for(int j = i + 1 ; j <= i + range ; j ++){
if(j >= str.Length)
break;
sb.Append(str[j]);
}
}
}
return sb.ToString();
}
you can parse your string to a char array :
string message="ABCDABCDABCDABCD";
char[] myCharArray = message.ToCharArray();
string result="";
for(int i=0, i<myCharArray.Length -1 ; i++)
{
if(i%4 ==0)
result+=myCharArray[i];
}
EDIT 1 :
public string[] myfunction(char[] charArray)
{
List<string> result = new List<string>();
for(int i=0, i<charArray.length -1; i=i+4)
{
result.add(charArray[i]+charArray[i+1])
}
return result.toArray();
}
This is a recursive solution. In YourFunction, PatternLength is the length of the character pattern which is repeated (so, 4 for "ABCD"), Offset is where you start in the pattern (e.g. 0 if you start with "A") and SubstringLength is the number of characters.
The function call in Main will give you all "A". If you change SubstringLength to 2, it gives you all "AB". There is no error handling, make sure then PatternLength<=Offest+SubstringLength
namespace Foo
{
class Bar
{
static void Main(string[] args)
{
Console.WriteLine(YourFunction("ABCABCABCABCABCABCABC", 3, 0,1));
Console.ReadKey();
}
static string YourFunction(string SubString, int PatternLength, int Offset, int SubstringLength)
{
string result;
if (SubString.Length <= PatternLength)
{
result = SubString.Substring(Offset, SubstringLength);
}
else
{
result = YourFunction(SubString.Substring(PatternLength, (SubString.Length - PatternLength)), PatternLength, Offset, SubstringLength) + SubString.Substring(Offset, SubstringLength);
}
return result;
}
}
}

Splitting string into an array on 16th char [duplicate]

This question already has answers here:
Splitting a string into chunks of a certain size
(39 answers)
Split string after certain character count
(4 answers)
Closed 8 years ago.
I have a text file with various 16 char strings both appended to one another and on separate lines. I've done this
FileInfo f = new FileInfo("d:\\test.txt");
string FilePath = ("d:\\test.txt");
string FileText = new System.IO.StreamReader(FilePath).ReadToEnd().Replace("\r\n", "");
CharCount = FileText.Length;
To remove all of the new lines and create one massively appended string. I need now to split this massive string into an array. I need to split it up on the consecutive 16th char until the end. Can anyone guide me in the right direction? I've taken a look at various methods in String such as Split and in StreamReader but am confused as to what the best way to go about it would be. I'm sure it's simple but I can't figure it out.
Thank you.
Adapting the answer from here:
You could try something like so:
string longstr = "thisisaverylongstringveryveryveryveryverythisisaverylongstringveryveryveryveryvery";
IEnumerable<string> splitString = Regex.Split(longstr, "(.{16})").Where(s => s != String.Empty);
foreach (string str in splitString)
{
System.Console.WriteLine(str);
}
Yields:
thisisaverylongs
tringveryveryver
yveryverythisisa
verylongstringve
ryveryveryveryve
ry
One possible solution could look like this (extracted as extension method and made dynamic, in case different token size is needed and no hard-coded dependencies):
public static class ProjectExtensions
{
public static String[] Chunkify(this String input, int chunkSize = 16)
{
// result
var output = new List<String>();
// temp helper
var chunk = String.Empty;
long counter = 0;
// tokenize to 16 chars
input.ToCharArray().ToList().ForEach(ch =>
{
counter++;
chunk += ch;
if ((counter % chunkSize) == 0)
{
output.Add(chunk);
chunk = String.Empty;
}
});
// add the rest
output.Add(chunk);
return output.ToArray();
}
}
The standard usage (16 chars) looks like this:
// 3 inputs x 16 characters and 1 x 10 characters
var input = #"1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890";
foreach (var chunk in input.Chunkify())
{
Console.WriteLine(chunk);
}
The output is:
1234567890ABCDEF
1234567890ABCDEF
1234567890ABCDEF
1234567890
Usage with different token size:
foreach (var chunk in input.Chunkify(13))
{
Console.WriteLine(chunk);
}
and the corresponding output:
1234567890ABC
DEF1234567890
ABCDEF1234567
890ABCDEF1234
567890
It is not a fancy solution (and could propably be optimised for speed), but it works and it is easy to understand and implement.
Create a list to hold your tokens. Then get subsequent substrings of length 16 and add them to the list.
List<string> tokens = new List<string>();
for(int i=0; i+16<=FileText.Length; i+=16) {
tokens.Add(FileText.Substring(i,16));
}
As mentioned in the comments, this ignores the last token if it has less than 16 characters. If you want it anyway you can write:
List<string> tokens = new List<string>();
for(int i=0; i<FileText.Length; i+=16) {
int len = Math.Min(16, FileText.Length-i));
tokens.Add(FileText.Substring(i,len);
}
Please try this method. I haven't tried it , but used it once.
int CharCount = FileText.Length;
int arrayhold = (CharCount/16)+2;
int count=0;
string[] array = new string[arrayhold];
for(int i=0; i<FileText.Length; i+=16)
{
int currentleft = FileText.Length-(16*count);
if(currentleft>16)
{
array[count]=FileText.Substring(i,16);
}
if(currentleft<16)
{
array[count]=FileText.Substring(i,currentleft);
}
count++;
}
This is the new code and provide a TRUE leftovers handling. Tested in ideone
Hope it works
Try this one:
var testArray = "sdfsdfjshdfalkjsdfhalsdkfjhalsdkfjhasldkjfhasldkfjhasdflkjhasdlfkjhasdlfkjhasdlfkjhasldfkjhalsjfdkhklahjsf";
var i = 0;
var query = from s in testArray
let num = i++
group s by num / 16 into g
select new {Value = new string(g.ToArray())};
var result = query.Select(x => x.Value).ToList();
result is List containing all the 16 char strings.

Categories

Resources