Unity random characters in string - c#

How do I repeat generating a random char? I want to make a glitched text effect so I set:
textbox.text = st[Random.Range(0, st.Length)];
in my update method. I do however only get one character out of this line - how would I repeat this process in a string with the length of 5? What I am trying to achieve is to randomly generate 5 characters over and over again. There must be a better way than this:
randomChar + randomChar + randomChar + randomChar + randomChar
Thank you in advance!

Could use something similar:
public static readonly char[] CHARS = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
static void Main(string[] args)
{
static string GenerateGlitchedString(uint wordCount,uint wordslength)
{
string glitchedString = "";
for (int i = 0; i < wordCount; i++)
{
for (int j = 0; j < wordslength; j++)
{
Random rnd = new Random();
glitchedString += CHARS[rnd.Next(CHARS.Length)];
}
glitchedString += " "; //Add spaces
}
return glitchedString;
}
string output = GenerateGlitchedString(5, 5);
Console.WriteLine(output);
}

You can use Linq to generate any number of random characters from an enumerable:
int howManyChars = 5;
var newString = String.Join("", Enumerable.Range(0, howManyChars).Select(k => st[Random.Range(0, st.Length)]));
textbox.text = newString;

If you want completely glitchy strings, go the way of Mojibake. Take a string, convert it to one encoding and then decode it differently. Most programmers end up familiar with this kind of glitch eventually. For example this code:
const string startWith = "Now is the time for all good men to come to the aid of the party";
var asBytes = Encoding.UTF8.GetBytes(startWith);
var glitched = Encoding.Unicode.GetString(asBytes);
Debug.WriteLine(glitched);
consistently results in:
潎⁷獩琠敨琠浩⁥潦⁲污潧摯洠湥琠潣敭琠桴⁥楡⁤景琠敨瀠牡祴
But, if you just want some text with some random glitches, how about something like this. It uses a set of characters that should be glitched in, a count of how many glitches there should be in a string (based on the string length) and then randomly inserts glitches:
private static Random _rand = new Random();
private const string GlitchChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%&";
public static string GlitchAString(string s)
{
var glitchCount = s.Length / 5;
var buffer = s.ToCharArray();
for (var i = 0; i < glitchCount; ++i)
{
var position = _rand.Next(s.Length);
buffer[position] = GlitchChars[_rand.Next(GlitchChars.Length)];
}
var result = new string(buffer);
Debug.WriteLine(result);
return result;
}
The first two times I ran this (with that same Now is the time... string), I got:
Original String:
Now is the time for all good men to come to the aid of the party
First Two Results:
LowmiW HhZ7time for all good mea to comX to ths aid oV the p1ray
Now is fhO P!me forjall gKod men to #ome to the a#d of F5e Nawty
The algorithm is, to some extent, tunable. You can have more or fewer glitches. You can change the set of glitch chars - whatever you'd like.

Related

Display the the total amount of the same vowel

