C# random letter generator with specified ratio of consonants:vowels - c#

I need to create code to scatter 50 random letters into the console (It's a "Snake" game); that part, I didn't have a problem with. I used this code to generate the letters (the "scatter them around the console" part I'm handling once I know how to fix the problem)
Random rand = new Random();
int number = rand.Next(0, 26);
char letter = (char)('a' + number);
It generates random letters just fine, but the instructions for the problem specify the ratio of consonants to vowels must be 4:1, and I have no idea how to make that part happen.

Create a pair of static strings:
String consonants = "BCDFGHJKLMNPQRSTVWXYZ";
String vowels = "AEIOU";
Generate a random number between 1..5 (or 0..4). If the number is 1 (0), pick a random character from the vowels list. Otherwise pick a random character from the consonants list.
Alternately, if you need exactly the ratio of 4:1, use a for-loop in place of the first random number generator, to wit:
for ( i = 0; i < 50; i++ )
{
if ( i % 5 == 0 )
// select a vowel at random
else
// select a consonant at random
}
EDIT: Complete solution. I'm writing my fifty characters to an array then printing them to the console. You can pass theChar to your output method.
public void RandomChars()
{
Random random = new Random();
String consonants = "BCDFGHJKLMNPQRSTVWXYZ";
String vowels = "AEIOU";
StringBuilder result = new StringBuilder();
for (int i = 0; i < 50; i++)
{
char theChar;
if (i % 5 == 0)
{
theChar = vowels[random.Next(vowels.Length)];
}
else
{
theChar = consonants[random.Next(consonants.Length)];
}
result.Append(theChar);
}
Console.WriteLine(result.ToString());
}

Related

Pertaining to random and non-repeating numbers

My code is supposed to generate random and non-repeating numbers, but when I print it it doesn't do it properly and sometimes it repeats itself. How can I fix?
Console.WriteLine("choose how many digits your password should be\nminimum 5 maximum 10 digits");
Console.Write("number of digits:");
int digit = int.Parse(Console.ReadLine());
int[] passwordarray = new int[digit];
Random r = new Random();
for (int i = 0; i < passwordarray.Length; i++)
{
if (digit <= 10 && digit >= 5)
{
do
{
passwordarray[i] = r.Next(0, 10);
} while (!(passwordarray.Contains(passwordarray[i])));
}
else
{
Console.WriteLine("your number of digits is less than 5 or more than 10");
}
}
I restructured your code:
Console.WriteLine("choose how many digits your password should be\nminimum 5 maximum 10 digits");
Console.Write("number of digits:");
int digit = int.Parse(Console.ReadLine());
int[] passwordarray = new int[digit];
Random r = new Random();
// check the digits first
if (digit <= 10 && digit >= 5)
{
int tempVal;
for (int i = 0; i < passwordarray.Length; i++)
{
// generate values until you have a value thats not in the array
do
{
tempVal = r.Next(0, 10);
} while (passwordarray.Contains(tempVal));
// add the value
passwordarray[i] = tempVal;
}
}
Basically you want to check first if the digits are between 5 and 10, then iterate trough your array, generate random values until you have one that isn't in the password array yet, and add this value. I just restructured your code, I didn't run it.
EDIT: obviously there are better solutions to implement this behavior, like Dmitrys answer, I restructured the code just to show you where your logic is wrong

Obtain the lexicographically smallest string possible, by using at most P points

⦁ Replace and/or re-arrange characters of this given string to get the lexicographically smallest string possible. For this, you can perform the following two operations any number of times.
⦁ Swap any two characters in the string. This operation costs 1 point. (any two, need not be adjacent)
⦁ Replace a character in the string with any other lower case English letter. This operation costs 2 points.
Obtain the lexicographically smallest string possible, by using at most P points.
Input:
⦁ Two lines of input, first-line containing two integers N, P.
⦁ The second line contains a string S consisting of N characters.
Output:
Lexicographically smallest string obtained.
for e.g
Sample Input:
3 3
bba
Sample Output:
aab
Ive tried this but it doesnt contain P points i dont know how to do that can you guys please help me with that:
namespace Lexicographical
{
class GFG
{
// Function to return the lexicographically
// smallest String that can be formed by
// swapping at most one character.
// The characters might not necessarily
// be adjacent.
static String findSmallest(char[] s)
{
int len = s.Length;
// Store last occurrence of every character
int[] loccur = new int[26];
// Set -1 as default for every character.
for (int i = 0; i < 26; i++)
loccur[i] = -1;
for (int i = len - 1; i >= 0; --i)
{
// char index to fill
// in the last occurrence array
int chI = s[i] - 'a';
if (loccur[chI] == -1)
{
// If this is true then this
// character is being visited
// for the first time from the last
// Thus last occurrence of this
// character is stored in this index
loccur[chI] = i;
}
}
char[] sorted_s = s;
Array.Sort(sorted_s);
for (int i = 0; i < len; ++i)
{
if (s[i] != sorted_s[i])
{
// char to replace
int chI = sorted_s[i] - 'a';
// Find the last occurrence
// of this character.
int last_occ = loccur[chI];
// Swap this with the last occurrence
char temp = s[last_occ];
s[last_occ] = s[i];
s[i] = temp;
break;
}
}
return String.Join("", s);
}
// Driver code
public static void Main(String[] args)
{
String s = "abb";
Console.Write(findSmallest(s.ToCharArray()));
}
}
}
The output for this is abb but it should be aab...
I want to know how i can use above Question in this

Creating strings from a template by replacing placeholders by all permutations of an input set

I want to make a simple generator of strings.
User inputs a "template" for string. Template can have placeholders in any place in it.
Then he inputs possible characters that can fit into any placeholder in string.
How it should work:
INPUT:
a.b.
123
OUTPUT:
[
"a1b1", "a1b2", "a1b3",
"a2b1", "a2b2", "a2b3",
"a3b1", "a3b2", "a3b3"
]
I found some of my old python code, but i don't understand it at all.
I split the input string to array of strings and array of dots.
Then I tried to increment just dots and each time just concat those two arrays in the right way.
But I found a new trouble.
string[] splitted = kt_NonCur.Split('.'); // array of constant strings
char[] nch = new char[splitted.Length - 1]; // array of new chars (generated)
char lgc = goodLetters.Last( ); // last good char
for( int i = 0; i < nch.Length - 1; i++ ) // set up all nch to first letter
nch[i] = goodLetters[0];
while( nch.Last( ) != lgc ) { // until last nch is set to last good char
outputData.Add($"{concatsplit(splitted, nch)}"); // concatsplit(s,n) concatenates two arrays into string
nch[0] = up(nch[0]); // up(char) gets next character from goodLetters. If there is no next, it returns first letter.
if( nch[0] == goodLetters[0] ) {
nch[1] = up(nch[1]);
if(nch[1] == goodLetters[0]){
nch[2] = up(nch[2]);
// .
// .
// .
}
}
}
And the problem is: I am facing a dilemma. Either find better way, or limit number of placeholders so that the code ladder is not too long. Of course I would add then some code that checks if it is the last and stop executing code for others, but I still would have to make
You can look at your problem this way: if you have P placeholders in your input string and the number of replacement characters is R, to construct every possibe output string you need at each step P numbers [0...R-1] (which can then serve as index into the replacement character list). Well, this is the definition of an integer with P digits in base R.
So let's write a helper class representing such integers:
class NDigitNumber
{
int[] _digits;
int _base;
// construct an integer with the specified numer of digits in the specified base
public NDigitNumber(int digits, int #base)
{
_digits = new int[digits];
_base = #base;
}
// get the digit at the specified position
public int this[int index] => _digits[index];
// increment the number, returns false on overflow
public bool Increment()
{
for (var pos = 0; pos < _digits.Length; pos++)
{
if (++_digits[pos] < _base)
break;
if (pos == _digits.Length-1)
return false;
for (var i = 0; i <= pos; i++)
_digits[i] = 0;
}
return true;
}
}
The Increment methods works like these mechanical counter devices where each digit wheel, when rotated from its maximum digit to the next, resets itself and all lower wheels to 0 and increments the next higher wheel.
Then we only have to iterate over all possible such integers to get the desired output:
var input = "a.b.";
var placeholder = '.';
var replacements = new[] { '1', '2', '3' };
// determine positions of placeholder in string
var placeholderPositions = new List<int>();
for (var i = 0; i < input.Length; i++)
{
if (input[i] == placeholder)
placeholderPositions.Add(i);
}
// iterate over all possible integers with
// placeholderPositions.Count digits
// in base replacements.Length
var number = new NDigitNumber(placeholderPositions.Count, replacements.Length);
do
{
var result = new StringBuilder(input);
for (var i = 0; i < placeholderPositions.Count; i++)
result[placeholderPositions[i]] = replacements[number[i]];
Console.WriteLine(result.ToString());
} while(number.Increment());
Output:
a1b1
a2b1
a3b1
a1b2
a2b2
a3b2
a1b3
a2b3
a3b3
Based on accepted answer of this post:
public static IEnumerable<string> Combinations(string template, string str, char placeholder)
{
int firstPlaceHolder = template.IndexOf(placeholder);
if (firstPlaceHolder == -1)
return new string[] { template };
string prefix = template.Substring(0, firstPlaceHolder);
string suffix = template.Substring(firstPlaceHolder + 1);
var recursiveCombinations = Combinations(suffix, str, placeholder);
return
from chr in str
from recSuffix in recursiveCombinations
select prefix + chr + recSuffix;
}
Usage:
List<string> combinations = Combinations("a.b.", "123", '.').ToList();

Insert random amount of dots to string with minimum different places?

I want to insert a random amount of dots (from 1 to 7) on random parts of a string without breaking the layout.
This is my current code:
Random rand = new Random();
string[] words = iTemplate.Text.Split(' ');
string result = string.Empty;
for (int i = 0; i < words.Count(); i++)
{
string word = words[i];
if (rand.Next(i, words.Count()) == i)
{
for (int dots = rand.Next(1, 7); dots > 0; dots--)
word += ".";
}
result += word + " ";
}
Is there a more efficient or nice LINQ option to it ?
Right now, since its random, there may be cases of no dots showing up. I have narrowed it by using if (rand.Next(i, words.Count()) == i) which seems to work but still some results only show 1 to 3 places having dots inserted.
How could I guarantee that the dots are inserted a minimum of 4 different places during the process ?
Sample data/result as per comment request:
string template = "Hi, this is a template with several words on it and I want to place random dots on 4 different random places every time I run the function";
Result 1:
string result = "Hi, this... is a template with several.. words on it and. I want to place random dots on 4 different random...... places every time I run the function";
Result 2:
string result = "Hi, this is a template. with several... words on it and I want to..... place random dots on 4 different random. places every time I run the function";
Result 3:
string result = "Hi, this. is a template with... several words on it and I want to place random.. dots on 4 different random....... places every time I run the.. function";
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class Program
{
static void Main(string[] args)
{
Random rand = new Random();
string[] words = "Now is the time for all good men to come to the aid of their countrymen".Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (words.Length > 0)
{
// Generate a list of integers from 0 to words.Length - 1
List<int> addIndices = Enumerable.Range(0, words.Length).ToList();
// Shuffle those indices
Shuffle(addIndices, rand);
// Pick the number of words that will have dots added
int addCount = rand.Next(4, Math.Max(4, words.Length));
// Truncate the array so that it only contains the first addCount items
addIndices.RemoveRange(addCount, addIndices.Count - addCount);
StringBuilder result = new StringBuilder();
for (int i = 0; i < words.Length; i++)
{
result.Append(words[i]);
if (addIndices.Contains(i)) // If the random indices list contains this index, add dots
result.Append('.', rand.Next(1, 7));
result.Append(' ');
}
Console.WriteLine(result.ToString());
}
}
private static void Shuffle<T>(IList<T> array, Random rand)
{
// Kneuth-shuffle
for (int i = array.Count - 1; i > 0; i--)
{
// Pick random element to swap.
int j = rand.Next(i + 1); // 0 <= j <= i
// Swap.
T tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
}
This will ensure that you add dots to at least 4 words, as well as not adding a trailing space to your final string.
Random rand = new Random();
string[] words = iTemplate.Text.Split(' ');
// Insert dots onto at least 4 words
int numInserts = rand.Next(4, words.Count());
// Used later to store which indexes have already been used
Dictionary<int, bool> usedIndexes = new Dictionary<int, bool>();
for (int i = 0; i < numInserts; i++)
{
int idx = rand.Next(1, words.Count());
// Don't process the same word twice
while (usedIndexes.ContainsKey(idx))
{
idx = rand.Next(1, words.Count());
}
// Mark this index as used
usedIndexes.Add(idx, true);
// Append the dots
words[idx] = words[idx] + new String('.', rand.Next(1, 7));
}
// String.Join will put the separator between each word,
// without the trailing " "
string result = String.Join(" ", words);
Console.WriteLine(result);
This code assumes that you do in fact have at least 4 words in iTemplate.Text. If there's a chance that you won't, you should add some additional validation logic.
Well, if you need at least 4 different places, you need at least four dots. You do it in two parts - first choose the 4 words that get a dot at the end (that is, choose a word at random, add a dot to it, and make sure you don't choose it again), then choose 3 words at random, with repetitions, and add dots to them.
Just for fun and as terse as I can make it:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var random = new Random();
var iTemplate = "Hi, this is a template with several words on it and I want to place random dots on 4 different random places every time I run the function";
var result = iTemplate;
while (new Regex("\\. ").Matches(result).Count < 4)
result = result.TrimEnd()
.Split(' ')
.Aggregate(
string.Empty,
(current, word) =>
current + (word + (((word.EndsWith(".") || (random.Next(1, 100) % 10) != 0)) ? "" : new string('.', random.Next(1, 7))) + " ")
);
Console.WriteLine(result);
Console.Read();
}
}
}

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