Words in a rectangle c# - c#

I am trying to create rectangle from stars and put inside a text, but I can't figure it out. Can anyone help me?
string s = Console.ReadLine();
string[] n = s.Split(' ');
int longest = 0;
for (int i = 0; i < n.Length; i++)
{
if(n[i].Length > longest)
{
longest = n[i].Length;
}
}
for (int i = 1; i <= n.Length + 2; i++)
{
for (int j = 1; j <= longest + 2; j++)
{
if (i == 1 || i == n.Length + 2 || j == 1 || j == longest + 2)
{
Console.Write("*");
}
if (i == 2 && j == 1)
{
Console.Write(n[0]);
}
else
Console.Write("");
}
Console.WriteLine();
}
Console.ReadLine();
I can put single word and it's fine but, if I will change the number of array index it doesn't work properly.
Thanks for help!

Multi word version
// please, think about variables' names: what is "n", "s"?
// longest is NOT the longest word, but maxLength
string text = Console.ReadLine();
// be nice: allow double spaces, take tabulation into account
string[] words = text.Split(new char[] { ' ', '\t' },
StringSplitOptions.RemoveEmptyEntries);
// Linq is often terse and readable
int maxLength = words.Max(word => word.Length);
// try keep it simple (try avoiding complex coding)
// In fact, we have to create (and debug) top
string top = new string('*', maxLength + 2);
// ... and body:
// for each word in words we should
// - ensure it has length of maxLength - word.PadRight(maxLength)
// - add *s at both ends: "*" + ... + "*"
string body = string.Join(Environment.NewLine, words
.Select(word => "*" + word.PadRight(maxLength) + "*"));
// and, finally, join top, body and top
string result = string.Join(Environment.NewLine, top, body, top);
// final output
Console.Write(result);
For the Hello My World! input the output is
********
*Hello *
*My *
*World!*
********

Related

How to remove spaces using IndexOf?

I created following to count number of words. Now I need to remove all spaces using IndexOf. I'm stuck. Can someone help? It has to be something simple, but I cant figure it out.
string text = "Hello. What time is it?";
int position = 0;
int noSpaces = 0;
for (int i = 0; i < text.Length; i++)
{
position = text.IndexOf(' ', position + 1);
if (position != -1)
{ noSpaces++; }
if (position == -1) break;
}
Console.WriteLine(noSpaces + 1);
If you are looking to just remove the spaces in your text so it would look like: Hello.Whattimeisit? then all you need to do is use String.Replace:
string text = "Hello. What time is it?";
string textWithNoSpaces = text.Replace(" ", "");
Console.WriteLine(textWithNoSpaces); // will print "Hello.Whattimeisit?"
If you are looking to split the text into separate words then you would want to use String.Split:
string text = "Hello. What time is it?";
string[] words = text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // "RemoveEmptyEntries" will remove any entries which are empty: ""
// words[0] > Hello.
// words[1] > What
// etc.
You then can get a count of how many words are in the text and then combine them, using String.Concat, if you need text in the form of Hello.Whattimeisit?:
int numberOfWords = words.Length;
string textWithNoSpaces = string.Concat(words);
Update: This is how you would count the number of words and remove spaces using String.IndexOf & String.Substring:
This is a really sloppy example, but it gets the job done
string text = "Hello. What time is it?";
string newText = string.Empty;
int prevIndex = 0;
int index1 = 0;
int index2 = 0;
int numberOfWords = 0;
while (true)
{
index1 = text.IndexOf(' ', prevIndex);
if (index1 == -1)
{
if (prevIndex < text.Length)
{
newText += text.Substring(prevIndex, (text.Length - prevIndex));
numberOfWords += 1;
}
break;
}
index2 = text.IndexOf(' ', (index1 + 1));
if ((index2 == -1) || (index2 > (index1 + 1)))
{
newText += text.Substring(prevIndex, (index1 - prevIndex));
numberOfWords += 1;
}
prevIndex = (index1 + 1);
}
Console.WriteLine(numberOfWords); // will print 5
Console.WriteLine(newText); // will print "Hello.Whattimeisit?"
Console.ReadLine();
If your requirement is to count the number of words, can't you try this?
string text = "Hello. What time is it?";
var arr = text.Split(' ');
var count = arr.Length;
.Net Fiddle
Strings are immutable so you cant achieve it with only IndexOf that will require multiple changes. if you need to achieve it with that particular method I think that StringBuilder is the only way. However if this is not some assignment and you plan to use it in real application I strongly dissuade because it is really process heavy.