I am trying to display the total number of the same vowels when I input a word. For example : cheesecake.
Total vowels are 5 (e,e,e,a,e) and the total number of the same vowels (which is 'e') is 4.
The code I did,is still showing the number of the same vowels to 5.
Is there something wrong on my code?
static void Main()
{
Console.Write("Enter a word or phrase : ");
string input = Console.ReadLine();
char[] listOfVowels = new char[] { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };
int vowel = 0;
int sameVowel = 0;
for (int i = 0; i < input.Length; i++)
{
if (listOfVowels.Contains(input[i]))
{
Console.WriteLine(input[i]);
vowel++;
if(input[i] == input[i])
{
sameVowel++;
}
}
}
Console.WriteLine($"The total number of vowel are : {vowel}");
Console.WriteLine($"The total of the same number of vowel are : {sameVowel}");
}
The total number of vowel are : 5
The total of the same number of vowel are : 5
You can try this code, create a list to store vowel, and use linq to count same vowel
static void Main(string[] args)
{
Console.Write("Enter a word or phrase : ");
string input = Console.ReadLine();
char[] listOfVowels = new char[] { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };
int vowel = 0;
int sameVowel = 0;
List<char> vowers = new List<char>();
for (int i = 0; i < input.Length; i++)
{
if (listOfVowels.Contains(input[i]))
{
Console.WriteLine(input[i]);
vowel++;
vowers.Add(input[i]);
//if(vowers.Contains(input[i]))
//{
// sameVowel++;
//}
}
}
sameVowel = vowers.GroupBy(_ => _).Where(_ => _.Count() > 1).Sum(_ => _.Count());
Console.WriteLine(string.Format("The total number of vowel are : {0}", vowel));
Console.WriteLine(string.Format("The total of the same number of vowel are : {0}", sameVowel));
Console.ReadLine();
}
Following the pillars of OOP and the Single Responsibility Principle, you could encapsulate this logic into a class that will handle this logic for you
Class
public class VowelStatistics
{
private readonly string word;
public VowelStatistics(string word)
{
this.word = word;
}
public IEnumerable<char> Vowels => word.Where(c => "aeiouAEIOU".Contains(c));
public int VowelCount => Vowels.Count();
public char MostFrequentVowel => Vowels
.GroupBy(c => c)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.First();
public int MostFrequentVowelCount => Vowels
.GroupBy(c => c)
.Max(g => g.Count());
// Adding this as per #Everyone's comment, which will give you vowel groupings by frequency.
public IEnumerable<IGrouping<char, char>> VowelsByFrequency => Vowels
.GroupBy(c => c)
.OrderByDescending(g => g.Count());
}
Usage
VowelStatistics vs = new VowelStatistics("cheesecake");
Results
vs.Vowels = { 'e', 'e', 'e', 'a', 'e' }
vs.VowelCount = 5
vs.MostFrequentVowel = 'e'
vs.MostFrequentVowelCount = 4
Your code can be simplified:
static void Main()
{
Console.Write("Enter a word or phrase : ");
string input = Console.ReadLine()/*"cheesecake"*/;
char[] listOfVowels = new char[] { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };
int vowel = 0;
vowel = input.Count(z => listOfVowels.Contains(z));
var sameVowelPair = input.Where(c => listOfVowels.Contains(c)).GroupBy(c => c).ToDictionary(s1 => s1.Key, s1=> s1.Count()).OrderByDescending(w => w.Value).FirstOrDefault();
Console.WriteLine($"The total number of vowel are : {vowel}");
Console.WriteLine($"The total of the same number of vowel are : {sameVowelPair.Value}");
}
Outputs:
The total number of vowel are : 5
The total of the same number of vowel are : 4
Take a look at this (no LINQ involved):
static (int, char, int) vowelStats(string str)
{
// VOWEL ONLY DICTIONARY
Dictionary<char, int> counts = new Dictionary<char, int>()
{
{'a', 0} , { 'e', 0} , { 'i', 0} , { 'o', 0} , { 'u', 0}
};
int vowels = 0;
char high = '\0';
foreach(char c in str)
{
char c1 = Char.ToLower(c); // convert letter to lowercase first
// if dictionary has the character, then it must be a vowel
if (counts.ContainsKey(c1))
{
counts[c1]++; // vowel itself count
vowels++; // total vowel count
if (!counts.ContainsKey(high)) high = c1; // will only be true once
if(vowels - counts[c1] < vowels - counts[high]) // update current most frequent
high = c1;
}
}
if(!counts.ContainsKey(high)) // if no vowels found, high will be '\0'
return (0, '\0', 0);
return (vowels, high, counts[high]);
}
static void Main(string[] args)
{
Console.Write("Enter a word or phrase : ");
string input = Console.ReadLine();
int vowels, mostFrequentVowelCount;
char mostFrequenctVowel;
(vowels, mostFrequenctVowel, mostFrequentVowelCount) = vowelStats(input);
Console.WriteLine("Total number of vowels: {0}", vowels);
Console.WriteLine("Most frequent vowel: {0}", mostFrequenctVowel);
Console.WriteLine("Most frequent vowel count: {0}", mostFrequentVowelCount);
}
Output:
Enter a word or phrase : cheesecake
Total number of vowels: 5
Most frequent vowel: e
Most frequent vowel count: 4
Notes:
1) I assumed what you meant by "same vowel" is "the most frequent vowel".
2) The code will only work (as is) in .Net Framework 4.7 or higher (tuple functions) OR .Net Core 2 or higher.
3) Time complexity: O(N) where N is the number of characters in the string.
4) Space complexity: O(C) where C is a constant representing the number of vowels and their corresponding integers in the Dictionary, plus the few other variables.
5) In case of two vowels having been the most frequent, this function will pick the one that was encountered first. That is, in case of "woohee" it will be 'o', and in case of "weehoo" it will be 'e'.
6) I updated the code so it does not care about uppercase/lowercase. If it encounters a vowel regardless of its case, it will update one and only one counter.
7) This does not use any LINQ and should be simple enough for basic C#. The reason I used no LINQ is because of its added complexity and overhead to performance.
This is nice and simple for me:
string input = "cheesecake";
var query =
from v in "aeiouAEIOU"
join c in input on v equals c
group c by c into gcs
orderby gcs.Count() descending
select gcs;
Console.WriteLine($"Vowels: {String.Join(", ", query.SelectMany(c => c))}");
Console.WriteLine($"Most Frequent Vowel: {query.First().Key}");
Console.WriteLine($"Most Frequent Vowel Count: {query.First().Count()}");
That gives:
Vowels: e, e, e, e, a
Most Frequent Vowel: e
Most Frequent Vowel Count: 4
Performance testing code:
static (int, char, int) vowelStatsPlain(string str)
{
// VOWEL ONLY DICTIONARY
Dictionary<char, int> counts = new Dictionary<char, int>()
{
{'a', 0} , { 'e', 0} , { 'i', 0} , { 'o', 0} , { 'u', 0}
};
int vowels = 0;
char high = '\0';
foreach (char c in str)
{
char c1 = Char.ToLower(c); // convert letter to lowercase first
// if dictionary has the character, then it must be a vowel
if (counts.ContainsKey(c1))
{
counts[c1]++; // vowel itself count
vowels++; // total vowel count
if (!counts.ContainsKey(high)) high = c1; // will only be true once
if (vowels - counts[c1] < vowels - counts[high]) // update current most frequent
high = c1;
}
}
if (!counts.ContainsKey(high)) // if no vowels found, high will be '\0'
return (0, '\0', 0);
return (vowels, high, counts[high]);
}
static (int, char, int) vowelStatsLinq(string str)
{
var query =
(
from v in "aeiouAEIOU"
join c in str on v equals c
group c by c into gcs
orderby gcs.Count() descending
select gcs
).ToArray();
var first = query.First();
return (query.SelectMany(c => c).Count(), first.Key, first.Count());
}
static void Main(string[] args)
{
string input = "The information contained in this email is confidential and for the addressee only; If you are not the intended recipient of this email, please reply and let us know that an incorrect address may have been used. If you do not wish to be communicated with by email, please respond so that we may remove your address from our records. Your co-operation is appreciated.";
Func<TimeSpan> callPlain = () =>
{
var sw = Stopwatch.StartNew();
(int vowels, char mostFrequenctVowel, int mostFrequentVowelCount) = vowelStatsPlain(input);
sw.Stop();
return sw.Elapsed;
};
Func<TimeSpan> callLinq = () =>
{
var sw = Stopwatch.StartNew();
(int vowels, char mostFrequenctVowel, int mostFrequentVowelCount) = vowelStatsLinq(input);
sw.Stop();
return sw.Elapsed;
};
var trials = Enumerable.Range(0, 1000000).Select(x => new { plain = callPlain(), linq = callLinq() }).ToArray();
Console.WriteLine(trials.Skip(2).Average(x => x.plain.TotalMilliseconds));
Console.WriteLine(trials.Skip(2).Average(x => x.linq.TotalMilliseconds));
Console.WriteLine(trials.Skip(2).Average(x => x.linq.TotalMilliseconds) / trials.Skip(2).Average(x => x.plain.TotalMilliseconds));
}

