I need to break on closest space to 30th character of texbox, and I got very good answer for that:
var x = 30;
if (textBox1.Text.Length > x)
{
var index = textBox1.Text.Select((c, i) => new {c, i}).TakeWhile(q => q.i < x).Where(q => q.c == ' ' ).Select(q => q.i).Last();
textBox1.Text = textBox1.Text.Insert(index, Environment.NewLine);
}
Only problem is that I need to exclude from counting characters like "#A", "#B", because they are used for text formatting.
Although perhaps not the cleanest solution. If you simply count on # (or perform a regex to detect patterns) and add that number to x (30) like:
int paramCount = test.Where(c => c == '#').Count();
var index = test.Select((c, i) => new { c, i })
.TakeWhile(q => q.i < x + paramCount)
.Where(q => q.c == ' ')
.Select(q => q.i)
.Last();
edit
In order to make sure your count only counts the first 30 characters (excluding '#'), you can perform an aggregate in advance:
int paramCount = test.Select((c, i) => new { c, i })
.Aggregate(0, (count, s) => s.c == '#' && s.i < x + count ? count + 1 : count);
textBox1.Text.Replace("#A", "").Replace("#B", "")...
You can try the code below.
string sTemp = textBox1.Text.Substring(0, 30);
sTemp = sTemp.Replace(" #A ", "");
sTemp = sTemp.Replace("#A ", "");
sTemp = sTemp.Replace(" #A", "");
sTemp = sTemp.Replace("#A", "");
sTemp = sTemp.Replace(" #B ", "");
sTemp = sTemp.Replace("#B ", "");
sTemp = sTemp.Replace(" #B", "");
sTemp = sTemp.Replace("#B", "");
int numberOfLeak = 30 - sTemp.Length;
var x = 30 + numberOfLeak;
if (textBox1.Text.Length > x)
{
textBox1.Text = textBox1.Text.Insert(x, Environment.NewLine);
}
string oriText = textBox1.Text;//Original text that you input
int charPerLine = 30;//Number of character per line
string sKeyword = "#A|#B";//You can add more template here, the separator is "|"
string[] arrKeyword = sKeyword.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
ArrayList arrListKeyword = new ArrayList();
for (int i = 0; i < arrKeyword.Length; i++)
{
arrListKeyword.Add(" " + arrKeyword[i] + " ");
arrListKeyword.Add(arrKeyword[i] + " ");
arrListKeyword.Add(" " + arrKeyword[i]);
arrListKeyword.Add(arrKeyword[i]);
}
int nextIndex = 0;
while (true)
{
//Check if the sub string after the NewLine has enough length
if (charPerLine < oriText.Substring(nextIndex).Length)
{
string sSubString = oriText.Substring(nextIndex, charPerLine);
//Replace all keywords with the blank
for (int i = 0; i < arrListKeyword.Count; i++)
{
sSubString = sSubString.Replace(arrListKeyword[i].ToString(), "");
}
int numberOfLeak = charPerLine - sSubString.Length;
int newLineIndex = nextIndex + charPerLine + numberOfLeak;//find the index to insert NewLine
oriText = oriText.Insert(newLineIndex, Environment.NewLine);//Insert NewLine
nextIndex = newLineIndex + Environment.NewLine.Length;//Environment.NewLine cost 2 in length
}
else
{
break;
}
}
textBox1.Text = oriText;
Related
I am trying to rearrange a given string, so no two adjacent letters are the same.
For that I'm thinking to count every distinct letter's occurence, and then rearrange the string the characters occurence number
example:
Input: AABAABBC
Output: AAAABBBC
and after that spliting it in 2 different strings
AAAA BBBC
and then trying to get the final result.
My question is how do I rearrange the string without using Linq?
Here is my code so far:
private static string GetDistinctChars(string text)
{
string result = "";
foreach (char c in text)
{
if (!result.Contains(c))
{
result += c;
}
}
return result;
}
private static double GetCharOccurrence(string text, char charToCount)
{
int count = 0;
foreach (char c in text)
{
if (c == charToCount)
{
count++;
}
}
return count;
}
You can do it like that:
string example = "AABBAACDCAA";
var orderList = example.OrderBy(x => x).ToList();
List<string> letters = new List<string>();
string temp = string.Empty;
for(int i = 0; i < orderList.Count; i++)
{
temp += orderList[i];
if (i + 1 == orderList.Count)
{
letters.Add(temp);
break;
}
if(orderList[i] != orderList[i + 1])
{
letters.Add(temp);
temp = string.Empty;
}
}
string result = String.Join(" ", letters);
Console.WriteLine(result);
If you don't want to use Linq Order by method, you should implement sorting algorithm like this:
static char[] SortArray(char[] array)
{
int length = array.Length;
char temp = array[0];
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length; j++)
{
if (array[i] > array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
return array;
}
and use it in your program:
string example = "AABBAACDCAA";
var orderList = SortArray(example.ToCharArray());
List<string> letters = new List<string>();
string temp = string.Empty;
for(int i = 0; i < orderList.Length; i++)
{
temp += orderList[i];
if (i + 1 == orderList.Length)
{
letters.Add(temp);
break;
}
if(orderList[i] != orderList[i + 1])
{
letters.Add(temp);
temp = string.Empty;
}
}
string result = String.Join(" ", letters);
Console.WriteLine(result);
alternativly, if you don't want to use list anymore, you can operate only on strigns:
string example = "AABBAACDCAA";
var orderList = SortArray(example.ToCharArray());
string lettersString = string.Empty;
for (int i = 0; i < orderList.Length; i++)
{
lettersString += orderList[i];
if (i + 1 == orderList.Length)
break;
if (orderList[i] != orderList[i + 1])
lettersString += " ";
}
Console.WriteLine(lettersString);
You can find your problem on LeetCode, it's a problem #767.
My algorithm is
If we have too many of same characters, we can't solve the problem (e.g. "aaaaaabc")
If solution exists, we can sort characters aababc -> aaabbc and then take item by item from the beginning and from the center:
For instance:
aababc -> aaabbc (ordered by frequency: a appears 3 time, b - 2, c - 1)
then
aaabbc => ab
^ ^
take these
aaabbc => abab
^ ^
take these
aaabbc => ababac <- final answer
^ ^
take these
Code:
using System.Linq;
using System.Text;
...
public static string ReorganizeString(string s) {
int count = s.GroupBy(c => c).Max(g => g.Count());
// One of the item is too frequent, no solutions
if (count > (s.Length + 1) / 2)
return "";
string st = string.Concat(s
.GroupBy(c => c)
.OrderByDescending(g => g.Count())
.ThenBy(g => g.Key) // not required, just for aesthetic
.SelectMany(c => c));
StringBuilder sb = new StringBuilder(s.Length);
for (int i = 0; i < s.Length / 2; ++i) {
sb.Append(st[i]);
sb.Append(st[(st.Length + 1) / 2 + i]);
}
// Middle character
if (s.Length % 2 != 0)
sb.Append(st[st.Length / 2]);
return sb.ToString();
}
Demo:
string value = "AABAABBC";
Console.Write(ReorganizeString(value));
Output:
ABABABAC
Fiddle it yourself.
Edit: If StringBuilder (as well as System.Text) is really forbidden, we can use string, which, however, slows down the routine:
using System.Linq;
...
public static string ReorganizeString(string s) {
int count = s.GroupBy(c => c).Max(g => g.Count());
// One of the item is too frequent, no solutions
if (count > (s.Length + 1) / 2)
return "";
string st = string.Concat(s
.GroupBy(c => c)
.OrderByDescending(g => g.Count())
.ThenBy(g => g.Key) // not required, just for aesthetic
.SelectMany(c => c));
string result = "";
for (int i = 0; i < s.Length / 2; ++i) {
result += st[i];
result += st[(st.Length + 1) / 2 + i];
}
// Middle character
if (s.Length % 2 != 0)
result += st[st.Length / 2];
return result;
}
I have a string like this (including newlines)
A2,
10.22,
-57,
A,
10.23,
-68,
A2,
10.24,
-60,
LB,
10.25,
-62,
I am trying to make this string to look like this:
A2,10.22,-57,
A,10.23,-68,
A2,10.24,-60,
LB,10.25,-62,
I need to join string in every 3 line i have tried :
int numLines = a.Split('\n').Length;
for (int i = 0; i < numLines; i += 3)
{
richTextBox1.Text = a.Replace("\n", "");
}
But it is not working for me. Please help me out
You can also approach this with LINQ, by using the index overload of .Select to retain a running count of the line numbers, and then to group them into groups of 3 - I've used integer division to Floor the line index, 3 at a time, but there are likely other suitable ways.
var groups = values.Select((s, idx) => (Index: idx / 3, Value: s))
.GroupBy(x => x.Index);
Where each item in the groups above will be IEnumerable<(Index, Value)>.
You'll also need to be wary of newlines - these may be \r\n in Windows, not just the \n you've indicated.
Here's an example:
var a =
#"A2,
10.22,
-57,
A,
10.23,
-68,
A2,
10.24,
-60,
LB,
10.25,
-62,";
var values = a.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
var groups = values.Select((s, idx) => (Index: idx / 3, Value: s))
.GroupBy(x => x.Index);
foreach (var grp in groups)
{
Console.WriteLine(string.Join("", grp.Select(x => x.Value)));
}
Since you've already got commas at the end of each string (including the last one), there's no need to add another separator.
Output:
A2,10.22,-57,
A,10.23,-68,
A2,10.24,-60,
LB,10.25,-62,
Why not use the array that the split gives you instead?
var newArr = a.Split('\n');
for (int i = 0; i < newArr.Length; i += 3)
{
richTextBox1.Text = newArr[i] + newArr[i + 1] + newArr[i + 2];
}
Just don't forget to check the length of the arrays so that you don't get a IndexOutOfRange Exception.
I'm assuming that the input is actually coming from a file here.
var file = //file path
var sb = new StringBuilder();
var lineNum = 1;
var output = string.Empty;
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (lineNum % 3 == 0)
{
output += sb.ToString() + "\n";
sb.Clear();
}
else
sb.Append(line);
lineNum++;
}
}
richTextBox1.Text = output;
Try this solution which is a combination of linq and for loop
var result = "";
var items = yourInputString.Split('\n');
for(var i=0; i<items.Count();i=i+3)
{
result += string.Join(",",items.Skip(i).Take(3))+"\n";
}
static void Main(string[] args)
{
var Lines = System.IO.File.ReadAllLines("input.txt");
var Result = new StringBuilder();
var SB = new StringBuilder();
for (var i = 0; i < Lines.Length; i++)
{
SB.Append(Lines[i]);
if ((i+1) % 3 == 0)
{
Result.Append($"{SB.ToString()}{Environment.NewLine}");
SB.Clear();
}
}
System.IO.File.WriteAllText("output.txt", Result.ToString());
}
Try to use Aggregate function
var outPutList = data.Replace("\r", string.Empty).Replace("\n", string.Empty).Split(",").Aggregate(new StringBuilder(""), (x, y) =>
{
if (double.TryParse(y, out double parsedValue))
x.Append(" " + parsedValue);
else
{
x.Append(Environment.NewLine);
x.Append(y.Trim());
}
return x;
});
richTextBox1.Text = outPutList.ToString();
Here is the output
try this works
private void button1_Click(object sender, EventArgs e)
{
//put your string in a textxbox with multiline property set to true
string[] s = textBox1.Text.Replace("\r", "").Replace("\n", "").Split(',');
string r = "";
for (int i = 0; i < s.Length; i++)
{
r = r + s[i] + ",";
if ((i + 1) % 3 == 0)
r = r + "+";
}
if (r.Substring(r.Length - 1, 1) == ",")
r = r.Substring(0, r.Length - 1);
if (r.Substring(r.Length - 1, 1) == "+")
r = r.Substring(0, r.Length - 1);
string[] finalArrayString = r.Trim().Split('+');
//just for show the result
textBox1.Text = "";
for (int i = 0; i < finalArrayString.Length; i++)
textBox1.Text = textBox1.Text + finalArrayString[i] + "\r\n";
}
hope it helps you
string givenstring,outputString="";
int i, j = 0;
Console.WriteLine("Enter the string");
givenstring = Console.ReadLine();
i = (givenstring.Length) / 2;
while (j < i)
{
outputString += givenstring[j];
j++;
}
Console.WriteLine(outputString);
outputString = string.Empty;
while (i < givenstring.Length)
{
outputString += givenstring[i];
i++;
}
Console.WriteLine(outputString);
Here I split the string into two string.
For example, input:
Helloworld
output:
Hello world.
But now I need the output:
dlrow olleH
The question is a vague one. If you need put all the words in the string in reversed order, e.g.
"This is a test string" -> "String test a is this"
then you can do
String source = "This is a test string";
String result = String.Join(" ", source
.Split(' ')
.Reverse()
.Select((item, index) => index > 0 ? item.ToLower() : ToNameCase(item)));
// "String test a is this"
Console.WriteLine(result);
where ToNameCase() is something like this:
private static String ToNameCase(String source) {
if (String.IsNullOrEmpty(source))
return source;
StringBuilder sb = new StringBuilder(source.Length);
sb.Append(Char.ToUpper(source[0]));
sb.Append(source.Substring(1));
return sb.ToString();
}
Edit: if you don't pay attention to case, i.e.
"This is a test string" -> "string test a is This"
you can simplify the solution into just
String source = "This is a test string";
String result = String.Join(" ", source
.Split(' ')
.Reverse());
// "string test a is This"
Console.WriteLine(result);
Edit 2: If you want to split the text into range chunks with equal lengths (with possible exception of the last chunk), and then reverse them:
String source = "HelloWorld";
int range = 2; // we want 2 chunks ("Hello" and "World")
String result = String.Join(" ", Enumerable
.Range(0, range)
.Select(index => index == range - 1 ?
source.Substring(source.Length / range * index) :
source.Substring(source.Length / range * index, source.Length / range))
.Reverse()); // remove ".Reverse()" and you will get "Hello World"
// "World Hello"
Console.WriteLine(result);
Use Aggregate like this:
string reversed = arr.Aggregate((workingSentence, next) => next + " " + workingSentence);
Console.WriteLine(reversed);
I just modify your code. It should be look like this now:
string givenstring, outputString = "";
int i, j = 0;
string[] arr = new string[2];
Console.WriteLine("Enter the string");
givenstring = Console.ReadLine();
i = (givenstring.Length) / 2;
while (j < i)
{
outputString += givenstring[j];
j++;
}
Console.Write("Input -> " + outputString + " ");//hello world
arr[0] = outputString;
outputString = string.Empty;
while (i < givenstring.Length)
{
outputString += givenstring[i];
i++;
}
arr[1] = outputString;
Console.WriteLine(outputString);
string reversed = arr.Aggregate((workingSentence, next) => next + " " + workingSentence);
Console.WriteLine("output -> " + reversed);//world hello
Console.WriteLine("output -> " + ReverseString(reversed));//olleh dlrow
Console.ReadLine();
Edit: As a better solution I removed redundant code. Check this:
static void Main(string[] args)
{
var arr = new string[2];
Console.WriteLine("Enter the string");
var givenstring = Console.ReadLine();
if (givenstring != null)
{
int i = (givenstring.Length) / 2;
arr[0] = givenstring.Substring(0 , i);
arr[1] = givenstring.Substring(i, givenstring.Length - i);
}
Console.WriteLine("Input -> " + arr[0] + " " + arr[1]);//hello world
var reversed = arr.Aggregate((workingSentence, next) => next + " " + workingSentence);
Console.WriteLine("output -> " + reversed);//world hello
Console.WriteLine("output -> " + ReverseString(reversed));//olleh dlrow
Console.ReadLine();
}
static string ReverseString(string str)
{
char[] chars = str.ToCharArray();
char[] result = new char[chars.Length];
for (int i = 0, j = str.Length - 1; i < str.Length; i++, j--)
{
result[i] = chars[j];
}
return new string(result);
}
Try this
string s = "Helloworld someother string";
var str = s.Split(' ')[0];
int i = str.Length/2;
Console.WriteLine(str.Substring(i) + " " + str.Substring(0,i));
//or
Console.WriteLine(string.Join(" ",str.Substring(i),str.Substring(0,i)));
You can use mixture of Skipwhile, Concat and Take methods :
string s = "Helloworld";
int half = s.Length / 2;
s = new String(s.SkipWhile((ss, i) => i < half)
.Concat(" ").Concat(s.Take(half)).ToArray());
Console.WriteLine(s);
Output : world Hello
OR you can simply concat substrings :
string givenstring,outputString="";
Console.WriteLine("Enter the string");
givenstring = Console.ReadLine();
int half = givenstring.Length / 2;
givenstring = givenstring.Substring(half , half) + " " + givenstring.Substring(0, half );
(I assume you've string with just two words because you didn't provide an example of a test string you work with other then Helloworld)...
I have a string which are combination of rules which I have to extract into array. AND condition are seperated by commas while OR move to next array index below are some condtion I am trying
(1 AND 2) AND (3 AND 4) => ["1,2,3,4"]
1 OR 2 => ["1","2"]
(1 OR (2 AND 3)) AND 4 => ["1,4","2,3,4"]
(1 OR 2) OR (3 OR 4) => ["1","2","3","4"]
I have tried the below approach is there a better approach than this.
static void Main(string[] args)
{
string input = "4 AND (1 OR (2 AND 3))";
List<string> output = new List<string>();
string inputTmp = input.Replace("(", "")
.Replace(")", "")
.Replace(" AND ", ",");
if (inputTmp.Contains("OR"))
{
List<string> orOutput = new List<string>();
List<List<string>> cmbOutput = new List<List<string>>();
char splitChar = ' ';
if (input.Contains(")) AND ((")) { inputTmp = input.Replace(")) AND ((", "&"); splitChar = '&'; }
else { if (input.Contains(")) AND ")) { inputTmp = input.Replace(")) AND ", "&"); splitChar = '&'; } }
if (input.Contains(")) OR ((")) { inputTmp = input.Replace(")) OR ((", "|"); splitChar = '|'; }
else { if (input.Contains(")) OR ")) { inputTmp = input.Replace(")) OR ", "|"); splitChar = '|'; } }
if (splitChar != ' ')
{
foreach (var item in inputTmp.Split(splitChar))
{
orOutput.Add(item.Replace("(", "").Replace(")", "").Replace(" AND ", ","));
}
}
else
{
orOutput.Add(input.Replace("(", "").Replace(")", "").Replace(" AND ", ","));
}
foreach (var item in orOutput)
{
List<string> lcOutput = new List<string>();
foreach (var oritem in item.Replace(" OR ", "|").Split('|'))
{
lcOutput.Add(oritem);
}
cmbOutput.Add(lcOutput);
}
if (cmbOutput.Count > 1 && splitChar == '&')
{
for (int i = 0; i < cmbOutput[0].Count; i++)
{
for (int j = 0; j < cmbOutput[1].Count; j++)
{
output.Add(cmbOutput[0][i] + "," + cmbOutput[1][j]);
}
}
}
else
{
foreach (var item in cmbOutput)
{
foreach (var initem in item) { output.Add(initem); }
}
}
}
else
{
output.Add(inputTmp);
}
output.ForEach(o => { Console.WriteLine(o); });
Console.ReadLine();
}
I've created a method that I hope meets your needs. It parses the given expression recursively.
Source code
public static string Parse(string s)
{
return '"' + InnerParse(s).Replace(";", "\",\"") + '"';
}
private static string InnerParse(string s)
{
int pos;
while ((pos = s.IndexOf('(')) != -1)
{
int count = 1;
int nextPos = pos;
while (count != 0)
{
nextPos = s.IndexOfAny(new[] { ')', '(' }, nextPos + 1);
if (nextPos == -1 || nextPos >= s.Length)
throw new ApplicationException(); // Unpaired parentheses
count = s[nextPos] == '(' ? count + 1 : count - 1;
}
s = (pos != 0 ? s.Substring(0, pos - 1) : String.Empty)
+ InnerParse(s.Substring(pos + 1, nextPos - pos - 1)) // Recursion
+ s.Substring(nextPos + 1);
}
string[] operands = s.Split(new[] { "AND", "OR" }, StringSplitOptions.None);
if (operands.Length != 2)
throw new ApplicationException(); // Count of operands != 2
string op1 = operands[0].Trim();
string op2 = operands[1].Trim();
// If operator is OR
if (s.Contains("OR"))
return op1 + ';' + op2;
// If operator is AND
string[] op1s = op1.Split(';');
string[] op2s = op2.Split(';');
string[] ret = new string[op1s.Length * op2s.Length];
int i = 0;
foreach (string s1 in op1s)
foreach (string s2 in op2s)
ret[i++] = s1 + ',' + s2;
return String.Join(";", ret);
}
Usage example
Console.WriteLine(Parse("(1 OR (2 AND 3)) AND 4"));
Restrictions
Two operators are recognized: AND, OR.
Operators are case-sensitive.
Operators have exactly two operands.
Operands cannot contain a double-quote " or a semicolon ;.
I am trying to make some logic, but it is not ful proof yet:
string s = "1234567877y";
StringBuilder sb = new StringBuilder(s);
for (int i = 5; i <= s.Length + (s.Length / 5 ); i += 5 + (s.Length / 5) )
{
sb.Insert(i, Environment.NewLine);
}
Console.WriteLine(sb.ToString());
Console.ReadKey();
Output should be:
12345
67877
y
StringBuilder contain: "12345\r\n67877\r\ny"
But if i change input string i am not getting desired result. What i can do here or suggest some other way around.
EDIT:
if i change
string s = "1234567877y3434";
output will be
12345
67877y
3434
Another concise approach is using GroupBy:
string s = "1234567877y";
IEnumerable<string> groups = s.Select((c, index) => new{ c, index })
.GroupBy(x => x.index / 5)
.Select(xg => string.Join("", xg.Select(x => x.c)));
string result = string.Join(Environment.NewLine, groups);
Here is an approach with a StringBuilder which is more efficient:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
if ((i+1) % 5 == 0)
sb.Append(s[i]).Append(Environment.NewLine);
else
sb.Append(s[i]);
}
i would do it this way :)
string s = "1234567877y3434";
for (int i = 5; i < s.Length; i += 5 + Environment.NewLine.Length)
{
s = s.Substring(0, i) + Environment.NewLine + s.Substring(i, s.Length - i);
}
EDIT: i corrected my code using the suggstestion from Chris using Environment.NewLine instead of \r\n