Split string at particular characters (C#)

What I want to do is to split an array and then put the character which i split at into another element
i.e. string text = "1*5+89-43&99" should become string[] textsplit = ["1","*","5","+","89","-","43","&","99"] (it must be a string)
and I will supply the characters to be left in seperate elements
You can do this using string.IndexOfAny.
Simply keep looking for the next index of any of the separators. When you find a separator, add the text between it and the last separator to your results, then look for the next separator.
string input = "1*1*5+89-43&33";
var separators = new[] { '+', '-', '*', '/', '&' };
var result = new List<string>();
int index;
int lastIndex = 0;
while ((index = input.IndexOfAny(separators, lastIndex)) != -1)
{
// Add the text before the separator, if there is any
if (index - lastIndex > 0)
{
result.Add(input.Substring(lastIndex, index - lastIndex));
}
// Add the separator itself
result.Add(input[index].ToString());
lastIndex = index + 1;
}
// Add any text after the last separator
if (lastIndex < input.Length)
{
result.Add(input.Substring(lastIndex));
}
Try with the following code snippet:
string text = "1*1*5+89-43&33";
List<string> textsplit = new List<string>();
foreach(var match in Regex.Matches(text, #"([*+/\-)(])|([0-9]+)"))
{
textsplit.Add(match.ToString());
}
Result added as an image.
Here's a basic and naive implementation that I beliewe will do what you want:
public static List<string> SplitExpression(string expression)
{
var parts = new List<string>();
bool isNumber(char c) => c == '.' || (c >= '0' && c <= '9');
bool isOperator(char c) => !isNumber(c);
int index = 0;
while (index < expression.Length)
{
char c = expression[index];
index++;
if (isNumber(c))
{
int numberIndex = index - 1;
while (index < expression.Length && isNumber(expression[index]))
index++;
parts.Add(expression.Substring(numberIndex, index - numberIndex));
}
else
parts.Add(c.ToString());
}
// move unary signs into following number
index = 0;
while (index < parts.Count - 1)
{
bool isSign = parts[index] == "-" || parts[index] == "+";
bool isFirstOrFollowingOperator = index == 0 || isOperator(parts[index - 1][0]);
bool isPriorToNumber = isNumber(parts[index + 1][0]);
if (isSign && isFirstOrFollowingOperator && isPriorToNumber)
{
parts[index + 1] = parts[index] + parts[index + 1];
parts.RemoveAt(index);
}
else
index++;
}
return parts;
}
Example input: "-1+-2*-10.1*.1", and output:
-1
+
-2
*
-10.1
*
.1

Replacing words input by the user within a sentence and then outputting the sentence but with the censored/replaced words

I am aiming to replace words within an array (input by the user) that appear in a sentence. I want to then output this sentence but with the replace version which would be either ***** or for example censor would become c****r.
static void CensorSelectedWords(string _sentence, int _wordCount)
{
string[] words = new string[_wordCount];
string[] splitSentence = new string[_wordCount];
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Type in the words you wish to be censored: ");
words[i] = Console.ReadLine();
splitSentence = _sentence.Split(' ', '.', '?', ',', '!');
for (int j = 0; j < splitSentence.Length; j++)
if (splitSentence[j] == words[i])
splitSentence[j] = words[i].Replace(words[i], "*");
}
Console.WriteLine(splitSentence);
}
You can replace every word within _sentence like this:
static void CensorSelectedWords(string _sentence, int _wordCount)
{
string astr;
string[] words = new string[_wordCount];
string[] splitSentence = new string[_wordCount];
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine("Type in the words you wish to be censored: ");
words[i] = Console.ReadLine();
astr = "";
for (int j = 0; j < words[I].Length; j++)
astr += "*";
_sentence = _sentence.Replace(word[i], astr);
}
Console.WriteLine(_sentence);
}
I'm slightly confused at what the output should be, but here's one way to do it. I've extracted the functionality of replacing a word with censored text into separate function so it can be modified independently.
The rest is very simple - get a sentence, get a list of censored words, then replace all the words with their censored counterparts in the sentence and display it:
public static string HideAllButFirstAndLast(string word)
{
if (word == null) return null;
if (word.Length < 4) return new string('*', word.Length);
return word[0] + new string('*', word.Length - 2) + word[word.Length - 1];
}
private static void Main()
{
Console.WriteLine("Enter a sentence: ");
var sentence = Console.ReadLine();
Console.WriteLine("Enter a comma-separated list of censored words:");
var censoredWords = Console.ReadLine()
.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)
.Select(word => word.Trim())
.ToList();
// Split sentence into words, replace words as needed, and join the words again
sentence = string.Join(" ", sentence.Split().Select(word =>
censoredWords.Contains(word, StringComparer.OrdinalIgnoreCase)
? HideAllButFirstAndLast(word)
: word));
Console.WriteLine(sentence);
GetKeyFromUser("\n\nDone! Press any key to exit...");
}
Output

How to print occurrence of a character in string in alphabetical order in C#?