How to sort an array of non-english (Slovanian) words in C#?

I have a string composes of Slovenian characters such as (žiga, špela, črt, ...) and i need to sort this string alphabetically, the problem i want to do that using loops only without using any builtin function in .NET like array.Sort().
static string[] SortByName(string[] fullname)
{
char[] abc =
{
'a', 'b', 'c', 'č', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 'š','t', 'u', 'v', 'z', 'ž'
};
int counter = 0;
for (int i = 0; i<abc.Length;i++)
{
for (int j = 0; j < fullname[counter].Length; j++)
{
// I still cant figure out what i can do here
}
counter++;
}
}
In your program, the char array abc stores all the Slovenian alphabets in order. You can use this array as a reference to the ranks of all the Slovene alphabets to compare the Slovene words. In the code below, I have defined a method CompareSl() to compare Slovene words, just like the Compare() method of the String class compares English words. (The method index() returns the index of a character in the array abc.)
The Compare() method of the String class takes two strings s1 and s2 as arguments and
♦ Returns 0 if the strings are equal
♦ Returns (+)ve if s1 > s2
♦ Returns (-)ve if s1 < s2
using System;
class Sl_Sort{
static void Main(){
string[] words = new string[]{"žiga", "špela", "črt"};
Console.WriteLine("Unsorted array is");
foreach(String st in words)
Console.Write(st+" , ");
//do selection sort to sort in ascending order
for(int i=0; i<words.Length-1;i++){
int min = i;
for(int j=i+1; j<words.Length;j++){
if(CompareSl(words[min], words[j]) > 0)
min = j;
}
string temp = words[i];
words[i] = words[min];
words[min] = temp;
}
Console.WriteLine("\nSorted array is");
foreach(String st in words)
Console.Write(st+" , ");
Console.ReadKey(); //waits till user presses a key before terminating
}
public static int CompareSl(string s1, string s2){
if(s1.Length == s2.Length){
for(int i=0; i<s1.Length; i++){
if(s1[i] != s2[i])
return index(s1[i]) - index(s2[i]);
}
}
else{
String s = s1.Length<s2.Length?s1:s2;
for(int i=0; i<s.Length; i++){
if(s1[i] != s2[i])
return index(s1[i]) - index(s2[i]);
}
if(s == s1)
return -1;
else
return 1;
}
return 0;
}
private static int index(char c){
char[] abc = { 'a', 'b', 'c', 'č', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 'š', 't', 'u', 'v', 'z', 'ž' };
for(int i=0; i<abc.Length; i++){
if(abc[i]==c)
return i;
}
return -1;
}
}
OUTPUT:
Unsorted array is
ziga , spela , crt ,
Sorted array is
crt , spela , ziga
Note: The characters ž, š and č got converted to z, s and c respectively because the platform I ran the code on was not set to UTF-8 or Unicode, which support Slovene, but ANSI, which does not support Slovene. Make sure your system supports Slovene to get the correct output.
Hope this helps.
Maybe you could do something like this:
private char[] charList = { 'a', 'b', 'c', 'č', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 'š', 't', 'u', 'v', 'z', 'ž' };
public string[] Sort(string inputStr)
{
string[] sortedChars = new string[inputStr.Length];
int index = 0;
for (int i = 0; i < charList.Length; i++)
{
for (int u = 0; u < inputStr.Length; u++)
{
sortedChars[index] = inputStr[u];
index++;
}
if (index == inputStr.Length)
return sortedChars;
}
return sortedChars;
}
I haven't tested the code, so not sure it works, but what it does is:
Iterate trough the chars, so it searches for "a" on each char of the inputString, if it's there it will be added to the sorted string[], then when it finishes with the first char, the next...etc.
Probably there's some error, maybe you can improve the code.

