How to write a word from a string. c# - c#

I've started recently to learn c# and I have a problem.
The problem gives me a sentence and a number and my program has to return that number's word.
Here is what I've made:
using System;
string inputData = Console.ReadLine();
string text = inputData;
inputData=Console.ReadLine();
int x = Convert.ToInt32(inputData);
string currentWord = String.Empty;
int wordCount = 1;
for (int i = 0; i < text.Length; ++i)
{
if (text[i] == ' ')
{
wordCount++; currentWord = String.Empty;
while (text[i] == ' ') i++;
}
if (text[i] != ' ') { currentWord += text[i]; }
if (wordCount == x) Console.WriteLine(currentWord);
}
Console.Read();
For the sentence " I have two pens" and the number 2, the program returns
h
ha
hav
have.
What do I do wrong?

I would change it a bit. The problem why it's is giving multiple values, is because you don't terminate the iteration. (break the forloop). I've added some comment to it:
class Program
{
static void Main(string[] args)
{
// some test data (instead of readline)
string inputData = " I have two pens";
string text = inputData;
inputData = "2";
int x = Convert.ToInt32(inputData);
string currentWord = String.Empty;
int wordCount = 1;
for (int i = 0; i < text.Length; i++)
{
// when the character is a space and the currentWord has something or it was the last character of the text
// a new word has been found.
if ((text[i] == ' ' && !string.IsNullOrEmpty(currentWord)) || i==text.Length-1))
{
// when a new word has been found, just check it.
if (wordCount == x)
{
Console.WriteLine(currentWord);
// this is where your solution fails.
// when the word has been found, break the iteration.
break;
}
wordCount++;
currentWord = String.Empty;
}
else if (text[i] != ' ')
{
currentWord += text[i];
}
}
Console.Read();
}
}
You could use System.Linq for this, which is much easier.
// Split the string on space and create an array.
// Skip some elements and select the first.
var s = text.Split(' ').Skip(x).FirstOrDefault();
Console.WriteLine(s);

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.

Identifing number of character/digits/special character in string