Can anyone help me to find most efficient way to print character occurrence along with that character in a given string in alphabetical order?
I am able to count occurrence of character in string but I am not able to sort it in alphabetical order.
string OutputString = string.Empty;
int count = 1;
char[] charArr = inputString.ToCharArray();
for (int i = 0; i < charArr.Length; i++) {
for (int j = i + 1; j < charArr.Length; j++) {
if (charArr[i] == charArr[j])
count++;
}
if (!OutputString.Contains(charArr[i]))
OutputString += charArr[i].ToString() + count.ToString();
count = 1;
}
OutputString = string.Concat(OutputString.OrderBy(c => c));
let's say input string in xgdgyd
output should be:
d2g2x1y1.
You can use Linq to simplify this:
string s = "xgdgyd";
var result = s
.GroupBy(c => c)
.Select(g => g.Key.ToString() + g.Count())
.OrderBy(x => x);
Console.WriteLine(string.Concat(result)); // Outputs "d2g2x1y1"
The most useful thing here is GroupBy(), which will group all identical items together. That allows us to use g.Count() to count the number of items in each group.
Then we just concatenate each group key (a char) with its count into a single string.
Example on .Net Fiddle.
(I've simplified the code to use string.Concat() rather than string.Join() here.)
Solution given by #Matthew with LINQ is perfect, but if you want a solution with for loops as you posted in question then do this.
sort inputString first, and remove the line of code that sorts OutputString at the end, like this::
string inputString = "xgdgyd";
inputString = string.Concat(inputString.OrderBy(c => c));
string OutputString = string.Empty;
int count = 1;
char[] charArr = inputString.ToCharArray();
for (int i = 0; i < charArr.Length; i++)
{
for (int j = i + 1; j < charArr.Length; j++)
{
if (charArr[i] == charArr[j])
count++;
}
if (!OutputString.Contains(charArr[i]))
OutputString += charArr[i].ToString() + count.ToString();
count = 1;
}
Since you might not yet know LINQ, here is a solution using "classic" techniques:
string input = "xgdgyd";
char[] charArr = input.ToCharArray();
Array.Sort(charArr); // Sort before counting as Gian Paolo suggests!
// ==> "ddggxy"
int count;
string output = "";
for (int i = 0; i < charArr.Length; i += count) { // Increment by count to get
// the next different char!
count = 1;
// Note that we can combine the conditions within the for-statement
for (int j = i + 1; j < charArr.Length && charArr[j] == charArr[i]; j++) {
count++;
}
output += charArr[i] + count.ToString();
}
Console.WriteLine(output); // ==> d2g2x1y1
Note that the increment i += count, which is equivalent to i = i + count is performed at the end of the for-loop. Therefore count will be initialized at this point.
Another variant that uses only one loop instead of two nested loops appends the previous character to the output and resets the counter as soon as a different character is found.
string input = "xgdgyd";
char[] charArr = input.ToCharArray();
Array.Sort(charArr); // Sort before counting as Gian Paolo suggests!
int count = 1;
string output = "";
for (int i = 1; i < charArr.Length; i++) {
if (charArr[i] == charArr[i - 1]) {
count++;
} else {
output += charArr[i - 1] + count.ToString();
count = 1;
}
}
// Output last char
output += charArr[charArr.Length - 1] + count.ToString();
Console.WriteLine(output);
A more advanced technique would be to use a StringBuilder. See Concatenating Strings Efficiently by Jon Skeet.

How can I split a text in C# and keep the position of each part

I want to split a large text based on delimiter.
I used:
string[] parts = text
.Split(new string[] { Environment.NewLine + "##" }, StringSplitOptions.None);
I would like to know the start position (character index of each part). I could search for each part in a loop:
int[] pos = new int[slides.Length];
for (int i = 0; i < slides.Length; i++)
{
pos[i] = i == 0 ? text.IndexOf(slides[i]) : text.IndexOf(slides[i], pos[i-1] + 1);
}
Or I can search for the delimiters. I would like to know if there is a faster and better solution.
You have just one delimiter and you don't remove empty items; why not just sum up lengths?
abc\r\n##defhhdsncdslcnslsc\r\n##pqr....
^ ^ ^
0 abc.Length + abc.Length +
delimiter.Length delimiter.Length +
defhhdsncdslcnslsc.Length +
delimiter.Length
Code (item and its index):
string delimiter = Environment.NewLine + "##";
int sum = 0;
var parts = text
.Split(new string[] {delimiter}, StringSplitOptions.None)
.Select(item => {
int index = sum;
sum = delimiter.Length + item.Length;
return new {
item, // item
index // its index
};
});
Or (2 separated arrays):
string[] parts = text.Split(new string[] {delimiter}, StringSplitOptions.None);
int[] pos = new pos[parts.Length];
for (int sum = 0, i = 0; i < parts.Length; sum += delimiter.Length + parts[i].Length, ++i)
pos[i] = sum;

Categories

Resources