Reputation: 129
This is the question:
It seemed interesting and not too complicated at first, but I couldn't solve it.
public static void Letters()
{
string input;
Console.Write("Enter a string: ");
input = Console.ReadLine();
var chars = new List<char>();
//To populate characters with the letters of the input but without repetition
for(int index = 0; index < input.Length; index++)
{
if(!characters.Contains(input[index]))
characters.Add(input[index]);
}
//To increment the counter corresponding to the character index
int[] counter = new int[characters.Count];
//Now what ?!
}
My thinking is:
I create a collection to hold the letters of the input string, without any repetition.
Then I use an int array of the same size such that each int holds the number of times the corresponding letter has occurred in the input string.
I not only don't know how to implement this, but I have a feeling its not an ideal solution to the problem. There's probably a query or a lambda expression that should make this easy to implement and read.
Note: The question following this is of the same nature. The difference is that it asks to replace the repeated letters with a single one "aaabbbccc" to "abc".
I will appreciate if the logic is described. I will try to implement it on my own, just point me to the logic.
EDIT:
This my answer using a dictionary
public static void Letters()
{
string input;
Console.Write("Enter a string: ");
input = Console.ReadLine();
var dict = new Dictionary<char, int>();
for(int index = 0; index < input.Length; index++)
{
char theKey = input[index]; //just for clarity
if(!dict.ContainsKey(theKey))
dict.Add(theKey, 1);
else
dict[input[index]]++;
}
foreach(var key in dict.Keys)
{
Console.WriteLine("{0}\t{1}", key, dict[key]);
}
Upvotes: 0
Views: 3655
Reputation: 1393
Consider first that a character has a binary representation (sequence of 1s and 0s) just like a scalar value. Consider also that for a Latin alphabet like English, the alphabetical order and numerical order of their equivalents correspond.
So... you could do something like this:
iterate over the array and for each non-zero element, print out the character equivalent of the array index and the contents of the element (character count)
string myString = "the quick brown fox jumps over the lazy dog";
byte[] bytes = Encoding.UTF8.GetBytes(myString);
int[] counts = new int[256];
foreach (var b in bytes)
{
counts[(int)b]++;
}
for (int i = 0; i < 256; i++)
{
if (counts[i] > 0)
{
Console.WriteLine("{0} - {1}", (char)(byte)i, counts[i]);
}
}
The above solution can easily be generalized to disregard case by performing GetBytes on myString.ToUpper(). To generalize to Unicode would be a little more work because you'd have to pair up the bytes in proper endian order.
Upvotes: 0
Reputation: 1150
var myString = "Hello";
var dict = new Dictionary<char, int>();
foreach(var c in myString)
{
if(!dict.ContainsKey(c))
dict.Add(c, 1);
else
dict[c]++;
}
var orderedDict = dict.OrderBy(x => x.Key);
foreach(var kvp in orderedDict)
{
Console.WriteLine("Letter: {0}, Times: {1}", kvp.Key, kvp.Value);
}
Upvotes: 2
Reputation: 3558
For simple and readable solution use LINQ, GroupBy and anonymous types
string input = Console.ReadLine();
var groupedLettersOrdered = input.GroupBy(x => x, (character, charCollection) =>
new {Character = character, Count = charCollection.Count()})
.OrderBy(x => x.Character);
foreach(var letterGroup in groupedLettersOrdered)
Console.WriteLine("Character {0}, Count: {1}", letterGroup.Character, letterGroup.Count);
However Dictionary<char, int>
solution will be (should be) faster and better for large strings
Upvotes: 1
Reputation: 735
Dictionnary<String, int>
Key = string = letter IE a,b,c,d,e,f..... Int is number of occurence
So start by doing this :
Dictionnary.add(a,0)
...
Dictionnary.add(z,0);
And then read the string and do this
Dictionnary[letterFound ] += 1;
There is a better way knowing what is the value in ASCi of each letter to init the dictionnary, but i don't think is mandatory for such exercice.
Good luck
Upvotes: 2