I want to calculate the summary of string in terms of number of alphabets, digits and special character in C#. For example:
String abc123$% should have summary like A3D3S2 (which means 3 Alphabet, 3 Digits and 2 Special character)
a34=$# should have summary like A1D2S3 (which means 1 Alphabet, 2 Digits and 3 Special character)
a3b$s should have summary like A1D1A1S1A1 (which means 1 Alphabet, 1 Digits,1 Alphabet, 1 Special character,1 Alphabet)
Can anyone guide me how can write an algorithm which can perform the above task in a quick way? as I think if I search the string character by character, then it will take considerable amount of time. and I have a large dataset of strings.
This works:
static string GetSummary(string input)
{
var sb = new StringBuilder();
string prevMode = "";
string curMode = "";
int sameModeCount = 0;
for (int i = 0; i <= input.Length; ++i)
{
if (i < input.Length)
{
char c = input[i];
if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z')
{
curMode = "A";
}
else if ('0' <= c && c <= '9')
{
curMode = "D";
}
else
{
curMode = "S";
}
}
else
{
curMode = "";
}
if (curMode != prevMode && prevMode != "")
{
sb.Append(prevMode);
sb.Append(sameModeCount);
sameModeCount = 0;
}
prevMode = curMode;
++sameModeCount;
}
return sb.ToString();
}
Test:
public static void Main()
{
Console.WriteLine(GetSummary("abc123$%"));
Console.WriteLine(GetSummary("a34=$#"));
Console.WriteLine(GetSummary("a3b$s"));
}
Results:
A3D3S2
A1D2S3
A1D1A1S1A1
With Linq, you can do like this :
string myinput = "abc123$%";
int letter =0 , digit = 0, specialCharacter = 0;
myinput.ToCharArray().ToList().ForEach(x =>
{
letter = Char.IsLetter(x) ? ++letter : letter;
digit = Char.IsDigit(x) ? ++digit : digit;
specialCharacter = !Char.IsLetterOrDigit(x) ?
++specialCharacter : specialCharacter;
});
string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit,
specialCharacter);
You can directly use array in Linq ForEach without converting to list by :
Array.ForEach(myinput.ToCharArray(), x =>
{
letter = Char.IsLetter(x) ? ++letter : letter;
digit = Char.IsDigit(x) ? ++digit : digit;
specialCharacter = !Char.IsLetterOrDigit(x) ? ++specialCharacter : specialCharacter;
});
string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit, specialCharacter);
This should work:
string s = "a3b$s";
char etype = 'X'; //current character's type
char etypeinit = 'X'; //tracker variable - holds type of last character
string str = "";
int count = 1;
foreach(char c in s)
{
//Use this block of conditionals to assign type for current character
if(char.IsLetter(c))
{
etype = 'A';
}
else if(char.IsDigit(c))
{
etype = 'D';
}
else
{
etype = 'S';
}
//This is a different type of character compared to the previous one
if(etypeinit != etype)
{
str += string.Format("{0}{1}",etype,count); //Build the string
count = 1; //Reset count
}
else
{
count++; //Increment because this is the same type as previous one
}
etypeinit = etype; //Set tracker variable to type of current character
}
Console.WriteLine(str);
Little late and little complex but able to produces all expected output as per given inputs in the question, please take a look:
string inputString = "abc123$%ab12";
var results = inputString.Select(x => char.IsLetter(x) ? 'A' :
char.IsDigit(x) ? 'D' : 'S');
StringBuilder outPutBuilder = new StringBuilder();
char previousChar = results.First();
int charCount = 0;
foreach (var item in results)
{
switch (item)
{
case 'A':
if (previousChar == 'A')
{
charCount++;
}
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
case 'D':
if (previousChar == 'D')
charCount++;
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
default:
if (previousChar == 'S')
charCount++;
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
}
previousChar = item;
}
outPutBuilder.Append(previousChar.ToString() + charCount);
Working example
Use a FOR loop to go through each character. If the character is in the range of a-z or A-Z then it is an alphabet. If in the range of 0-9 then it is a digit else special character.
Code
string inputStr = "a3b$s";
string outputStr = string.Empty;
char firstChar = Convert.ToChar(inputStr.Substring(0, 1));
outputStr = char.IsLetter(firstChar) ? "A1" : char.IsDigit(firstChar) ? "D1" : "S1";
for (int i = 1; i < inputStr.Length; i++)
{
char nextChar = char.IsLetter(inputStr[i]) ? 'A' :
char.IsDigit(inputStr[i]) ? 'D' : 'S';
char prevChar = Convert.ToChar(outputStr.Substring(outputStr.Length - 2, 1));
if (nextChar == prevChar)
{
int lastDig = Convert.ToInt32(outputStr.Substring(outputStr.Length - 1, 1));
outputStr = outputStr.Substring(0, outputStr.Length - 1) +
(lastDig + 1).ToString();
}
else
outputStr += nextChar.ToString() + "1";
}
Console.WriteLine(outputStr.ToString());
Output
A1D1A1S1A1
Find demo here

Split string into array of words

I want to split a string into an array of words without using string.Split. I tried already this code and it is working but cant assign the result into the array
string str = "Hello, how are you?";
string tmp = "";
int word_counter = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == ' ')
{
word_counter++;
}
}
string[] words = new string[word_counter+1];
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{
tmp = tmp + str[i];
continue;
}
// here is the problem, i cant assign every tmp in the array
for (int j = 0; j < words.Length; j++)
{
words[j] = tmp;
}
tmp = "";
}
You just need a kind of index pointer to put up your item one by one to the array:
string str = "Hello, how are you?";
string tmp = "";
int word_counter = 0;
for (int i = 0; i < str.Length; i++) {
if (str[i] == ' ') {
word_counter++;
}
}
string[] words = new string[word_counter + 1];
int currentWordNo = 0; //at this index pointer
for (int i = 0; i < str.Length; i++) {
if (str[i] != ' ') {
tmp = tmp + str[i];
continue;
}
words[currentWordNo++] = tmp; //change your loop to this
tmp = "";
}
words[currentWordNo++] = tmp; //do this for the last assignment
In my example the index pointer is named currentWordNo
Try using regular expressions, like this:
string str = "Hello, how are you?";
// words == ["Hello", "how", "are", "you"]
string[] words = Regex.Matches(str, "\\w+")
.OfType<Match>()
.Select(m => m.Value)
.ToArray();
String.Split is not a good option since there are too many characters to split on: ' ' (space), '.', ',', ';', '!' etc.
Word is not just a stuff between spaces, there are punctuations to consider, non-breaking spaces etc. Have a look at the input like this:
string str = "Bad(very bad) input to test. . ."
Note
Absence of space after "Bad"
Non-breaking space
Addition spaces after full stops
And the right output should be
["Bad", "very", "bad", "input", "to", "test"]
You can also use a List to create your words list:
string str = "Hello, how are you?";
string tmp = "";
List<string> ListOfWords = new List<string>();
int j = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] != ' ')
{
tmp = tmp + str[i];
continue;
}
// here is the problem, i cant assign every tmp in the array
ListOfWords.Add(tmp);
tmp = "";
}
ListOfWords.Add(tmp);
In this way you can avoid to count the number of word and the code is more simple. Use ListOfWord[x] to read any word