Applying complex code with multi-tasks to bruteforce logic

I've recently made a simple bruteforcer. Everything goes properly as I've expected, but not when I try to make everything multi-tasked.
This is the current code I have:
private static void startBruteForce(int keyLength)
{
var keyChars = createCharArray(keyLength, charactersToTest[0]);
var indexOfLastChar = keyLength - 1;
createNewKey(0, keyChars, keyLength, indexOfLastChar);
}
private static char[] createCharArray(int length, char defaultChar)
{
return (from c in new char[length] select defaultChar).ToArray();
}
private static void createNewKey(int currentCharPosition, char[] keyChars, int keyLength, int indexOfLastChar)
{
var nextCharPosition = currentCharPosition + 1;
for (int i = 0; i < charactersToTestLength; i++)
{
keyChars[currentCharPosition] = charactersToTest[i];
if (currentCharPosition < indexOfLastChar)
{
createNewKey(nextCharPosition, keyChars, keyLength, indexOfLastChar);
}
else
{
computedKeys++;
Console.WriteLine(new string(keyChars));
if (new string(keyChars) == "hola")
{
if (!isMatched)
{
isMatched = true;
result = new string(keyChars);
}
}
}
if (isMatched) return;
}
}
my current code to call the bruteforcer:
var estimatedPasswordLength = 3;
while (!isMatched)
{
estimatedPasswordLength++;
startBruteForce(estimatedPasswordLength);
}
these are the chars I use to combine the password to test:
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','A','B','C','D','E',
'F','G','H','I','J','K','L','M','N','O','P','Q','R',
'S','T','U','V','W','X','Y','Z','1','2','3','4','5',
'6','7','8','9','0','!','$','#','#','-'
To get the password hola I must to wait most likely ~10 mins. So to reduce the minutes to wait, I'm trying to split the work like this using multiple tasks, and so maybe doing this
estimatedPasswordLength++;
startBruteForce(estimatedPasswordLength);
synchronously without checking the same password at the time...
I appreciate any suggestion - how would I do it?
EDIT:
Regarding to #Cicero suggestion, this is what I tried:
Parallel.For(0, 4, i => // what should 0 and 4 be?
{
if (isMatched) return;
Task task = Task.Factory.StartNew(() => startBruteForce(estimatedPasswordLength));
estimatedPasswordLength++;
});
but length is now disproportionate, I get writed on the console strings like:
aaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaab
aaaaaaaaaaaaaaaac
while estimatedPasswordLength would be 4. How can I get a solution to make this with a proportionate length?

