I want something similar to this question I found lead me to this answer on another question where I tried to convert it from php to c# my attempt to convert it... failed very badly:
private string trimString(string str, int maxCharacters = 16)
{
int textLength = str.Length;
return str.Substring(maxCharacters/2, textLength-maxCharacters).Insert(maxCharacters/2,"...");
}
So doing trimString("123456789", 9) outputs 123...789 when I meant to do something like 123...012 or something similar.. I can't quite figure it out and I've tried many different versions mostly resulting in an input that is out of order.
If it's possible I'd like it to be a simple function and not include other libraries or initializing a new object every call as I plan on using this a lot in a quick session. I'd really like it not to cut off words and place the ellipses however this is not required.
The problem is that Substring(maxCharacters/2, textLength-maxCharacters) into which you insert the ... already has the characters that you don't want to see - 456789. There's no way to fix it after that.
What you should do instead is to pick the prefix and the suffix, and join them together, like this:
private static string trimString(string str, int maxCharacters = 16) {
if (str.Length <= maxCharacters) {
return str;
}
var suffixLength = maxCharacters / 2;
// When maxCharacters is odd, prefix will be longer by one character
var prefixLength = maxCharacters - suffixLength;
return string.Format(
"{0}...{1}"
, str.Substring(0, prefixLength)
, str.Substring(str.Length-suffixLength, suffixLength)
);
}
Demo.
this returns 123...012 for trimString("123456789012", 6) the first and the last 3 characters, seperated with ....
public static string trimString(string str, int max = 16)
{
if (str.Length <= max)
{
return str;
}
return str.Substring(0, max / 2) + "..." + str.Substring(str.Length - max / 2, max / 2);
}
Related
List<int> arr = new List<int>();
long max = 0;
long mul = 1;
string abc = #"73167176531330624919225119674426574742355349194934
85861560789112949495459501737958331952853208805511
96983520312774506326239578318016984801869478851843
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450";
foreach (char a in abc)
{
if(arr.Count == 13)
{
arr.RemoveAt(0);
}
int value = (int)Char.GetNumericValue(a);
arr.Add(value);
if(arr.Count == 13)
{
foreach(int b in arr)
{
mul = mul * b;
if (mul > max)
{
max = mul;
}
}
mul = 1;
}
}
Console.WriteLine(max);
I am getting 5377010688 which is a wrong answer and when I am trying same logic with given example in project Euler it is working fine, please help me.
Don't say the answer just correct me where I am doing wrong or where the code is not running as it should.
The string constant, as it is written down like above, contains blanks and \r\n's, e.g. between the last '4' of the first line and the first '8' on the second line. Char.GetNumericValue() returns -1 for a blank.
Propably the character sequence with the highest product spans across adjacent lines in your string, therefore there are blanks in between, which count as -1, which disables your code in finding them.
Write your constant like this:
string abc = #"73167176531330624919225119674426574742355349194934" +
"85861560789112949495459501737958331952853208805511" +
"96983520312774506326239578318016984801869478851843" + etc.
The result is then 23514624000, I hope that's correct.
Don't say the answer just correct me where I am doing wrong or where
the code is not running as it should
You have included all characters into calculation but you should not do that. The input string also contains for example carriage return '\n' at the end of each line.
Your actual string look like this:
string abc = #"73167176531330624919225119674426574742355349194934\r\n
85861560789112949495459501737958331952853208805511\r\n
...
How to solve this? You should ignore these characters, one possible solution is to check each char if it is a digit:
if(!char.IsDigit(a))
{
continue;
}
Whenever I am given a 11-digit number (like 12345678901, 82344678971 etc.), I want to partition it into 4 parts as 5digits-4digits-1digit-1digit always. So:
12345678901 -> 12345 6789 0 1
82344674971 -> 82344 6749 7 1
I saw a similar question in SOF but it uses regular blocks; namely same number of digits: Splitting a string / number every Nth Character / Number?
I want a function that will take any 11-digit (long) integer as parameter, and will return as the above way; from where I could be able to get any block I want: For example, SplitInParts(1) will return 12345; SplitInParts(2) will return 6789; SplitInParts(3) will return 0; SplitInParts(4) will return 1. Similarly for 82344674971: 82344, 6749, 7, 1 respectively.
Being a novice in C#, I could not achieve how to perform the above via C#.
This is an extension method on long that works in a similar manner to the example you provided and I think it's quite readable although it might not perform as well as other solutions.
public static class LongExtensions
{
public static int SplitIntoIrregularParts(this long longNumber, int partIndexToReturn)
{
int[] blocks = string.Format("{0:##### #### # #}", longNumber).Split(' ').Select(x => int.Parse(x)).ToArray();
return blocks[partIndexToReturn];
}
}
If you have it an integer, you can get the decimal digits out using something like:
List<int> GetDigits(long number){
var result = new List<int>();
while (number != 0){
result.Insert(0, (int)(number %10));
number /=10;
}
return result;
}
This uses repeated division and modulo 10 to get the singular digits into a List<int>
Now, from that you can get your formatted string in a number of ways, e.g. and using string.Join (framework 4.5 and above) on them, like:
var digits = GetDigits(12345678901);
var part1 = string.Join("",digits.Take(5));
var part2 = string.Join("",digits.Skip(5).Take(4));
var part3 = string.Join("",digits.Skip(9).Take(1));
var part4 = string.Join("",digits.Skip(10).Take(1));
This solution is a tad slower (albeit more fun) than the solutions that just use number.ToString(), so if you just need the format, go with that. Use this if you actually need the digits themselves.
Use this function where I use substring.
private string getMySubString(long value, int splitPart)
{
string str = value.ToString();
if (str.Length != 11) return "invalid number lenght";
string sub1 = str.Substring(0, 5);
string sub2 = str.Substring(5, 4);
string sub3 = str.Substring(9, 1);
string sub4 = str.Substring(10, 1);
switch (splitPart)
{
case 1:
return sub1;
case 2:
return sub2;
case 3:
return sub3;
case 4:
return sub4;
default:
return "Invalid part number";
}
}
Use "value" as original value that you want split and "splitPart" as number of part you want extract. I hope this is what you are asking
If you want , then you can convert the returned string into an Integer
Use the Take and Skip extension methods of Enumerable on a character array
Here are a few options:
string id = 82344678971.ToString();
string parsed = Regex.Replace(id, #"(\d{5})(\d{4})(\d{1})(\d{1})", #"$1 $2 $3 $4");
string parsed2 = String.Join(" ", new string[] {
id.Substring(0, 5),
id.Substring(5, 4),
id.Substring(9, 1),
id.Substring(10, 1)
});
char[] chars = id.ToCharArray();
string parsed3 = String.Join(" ", new string[] {
new String(chars, 0, 5),
new String(chars, 5, 4),
new String(chars, 9, 1),
new String(chars, 10, 1)
});
Depending on how you want to handle numbers shorter than 11 digits, then this might be a robust option. It copes with any number of digits, adding spaces if possible.
But you can use something simpler if you just need it to fail if the number of digits is less than 11.
var t = InsertGaps(12345678912);
private string InsertGaps(long value)
{
var result = value.ToString();
result = InsertGap(result, 5);
result = InsertGap(result, 10);
result = InsertGap(result, 12);
return result;
}
private string InsertGap(string value, int index)
{
if (value.Length > index)
{
return value.Insert(index, " ");
}
return value;
}
I am taking a line from a file only if that file doen't have a specific pattern.. and i want to take from that line the last 3 chars... my code is:
while (!line.Contains(pattern))
{
String num = line.Substring((line.Length - 3), (line.Length - 2));
System.Console.WriteLine(num);
}
but i get an error..
Index and length must refer to a location within the string.
Parameter name: length
why i get that? i am starting the new string 3 chars before the end of the line and i stop 2 chars before.. :\
Substring takes an offset and then a number of characters to return:
http://msdn.microsoft.com/en-us/library/aa904308%28v=VS.71%29.aspx
So:
String num = line.Substring((line.Length - 3), 3);
This of course assumes that line.Length > 3. You could check with:
String num = (line.Length < 3) ? line : line.Substring((line.Length - 3), 3);
Second argument of Substring is how many chars it have to take starting from first argument. It should just look like that:
String num = line.Substring(line.Length - 3, 3);
This is dangerous. What if the length of the line is < 3? You should probably check this otherwise you will get an exception.
In addition you should use the substring method as depicted here :
String num = line.Substring((line.Length - 3), 3);
The problem is that you try to get more characters then your array have.
Extensions are best for problems like this one ;) Mine have some dirty name but everyone know what it would do - this is exception safe substring:
public static string SubstringNoLongerThenSource(this string source, int startIndex, int maxLength)
{
return source.Substring(startIndex, Math.Min(source.Length - startIndex, maxLength));
}
So in your exact problem it should be like that:
String num = line.SubstringNoLongerThenSource((line.Length - 3), 3);
System.Console.WriteLine(num);
So num will have max 3 letters if the string you provide to function have enough letters :)
String num = line.Substring(line.Length - 3)
This is happening because the last parameter of Substring() should be the length of the string to extract.
In your case it should be 3
, and not line.Length - 2
The first parameter should also be:
line.Length - 3
I would like to implement a functionality that insert a word-breaking TAG if a word is too long to appear in a single line.
protected string InstertWBRTags(string text, int interval)
{
if (String.IsNullOrEmpty(text) || interval < 1 || text.Length < interval)
{
return text;
}
int pS = 0, pE = 0, tLength = text.Length;
StringBuilder sb = new StringBuilder(tLength * 2);
while (pS < tLength)
{
pE = pS + interval;
if (pE > tLength)
sb.Append(text.Substring(pS));
else
{
sb.Append(text.Substring(pS, pE - pS));
sb.Append("");//<wbr> not supported by IE 8
}
pS = pE;
}
return sb.ToString();
}
The problem is: What can I do, if the text contains html-encoded special chars?
What can I do to prevent insertion of a TAG inside a ß?
What can I do to count the real string length (that appears in browser)?
A string like ♡♥♡♥ contains only 2 chars (hearts) in browser but its length is 14.
One solution would be to decode the entities into the Unicode characters they represent and work with that. To do that use System.Net.WebUtility.HtmlDecode() if you're in .NET 4 or System.Web.HttpUtility.HtmlDecode() otherwise.
But be aware that not all Unicode character fit in one char.
You need to pass through whole text character by character, when you find a & than you examine what is next, if you reach a # it is quite sure that after this till a column will be a set of number (you can check it also). I such situation you move your iterator to the position of nearest semicolon and increment the counter.
In Java dialect
int count = 0;
for(int i = 0; i < text.length(); i++) {
if(text.charAt(i) == '&') {
i = text.indexOf(';', i) + 1; // what, from
}
count++;
}
Very simplified version
I have a regex to find the nth occurrence of a character in a string, here's the code:
public static int NthIndexOf(this string target, string value, int n)
{
Match m = Regex.Match(target, "((" + value + ").*?){" + n + "}");
if (m.Success)
{
return m.Groups[2].Captures[n - 1].Index;
}
else
{
return -1;
}
}
Now, I have 1594 entries in this string, with 1593 semicolons. If I write:
tempstring.NthIndexOf(";", 1593)
The answer comes back immediately and correctly. If I give it anything over 1594 it hangs. Does anyone know how to fix this?
Test Case
string holder = "test;test2;test3";
string test = "";
for (int i = 0; i < 600; i++)
{
test += holder;
}
int index = test.NthIndexOf(";", 2000);
This takes a very long time. Change 600 to 6 and it is very fast. Make 2000 to 1700 and it is very fast as well.
Why is my regular expression so slow?
If you're really only looking for character repetitions, and not string repetitions, then you should be able to replace you method with something simple like
public static int NthIndexOf(this string target, char testChar, int n)
{
int count = 0;
for(int i=0; i<target.Length; i++)
{
if(target[i] == testChar)
{
count++;
if(count == n) return i;
}
}
return -1;
}
and use that. It should have far fewer limitations.
As for why your original regex is going slow, here's what I suspect:
For your fast case, it's working because it can find a match on it's first pass through (with each group matching exactly one character)
For the slow case is because it can't find a match (and won't ever find one, because there aren't enough semicolons to satisfy the regex), but it recursively tries every possible way to break up the string (which is a really big operation)
Try to use a more distinct and efficient regular expression:
"^(?:[^" + value + "]*" + value + "){" + (n - 1) + "}([^" + value + "]*)
This will build the following regular expression for tempstring.NthIndexOf(";", 1593):
^(?:[^;]*;){1592}([^;]*)
But this will only work for single characters as separator.
Another approach would be to step through each character and count the occurences of the character you were looking for.