Splitting String N into 4 distinct strings

The string has to be split into 4 pairwise different non-empty parts. For example,
"happynewyear" could become ["happy", "new", "ye" and "ar"]
No deletion, change of order of characters is permitted.
This question was part of an online competition, which is now over. I have written the following C# code which works for the test cases which I have run but it failed in 3 test cases after submission. I am not sure what cases I might be missing, can anyone help?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hackerearth___India_Hacks
{
class Program
{
static void Main(string[] args)
{
var line1 = System.Console.ReadLine().Trim();
var N = Int32.Parse(line1);
string[] s = new string[N];
string result = "";
for (var i = 0; i < N; i++)
{
s[i] = System.Console.ReadLine().Trim();
result = result + "\n" + check(s[i]);
}
System.Console.Write(result);
Console.ReadKey();
}
static string check(string s)
{
if (s.Length > 3)
{
string[] s1 = new string[4];
int k = 0;
string c = "";
foreach (char ch in s)
{
c = c + ch.ToString();
// Console.WriteLine("C :" +c);
if (k == 0)
{
s1[k] = c;
c = "";
k = 1;
}
else
for (int i = 0; i < k; i++)
{
int f = 0;
for (int j = 0; j < k; j++)
{
if (s1[j].Equals(c) || c == "")
f=1;
}
if (f == 1)
break;
s1[k] = c;
c = "";
if (k == 3 && s1[k] != null)
return "YES";
k++;
// Console.WriteLine("K :"+s[k]);
}
}
return "NO";
}
else
{
return "NO";
}
}
}
}
This would be an example which would not work with your algorithm: "aababa". The 4 strings should be ["aa", "b", "a","ba"] given your criteria, but your algorithm always assumes that the first character is the first string in the solution. This assumption is false. If "a" is the first string in the example I give, your algorithm would fail because it would make the first 3 strings ["a", "ab", "aba",...] that last one would fail with your algorithm because it has no more characters to add to the array.
A recursive solution makes sense to me... here's some code that I think would work.
EDIT: it does work... here's a dotnetfiddle
public static List<string> FindStrings(string s, int n) {
if (n == 0) {
if (string.IsNullOrEmpty(s)) {
return new List<string>{ };
}
return null; // null means invalid
}
for (var i=s.Length-1; i>=0; i--){
var startOfString = s.Substring(0, i);
var endOfString = s.Substring(i);
var list = FindStrings(startOfString, n-1);
// invalid... gotta continue to next try
if (list == null) continue;
// make sure there are no matches so far
if (list.Contains(endOfString)) continue;
// bingo!
if (list.Count == n-1) {
list.Add(endOfString);
return list;
}
}
return null; // null means invalid
}
One way to tackle this problem is to solve the problem of creating all possible substrings. Then going through all the possibilities and making sure the results are distinct.
private static void Main(string[] args)
{
var N = int.Parse(Console.ReadLine());
for (var i = 0; i < N; i++)
{
Console.WriteLine(IsPairwiseUnquie(Console.ReadLine(), 4) ? "YES" : "NO");
}
}
public static bool IsPairwiseUnquie(string s, int count)
{
return s.AllSubstrings(4).Any(subs => subs.Count == subs.Distinct().Count());
}
public static IEnumerable<List<string>> AllSubstrings(this string str, int count)
{
if(str.Length < count)
throw new ArgumentException("Not enough characters");
if(count <= 0)
throw new ArgumentException("Must be greater than 0", nameof(count));
// Base case of only one substring, just return the original string.
if (count == 1)
{
yield return new List<string> { str };
yield break;
}
// break the string down by making a substring of all possible lengths from the first n
// then recursively call to get the possible substrings for the rest of the string.
for (int i = 1; i <= str.Length - count + 1; i++)
{
foreach (var subsubstrings in str.Substring(i).AllSubstrings(count - 1))
{
subsubstrings.Insert(0, str.Substring(0, i));
yield return subsubstrings;
}
}
}