C# Count Vowels

I am learning to program C# and I am trying to count the vowels. I am getting the program to loop through the sentence, but instead of returning vowel count, it is just returning the length of the string. Any help would be greatly appreciated.
static void Main()
{
int total = 0;
Console.WriteLine("Enter a Sentence");
string sentence = Console.ReadLine().ToLower();
for (int i = 0; i < sentence.Length; i++)
{
if (sentence.Contains("a") || sentence.Contains("e") || sentence.Contains("i") || sentence.Contains("o") || sentence.Contains("u"))
{
total++;
}
}
Console.WriteLine("Your total number of vowels is: {0}", total);
Console.ReadLine();
}
Right now, you're checking whether the sentence as a whole contains any vowels, once for each character. You need to instead check the individual characters.
for (int i = 0; i < sentence.Length; i++)
{
if (sentence[i] == 'a' || sentence[i] == 'e' || sentence[i] == 'i' || sentence[i] == 'o' || sentence[i] == 'u')
{
total++;
}
}
That being said, you can simplify this quite a bit:
static void Main()
{
int total = 0;
// Build a list of vowels up front:
var vowels = new HashSet<char> { 'a', 'e', 'i', 'o', 'u' };
Console.WriteLine("Enter a Sentence");
string sentence = Console.ReadLine().ToLower();
for (int i = 0; i < sentence.Length; i++)
{
if (vowels.Contains(sentence[i]))
{
total++;
}
}
Console.WriteLine("Your total number of vowels is: {0}", total);
Console.ReadLine();
}
You can simplify it further if you want to use LINQ:
static void Main()
{
// Build a list of vowels up front:
var vowels = new HashSet<char> { 'a', 'e', 'i', 'o', 'u' };
Console.WriteLine("Enter a Sentence");
string sentence = Console.ReadLine().ToLower();
int total = sentence.Count(c => vowels.Contains(c));
Console.WriteLine("Your total number of vowels is: {0}", total);
Console.ReadLine();
}
Since Reed has answered your question, I will offer you another way to implement this. You can eliminate your loop by using LINQ and lambda expressions:
string sentence = "The quick brown fox jumps over the lazy dog.";
int vowelCount = sentence.Count(c => "aeiou".Contains(Char.ToLower(c)));
If you don't understand this bit of code, I'd highly recommend looking up LINQ and Lambda Expressions in C#. There are many instances that you can make your code more concise by eliminating loops in this fashion.
In essence, this code is saying "count every character in the sentence that is contained within the string "aeiou". "
That's because your if statement is always true, you need to compare the character at sentence[i], and see if it is a vowel, instead of seeing if the sentence contains a vowel.
Or with linq.
static void Main()
{
int total = 0;
Console.WriteLine("Enter a Sentence");
string sentence = Console.ReadLine().ToLower();
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
total = sentence.Count(x => vowels.Contains(x));
Console.WriteLine("Your total number of vowels is: {0}", total);
Console.ReadLine();
}
You were checking to see if your whole sentence contained vowels for every iteration of your loop, which is why your total was simply the number of characters in your sentence string.
foreach(char ch in sentence.ToLower())
if("aeiou".Contains(ch))
total++;
Better yet use a regular expression. edit You'd only want to use a regex for something a little more complex than matching vowels.
using System.Text.RegularExpressions;
...
int total = Regex.Matches(sentence, #"[AEIOUaeiou]").Count;
EDIT Just for completeness the fastest/most efficient (if you were to do this on a ~million strings) solution. If performance wasn't a concern I'd use Linq for its brevity.
public static HashSet<char> SVowels = new HashSet<char>{'a', 'e', 'i', 'o', 'u'};
public static int VowelsFor(string s) {
int total = 0;
foreach(char c in s)
if(SVowels.Contains(c))
total++;
return total;
}
There are many ways to skin a cat :-) In programming a little lateral thinking can be useful...
total += sentence.Length - sentence.Replace("a", "").Length;
total += sentence.Length - sentence.Replace("e", "").Length;
total += sentence.Length - sentence.Replace("i", "").Length;
total += sentence.Length - sentence.Replace("o", "").Length;
total += sentence.Length - sentence.Replace("u", "").Length;
You could, for example, try removing a vowel from the sentence and looking if the sentence is smaller without the vowel, and by how much.
int cnt = 0;
for (char c in sentence.ToLower())
if ("aeiou".Contains(c))
cnt++;
return cnt;
Maybe too advanced for a starter, but this is the way you do that in C#:
var vowels = new[] {'a','e','i','o','u'};
Console.WriteLine("Enter a Sentence");
var sentence = Console.ReadLine().ToLower();
var vowelcount = sentence.Count(x => vowels.Contains(x));
Console.WriteLine("Your total number of vowels is: {0}", vowelcount);
Console.ReadLine();
This is how I would handle this.
var sentence = "Hello my good friend";
var sb = sentence.ToLower().ToCharArray();
var count = 0;
foreach (var character in sb)
{
if (character.Equals('a') || character.Equals('e') || character.Equals('i') || character.Equals('o') ||
character.Equals('u'))
{
count++;
}
}
You can also do this with switch statement
var total = 0;
var sentence = "Hello, I'm Chris";
foreach (char c in sentence.ToLower())
{
switch (c)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
total++;
break;
default: continue;
}
}
Console.WriteLine(total.ToString());
TMTOWTDI (Tim Toadie as they say: There's More Than One Way To Do It).
How about
static char[] vowels = "AEIOUaeiou".ToCharArray() ;
public int VowelsInString( string s )
{
int n = 0 ;
for ( int i = 0 ; (i=s.IndexOfAny(vowels,i)) >= 0 ; )
{
++n ;
}
return n;
}
Or (another regular expression approach)
static readonly Regex rxVowels = new Regex( #"[^AEIOU]+" , RegexOptions.IgnoreCase ) ;
public int VowelCount( string s )
{
int n = rxVowels.Replace(s,"").Length ;
return n ;
}
The most straightforward is probably the fastest, as well:
public int VowelCount( string s )
{
int n = 0 ;
for ( int i = 0 ; i < s.Length ; +i )
{
switch( s[i] )
{
case 'A' : case 'a' :
case 'E' : case 'e' :
case 'I' : case 'i' :
case 'O' : case 'o' :
case 'U' : case 'u' :
++n ;
break ;
}
}
return n ;
}
static void Main(string[] args)
{
Char[] ch;
Console.WriteLine("Create a sentence");
String letters = Console.ReadLine().Replace(" ", "").ToUpper();
ch = letters.ToCharArray();
int vowelCounter = 0;
int consonantCounter = 0;
for(int x = 0; x < letters.Length; x++)
{
if(ch[x].ToString().Equals("A") || ch[x].ToString().Equals("E") || ch[x].ToString().Equals("I") || ch[x].ToString().Equals("O") || ch[x].ToString().Equals("U"))
{
vowelCounter++;
}
else
{
consonantCounter ++;
}
}
System.Console.WriteLine("Vowels counted : " + vowelCounter);
System.Console.WriteLine("Consonants counted : " + consonantCounter);
Application to count vowels and consonants letters in a sentence.
This is another solution with less lines of code with understanding the idea of using loops and nested loops with char arrays.
An application interface with control names:
namespace Program8_4
{
public partial class Form1 : Form
{
// declare the counter variables in field
int iNumberOfVowels = 0;
int iNumberOfConsonants = 0;
public Form1()
{
InitializeComponent();
}
private void btnFind_Click(object sender, EventArgs e)
{
// call the methods in this event
GetVowels(txtStringInput.Text);
GetConsonants(txtStringInput.Text);
// show the result in a label
lblOutput.Text = "The number of vowels : " + iNumberOfVowels.ToString()+ Environment.NewLine+
"The number of consonants : " + iNumberOfConsonants.ToString();
// assign zero the counters to not add the previous number to new number, and start counting from zero again
iNumberOfVowels = 0;
iNumberOfConsonants = 0;
}
private int GetConsonants(string strFindConsonants)
{
// Declare char array to contain consonants letters
char[] chrConsonants = { 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'X',
'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'x' };
// loop to get each letter from sentence
foreach (char Consonants in strFindConsonants)
{
// another nested loop to compare each letter with all letters contains in chrConsonants array
for (int index= 0; index<chrConsonants.Length;index++)
{
// compare each letter with each element in charConsonants array
if (Consonants == chrConsonants[index])
{
// If it is true add one to the counter iNumberOfConsonants
iNumberOfConsonants++;
}
}
}
// return the value of iNumberOfConsonants
return iNumberOfConsonants;
}
private int GetVowels(string strFindVowels)
{
// Declare char array to contain vowels letters
char[] chrVowels = { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O','U' };
// loop to get each letter from sentence
foreach (char Vowels in strFindVowels)
{
// another nested loop to compare each letter with all letters contains in chrVowels array
for (int index = 0; index< chrVowels.Length; index++)
{
// compare each letter with each element in chrVowels array
if (Vowels == chrVowels[index])
{
// If it is true add one to the counter iNumberOfVowels
iNumberOfVowels = iNumberOfVowels+1;
}
}
}
// return the value of iNumberOfVowels
return iNumberOfVowels;
}
We can use regular expression to match vowels in a sentence.
Regex.Matches() function will return an array with all occurrence of vowel.
Then we can use the count property to find the count of vowels.
Regular expression to match vowels in a string: [aeiouAEIOU]+
Below is the working code snippet:
public static void Main()
{
string pattern = #"[aeiouAEIOU]+";
Regex rgx = new Regex(pattern);
string sentence = "Who writes these notes?";
Console.WriteLine(rgx.Matches(sentence).Count);
}
// Using two loops.
char[] vowels= new char[]{'a', 'e', 'i', 'o', 'u',
'A', 'E', 'I', 'O', 'U'};
string myWord= "This is a beautiful word.";
int numVowels = 0;
foreach(char c in myWord.ToCharArray())
{
foreach(char c2 in vowels)
{
if(c == c2) numVowels++;
}
}
Console.WriteLine($"{numVowels} vowels in: {myWord}");
We check each subsequent letter of the expression if it is equal to the vowels in the array
class Program
{
private static void Main(string[] args)
{
string random = Console.ReadLine();
string toLower = random.ToLower();
char []isVowels = { 'a','e','i','o','u','y' };
byte count = 0;
for (int i = 0; i < toLower.Length; i++)
{
for (int j = 0; j < isVowels.Length; j++)
{
if (toLower[i]==isVowels[j])
{
count++;
}
}
}
Console.WriteLine(count);
}
}
`public static void Main()
{
Console.WriteLine("Enter a Sentence");
string sentence = Console.ReadLine().ToLower();
string voval="aeiou";
int cnt=0;
foreach(char ch in sentence)
{
if(voval.Contains(ch.ToString()))
{
cnt++;
}
}
Console.WriteLine(cnt);
}`
Here was how I did it:
char[] englishWord = new Char[5] { 'a', 'e', 'i', 'o', 'u' };
string input = Console.ReadLine();
input.ToLower();
int count = 0;
for (int i = 0; i < input.Length; i++)
{
for (int j = 0; j < englishWord.Length; j++)
{
if (input[i] == englishWord[j])
{
count++;
break;
}
}
}
Console.WriteLine(count);
this is a nice generic way to count vowels and from here you can do all sorts of things. count the vowels, return a sorted list, etc.
public static int VowelCount(String vowelName) {
int counter = 0;
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
for (int index = 0; index < vowelName.Length; index++)
{
if (vowels.Contains(vowelName[index]))
{
counter++;
}
}
return counter;
}
void main()
{
int x=0;
char ch;
printf("enter a statement:");
while((ch=getche())='\r')
{
if(ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u')
x++;
}
printf("total vowels=");
getch();
}

How to simplify my implementation of a basic Caesar Shift Encryption algorithm c#?

So I have recently decided that my coding style is somewhat clunky. The trouble is I never seem to be able to get to a stage where I can figure out the way of simplifying it into less lines of more efficient code.
I was in a team coding situation the other day trying to code a word wrapping feature using TDD. When I was in the driving seat I spent most of my time with String.Split() and if statements this and if that. The guy I was coding with asked why so complex and went with the simpler recursive one liner that returned the values required and with a few conditions to boot him out of the recursive loop when he was done.
So my question is thus – Below is some code that I have written to do a Caesar Shift Encryption on a string input using only lower case alphabet and no spaces. The unit tests pass and I believe I have implemented the various conditions that may occur.
In a nut shell how would you guys simplify the code below to make it more readable and more efficient?
I appreciate the help on this, because at the end of the day I need to make my coding style less verbose and more simplistic and can’t figure out the best place to start.
Cheers
Code in C#:
public static string Encrypt(string inputString, int shiftPattern)
{
StringBuilder sb = new StringBuilder();
char[] alphabet = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
//y = x + 3 (mod 26)
foreach (var letter in inputString.ToLower())
{
if (!alphabet.Contains(letter))
{
return "The " + letter + " Character was not in the sample set, please ensure you only use letters";
}
var res = Array.IndexOf(alphabet, letter) + (shiftPattern % 26);
if (res >= 26)
{
res = res - alphabet.Length;
sb.Append(alphabet[res]);
}
else if (res < 0)
{
res = alphabet.Length + res;
sb.Append(alphabet[res]);
}
else
sb.Append(alphabet[res]);
}
return sb.ToString();
}
1.- Put sb.Append(alphabet[res]) only once outside the conditionals.
2.- Consider throw an exception instead of return a message... so later you can easily check that the operation works propertly. You should also consider let the character 'As Is' if It's not pressent in your alphabet definition. It will allow you deal with whitespaces, etc.
3.- Check that the last conditional are really necessary. At first view... It looks that it could be safety removed... so confirm it. We can add a Math.Abs function to avoid problems with negative numbers in ShiftPattern.
4.- In some places you use alphabet.Length, and in other places you use 26. Use always alphabet.Length.
5.-Don't check that (res >= 26), you can do directly a MOD operation.
public static string Encrypt(string inputString, int shiftPattern)
{
StringBuilder sb = new StringBuilder();
char[] alphabet = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
//y = x + 3 (mod 26)
foreach (var letter in inputString.ToLower())
{
if (!alphabet.Contains(letter)) //Consider throwing and exception instead
{
return "The " + letter + " Character was not in the sample set, please ensure you only use letters";
}
var res = Array.IndexOf(alphabet, letter) + (Math.Abs(shiftPattern) % alphabet.Length);
res = res % alphabet.Length
sb.Append(alphabet[res]);
}
return sb.ToString();
}
You can drop the array and everything in the for loop in one line of code.
StringBuilder sb = new StringBuilder();
foreach (var letter in inputString.ToLower())
sb.Append((char)((((letter - 'a') + shiftpattern)%26) + 'a'));
In: zombie & shift by 1
Out: apncjf
There is no need to hold the complete alphabet list.
Also, if you don't support spaces then your messages will be like roman latin, without spaces...
public static string Encrypt(string inputString, int shiftPattern)
{
StringBuilder sb = new StringBuilder();
foreach(char letter in inputString.ToLower())
{
int encryptedValue = 0;
if (letter == ' ')
{
encryptedValue = ' ';
}
else
{
encryptedValue = (((letter - 'a') + shiftPattern) % 26) + 'a';
}
sb.Append((char)encryptedValue);
}
return sb.ToString();
}
I would recommend the following,
in case or more than two conditions use Switch- Case.
Instead of char[] or any variable declaration use var if using 3.0 or above
For and Foreach loops are avoided using lambda expressions.
Make such methods static and put it in some common class that can be shared globally.
For more good practice . Follow Resharper tool from jetbrains
With some changes to the algorithm :
static char[] alphabet = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
public static string Encrypt(string inputString, int shiftPattern)
{
if (inputString == null) return null;
if (shiftPattern <= 0)
{
shiftPattern = alphabet.Length + shiftPattern % alphabet.Length;
}
var chars = inputString.Select(c =>
{
var index = Array.IndexOf(alphabet, char.ToLower(c));
if (index == -1) return c;
var result = alphabet[(index + shiftPattern) % 26];
return char.IsLower(c) ? result : char.ToUpper(result);
});
return new string(chars.ToArray());
}
Manage the null string case.
Non-cypherable chars are kept as-is (debatable in a cypher...)
Just use linq instead of old style loops and builders.
Manage upper case
Shorter, while still understandable without problems.
I separated the return from the select for clarity here, in normal code if the return ... Select line didn't go over the column limit for the code base I would have combined the two.

Categories