Random is not working good - c#

I generate a string with 62 options ^ 6 letters = 56,800,235,584
But when running the code, it repeats the same string less then every 200,200 times
What is the problem here?
BTW:
This code is based on the answer here
class Program
{
static void Main(string[] args)
{
var d = new Dictionary<string, bool>();
for (int i = 0; ; i++)
{
var s = GenerateString(6);
try
{
d.Add(s, false);
}
catch (Exception ex)
{
Console.WriteLine(String.Format("{0} - {1} - {2}", i, s, ex.Message));
i = 0;
}
}
Console.ReadKey();
}
static Random _rnd = new Random();
public static string GenerateString(int len)
{
const string bigLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string smallLetters = "abcdefghijklmnopqrstuvwxyz";
const string numbers = "1234567890";
var validChars = bigLetters + smallLetters + numbers;
var result = new StringBuilder();
for (int i = 0; i < len; i++)
{
result.Append(validChars[_rnd.Next(validChars.Length)]);
}
return result.ToString();
}
}

There is all OK with random.
The problem is related with Birthday paradox. When you have 200k items one of them could repeat.
Random string doesnt garantee always unique result. For unique results you should use GUID's.

To avoid repeatation you can do a check for existence before adding the string to the list:
After for loop in GenerateString()
if(d.Contains(result.ToString()) // check whether the current generated string is in the list
{
GenerateString(len); // if it is already existed generate another one
}
else
{
return result.ToString(); // if not then return the string
}

Related

Is there a way to compare two strings in C# and get the differences only?

I am trying to compare two string in C# and get the differences between them i.e words which are not present in the other string ignoring cases and commas just focusing on the words. If one string contains two or multiple the and the second string has one the, it means this will be disregarded as it exists in both. Example I have two strings like below;
Cat meet's a dog
Cat meet's a dog and a bird
The difference between those two strings is and bird because it does not exist in the first one or vise versa and I want to get those two words and bird either in a List or a new string with spaces between them and in other words I want the words which are not present in the other string. Is there a way this can be done in C#?
Here's a way using LINQ. You don't need the "ToList()" part, but you mentioned that as one form of output you'd want:
string str1 = "Cat meet's a dog";
string str2 = "Cat meet's a dog and a bird";
string[] str1Words = str1.ToLower().Split(' ');
string[] str2Words = str2.ToLower().Split(' ');
var uniqueWords = str2Words.Except(str1Words).Concat(str1Words.Except(str2Words)).ToList();
// Do whatever you want with uniqueWords instead
Console.WriteLine($"output: {String.Join(" ", uniqueWords)}");
#ngdeveloper. This is my variant of your solution (had to post it in a separate answer because of the length):
private static StringsDiff Difference(string firststring, string secondstring)
{
StringsDiff _stringsDiff = new StringsDiff();
char[] _firstStringArray = firststring.ToCharArray();
char[] _secondStringArray = secondstring.ToCharArray();
int shortestLenght;
int longestLenght;
bool firstIsLongest;
if (_firstStringArray.Length > _secondStringArray.Length)
{
firstIsLongest = true;
shortestLenght = _secondStringArray.Length;
longestLenght = _firstStringArray.Length;
}
else
{
firstIsLongest = false;
shortestLenght = _firstStringArray.Length;
longestLenght = _secondStringArray.Length;
}
for (int i = 0; i < shortestLenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = shortestLenght; i < longestLenght; i++)
{
if (firstIsLongest)
_stringsDiff._diffList1.Add(_firstStringArray[i]);
else
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
return _stringsDiff;
}
I wrote you a simple solution, hope it will help -
The main method is called 'Difference' it receive 2 strings to compare and return an object called StringDiff.
It runs 2 loops, first comparing between the two strings char by char and then adding the rest of the longer string.
The 'StringDiff' object is a class with 2 char lists that represnt the differences of each string.
In the main method i use String.join to convert the char lists to a string and print it.
internal class Program
{
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("enter first string");
string firstString = Console.ReadLine();
Console.WriteLine("enter second string");
string secondString = Console.ReadLine();
StringsDiff _stringsDiff = Difference(firstString, secondString);
Console.WriteLine(
$"fist string difference: {string.Join("", _stringsDiff._diffList1)} / second string difference: {string.Join("", _stringsDiff._diffList2)}");
Console.WriteLine("/////////////////////////////////////");
}
}
private static StringsDiff Difference(string firststring, string secondstring)
{
StringsDiff _stringsDiff = new StringsDiff();
char[] _firstStringArray = firststring.ToCharArray();
char[] _secondStringArray = secondstring.ToCharArray();
int lenght;
if (_firstStringArray.Length > _secondStringArray.Length)
{
lenght = _secondStringArray.Length;
for (int i = 0; i < lenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = _secondStringArray.Length; i < _firstStringArray.Length; i++)
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
}
}
else
{
lenght = _firstStringArray.Length;
for (int i = 0; i < lenght; i++)
{
if (!_firstStringArray[i].Equals(_secondStringArray[i]))
{
_stringsDiff._diffList1.Add(_firstStringArray[i]);
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
for (int i = _firstStringArray.Length; i < _secondStringArray.Length; i++)
{
_stringsDiff._diffList2.Add(_secondStringArray[i]);
}
}
return _stringsDiff;
}
class StringsDiff
{
public List<char> _diffList1 = new List<char>();
public List<char> _diffList2 = new List<char>();
}
}
Remember to use "string.join" to connect the lists objects if you need a string.

C# convert XML Node string to Int32

I reading data from webservice and is not clean. I need to convert string to Int where string can be null, number or with white spaces. I make simple program to achieve this but with whitespaces my code does not hit ... If (uint.TryParse(cleanNumber, out ux)) not sure what I am missing from puzzle?
public class Program
{
static void Main(string[] args)
{
string no = "08709079777 ";
//string no = "0870777777";
Console.WriteLine("no "+ no);
Program o = new Program();
var t1 = o.ConvertStringToInt32(no);
Console.WriteLine("t1 "+ t1);
Console.ReadLine();
}
private int ConvertStringToInt32(string number)
{
int returnIntVal = 0;
try
{
if (!string.IsNullOrEmpty(number))
{
var cleanNumber = Regex.Replace(number, #"\s+", "");
uint ux;
if (uint.TryParse(cleanNumber, out ux))
{
returnIntVal = (int)ux;
}
}
else
{
returnIntVal = 0;
}
}
catch(Exception exp)
{
var ex = exp;
}
return returnIntVal;
}
}
The number 0870777777 you are trying to parse is beyond int data type range which is -2,147,483,648 to 2,147,483,647. Check the data type ranges at here.
Use the data type as long (or Int64).
private static long ConvertStringToInt32(string number)
{
long returnIntVal = 0;
try
{
if (!string.IsNullOrEmpty(number))
{
var cleanNumber = Regex.Replace(number, #"\s+", "");
if (long.TryParse(cleanNumber, out long ux))
{
returnIntVal = ux;
}
}
else
{
returnIntVal = 0;
}
}
catch(Exception exp)
{
var ex = exp;
}
Console.WriteLine("returnIntVal: " + returnIntVal);
return returnIntVal;
}
Check this fiddle - https://dotnetfiddle.net/3Luoon
Well i dont know why you complicate things but this should be really very easy to solve
public int ConvertToInt(string n) {
// Trim should solve your case where the number end or start with whitespace. but just
// incase i did the replace thing to if there is any whitespace between the numbers.
// So its upp to you if you want to retaine the replace or not.
n = n?.Replace(" ", "").Trim();
if (Int.TryParse(n, var out number))
return number;
else return 0;
}

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.

Random string with no duplicates

I'm trying to generate a 16 chars random string with NO DUPLICATE CHARS. I thoght that it shouldn't be to hard but I'm stuck.
I'm using 2 methods, one to generate key and another to remove duplicate chars. In main I've created a while loop to make sure that generated string is 16 chars long.
There is something wrong with my logic because it just shoots up 16-char string
with duplicates. Just can't get it right.
The code:
public string RemoveDuplicates(string s)
{
string newString = string.Empty;
List<char> found = new List<char>();
foreach (char c in s)
{
if (found.Contains(c))
continue;
newString += c.ToString();
found.Add(c);
}
return newString;
}
public static string GetUniqueKey(int maxSize)
{
char[] chars = new char[62];
chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
byte[] data = new byte[1];
RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
crypto.GetNonZeroBytes(data);
data = new byte[maxSize];
crypto.GetNonZeroBytes(data);
StringBuilder result = new StringBuilder(maxSize);
foreach (byte b in data)
{
result.Append(chars[b % (chars.Length)]);
}
return result.ToString();
}
string builder = "";
do
{
builder = GetUniqueKey(16);
RemoveDuplicates(builder);
lblDir.Text = builder;
Application.DoEvents();
} while (builder.Length != 16);
Consider implementing shuffle algorithm with which you will shuffle your string with unique characters and then just pick up first 16 characters.
You can do this in-place, by allocating single StringBuffer which will contain your initial data ("abc....") and just use Durstenfeld's version of the algorithm to mutate your buffer, than return first 16 chars.
There are many algorithms for this.
One easy one is:
Fill an array of chars with the available chars.
Shuffle the array.
Take the first N items (where N is the number of characters you need).
Sample code:
using System;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
Random rng = new Random();
for (int i = 0; i < 10; ++i)
{
string randomString = RandomString(16, chars, rng);
Console.WriteLine(randomString);
}
}
public static string RandomString(int n, char[] chars, Random rng)
{
Shuffle(chars, rng);
return new string(chars, 0, n);
}
public static void Shuffle(char[] array, Random rng)
{
for (int n = array.Length; n > 1; )
{
int k = rng.Next(n);
--n;
char temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
}
const string chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
var r = new Random();
var s = new string(chars.OrderBy(x => r.Next()).Take(16).ToArray());
I am using a GUID generation method it itself generates random strings and you can modify it if a number appears in the beginning,
use the code given below:
string guid = System.Guid.NewGuid().ToString("N");
while (char.IsDigit(guid[0]))
guid = System.Guid.NewGuid().ToString("N");
Hope that helps.
See if this helps:
RandomString()
{
string randomStr = Guid.NewGuid().ToString();
randomStr = randomStr.Replace("-", "").Substring(0, 16);
Console.WriteLine(randomStr);
}
This returns alpha-numeric string.

Count length of word without using Inbuilt functions

This is a question I have come across and failed
Suppose say
string str = "wordcounter";
One can easily find the Length using str.Length
However, is it possible in C# to get the number of letters, without using any inbuilt functions like Length, SubStr etc
you could write a loop and increment a counter inside this loop:
int numberOfLetters = 0;
foreach (var c in str)
{
numberOfLetters++;
}
// at this stage numberOfLetters will contain the number of letters
// that the string contains
there is also another way:
int numberOfLetters = str.ToCharArray().Length;
there is also another, even crazier way using the SysStringByteLen function which operates on a BSTR. Strings in .NET are layed out in memory by using a 4 byte integer containing the length of the string followed by that many 2 byte UTF-16 characters representing each character. This is similar to how BSTRs are stored. So:
class Program
{
[DllImport("oleaut32.dll")]
static extern uint SysStringByteLen(IntPtr bstr);
static void Main()
{
string str = "wordcounter";
var bstr = Marshal.StringToBSTR(str);
// divide by 2 because the SysStringByteLen function returns
// number of bytes and each character takes 2 bytes (UTF-16)
var numberOfLetters = SysStringByteLen(bstr) / 2;
Console.WriteLine(numberOfLetters);
}
}
Obviously doing something like this instead of using the built-in Length function should never be done in any real production code and the code shown here should not be taken seriously.
My answer is bit late, but I would like to post the same. Though all above mentioned solutions are correct, but I believe that the IL of the foreach does knows about the length of the iterable before iterating it. Talking of a pure solution, here's mine:
private int stringLength(string str) {
int length = 0;
bool done = false;
do {
try {
char c = str[length];
length++;
} catch (IndexOutOfRangeException) {
done = true;
}
} while(!done);
return length;
}
How about?
int myOwnGetStringLength(String str)
{
int count = 0;
foreach(Char c in str)
count++;
return count;
}
not very fast but yo can always loop and count the number of caracter contained.
int counter = 0;
foreach (var caracter in str)
{
counter ++;
}
class Program
{
static void Main(string[] args)
{
string Name = "He is palying in a ground.";
char[] characters = Name.ToCharArray();
StringBuilder sb = new StringBuilder();
for (int i = Name.Length - 1; i >= 0; --i)
{
sb.Append(characters[i]);
}
Console.Write(sb.ToString());
Console.Read();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter a string to find its lenght");
string ch = Console.ReadLine();
Program p = new Program();
int answer = p.run(ch);
Console.WriteLine(answer);
Console.ReadKey();
}
public int run(string ch)
{
int count = 0;
foreach (char c in ch)
{
count++;
}
return count;
}
}
My general solution involves without using 'foreach' or 'StringBuilder' (which are C# specific) or without catching any exception.
string str = "wordcounter";
str += '\0';
int x = 0;
while (str[x] != '\0')
x++;
Console.WriteLine(x); //Outputs 11
class Program
{
static void Main(string[] args)
{
string test = "test";
//string as char array:
//iterate through char collection
foreach (char c in test)
{
//do something
}
//access elements by index
Console.WriteLine("Contents of char array : {0}, {1}, {2}, {3}", test[0], test[1], test[2], test[3]);
Console.ReadKey();
}
}
namespace ConsoleApplication {
class Program {
static void Main(string[] args) {
string testString = "testing";
int x = 0;
foreach(char c in testString) {
x++;
}
Console.WriteLine("\nLength Of String:{0}", (x));
Console.Read();
}
}

Categories

Resources