C# Regular Expression to insert "_" after third, then seventh character with a new line after the eighth character

I was wondering if someone could help. I am trying to change a string in the below format:
goeirjew98rut34ktljre9t30t4j3der
to be outputted as below:
geo_irje_w
98r_ut34_k
tlj_re9t_3
0t4_j3de_r
So insert an underscore after the third and seventh characters and insert a new line after the eighth.
After doing some reading I thought the best way to do this might be via a regular expression such as the example at the below link:
http://msdn.microsoft.com/en-us/library/xwewhkd1(v=vs.110).aspx
However I am not sure how to modify this for my needs. Any help what so ever would be greatly appreciated.
Thanks
It can be easily solved by a regular expression and a Replace, like this:
var s = "goeirjew98rut34ktljre9t30t4j3der";
Regex.Replace(s, #"(\w{3})(\w{4})(\w{1})", "$1_$2_$3\n").Dump();
This is definitely something that is best solved with a quick loop:
string s = "goeirjew98rut34ktljre9t30t4j3der";
var outputs = new List<string>();
for (var i = 0; i < s.Length; i += 8)
{
string sub = s.Substring(i, Math.Min(8, s.Length - i));
if(sub.Length > 3)
sub = sub.Insert(3, "_");
if (sub.Length > 8)
sub = sub.Insert(8, "_");
outputs.Add(sub);
}
I think you can not insert char in string by this rule, but I hope this code be useful for you.
public string Decode(string str)
{
var state = 0;
var c = 0;
var newStr = string.Empty;
foreach (var ch in str)
{
c++;
newStr += ch;
if (state == 0 && c == 3)
{
newStr += "_";
state = 1;
c = 0;
}
if (state == 1 && c == 4)
{
newStr += "_";
state = 2;
c = 0;
}
if (state == 2 && c == 1)
{
newStr += "\r\n";
state = 0;
c = 0;
}
}
return newStr;
}
I would make it so u can change everything on the fly and use stringextentions
class Program
{
static void Main(string[] args)
{
string str = "goeirjew98rut34ktljre9t30t4j3der";
var parts = str.SplitInParts(8); //Split in different parts
foreach (var part in parts)
{
string formattedString = part.MultiInsert("_", 2, 6); //Insert your char on all position u want
Console.WriteLine(formattedString);
}
Console.ReadKey();
}
}
static class StringExtensions
{
public static IEnumerable<String> SplitInParts(this String s, Int32 partLength)
{
if (s == null)
throw new ArgumentNullException("s");
if (partLength <= 0)
throw new ArgumentException("Part length has to be positive.", "partLength");
for (var i = 0; i < s.Length; i += partLength)
yield return s.Substring(i, Math.Min(partLength, s.Length - i));
}
public static string MultiInsert(this string str, string insertChar, params int[] positions)
{
StringBuilder sb = new StringBuilder(str.Length + (positions.Length * insertChar.Length));
var posLookup = new HashSet<int>(positions);
for (int i = 0; i < str.Length; i++)
{
sb.Append(str[i]);
if (posLookup.Contains(i))
sb.Append(insertChar);
}
return sb.ToString();
}
}

Categories

Resources