I'm new to C#. I have a short form and a long form of a client code. The short form is some alpha characters and some numeric ones (ABC12), while the long form is always 15 characters long with the space between the alpha and the numeric parts padded out with zeros (ABC000000000012). I need to be able to convert from the short form to the long. The code below is how I've got it to work - is this the best way to do this?
public string ExpandCode(string s)
{
// s = "ABC12"
int i = 0;
char c;
bool foundDigit = false;
string o = null;
while (foundDigit == false)
{
c = Convert.ToChar(s.Substring(i, 1));
if (Char.IsDigit(c))
{
foundDigit = true;
o = s.Substring(0, i) + new String('0', 15-s.Length) + s.Substring(i,s.Length-i);
}
i += 1;
}
return (o); //o = "ABC000000000012"
}
Your code is basically correct, however it could be slow, since String.Substring(...) creates a new string every time called.
I also suggest that you use the built-in functions of the .NET api for accomplishing your tasks, which can make coding easier a lot:
private char[] numbers = new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
public string ExpandCode(string s)
{
//Find the first numeric char.
int index = s.IndexOfAny(numbers);
//Insert zeros and return the result.
return s.Insert(index, new String('0', 15 - s.Length));
}
Take a look at this:
public string ExpandCode(string s)
{
var builder = new StringBuilder(s);
var index = Array.FindIndex(s.ToArray(), x => char.IsDigit(x));
while (builder.Length < 15)
{
builder.Insert(index, '0');
}
return builder.ToString();
}
I assume that string are always letter -> digit (like "abc123" or "ab1234").
The purer, the faster
public static string ExpandCode4(string s)
{
char[] res = new char[15];
int ind = 0;
for (int i = 0; i < s.Length && s[i] >= 'A'; i++)
res[ind++] = s[i];
int tillDigit = ind;
for (int i = 0; i < 15 - s.Length; i++)
res[ind++] = '0';
for (int i = 0; i < s.Length - tillDigit; i++)
res[ind++] = s[tillDigit + i];
return new string(res);
}
Benchmark for all the answers is as follows,
internal class Program
{
private static void Main(string[] args)
{
var inputs = new List<string>();
for (int i = 0; i < 10000000; i++)
{
inputs.Add("ABC1234");
}
var n1 = DateTime.Now;
inputs.ForEach(i => ExpandCode1(i));
var r1 = (DateTime.Now - n1).Ticks;
var n2 = DateTime.Now;
inputs.ForEach(i => ExpandCode2(i));
var r2 = (DateTime.Now - n2).Ticks;
var n3 = DateTime.Now;
inputs.ForEach(i => ExpandCode3(i));
var r3 = (DateTime.Now - n3).Ticks;
var n4 = DateTime.Now;
inputs.ForEach(i => ExpandCode4(i));
var r4 = (DateTime.Now - n4).Ticks;
var results = new List<Result>()
{
new Result() {Name = "1", Ticks = r1},
new Result() {Name = "2", Ticks = r2},
new Result() {Name = "3", Ticks = r3},
new Result() {Name = "4", Ticks = r4}
};
results.OrderBy(r => r.Ticks).ToList().ForEach(Console.WriteLine);
Console.ReadKey();
}
public static string ExpandCode4(string s)
{
char[] res = new char[15];
int ind = 0;
for (int i = 0; i < s.Length && s[i] >= 'A'; i++)
res[ind++] = s[i];
int tillDigit = ind;
for (int i = 0; i < 15 - s.Length; i++)
res[ind++] = '0';
for (int i = 0; i < s.Length - tillDigit; i++)
res[ind++] = s[tillDigit + i];
return new string(res);
}
public static string ExpandCode1(string s)
{
char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
//Find the first numeric char.
int index = s.IndexOfAny(numbers);
//Insert zeros and return the result.
return s.Insert(index, new String('0', 15 - s.Length));
}
public static string ExpandCode2(string s)
{
var builder = new StringBuilder(s);
var index = Array.FindIndex(s.ToArray(), x => char.IsDigit(x));
while (builder.Length < 15)
{
builder.Insert(index, '0');
}
return builder.ToString();
}
public static string ExpandCode3(string s)
{
var match = Regex.Match(s, #"([^\d]+)(\d+)");
var letters = match.Groups[1].Value;
var numbers = int.Parse(match.Groups[2].Value);
var formatString = "{0}{1:d" + (15 - letters.Length) + "}";
var longForm = string.Format(formatString, letters, numbers);
return longForm;
}
}
public class Result
{
public long Ticks { get; set; }
public string Name { get; set; }
public override string ToString()
{
return Name + " - " + Ticks;
}
}
You can use string.Format() to take care of the padding for you. I used regex (and not in a very robust manner) to parse out the letters and numbers but you may be able to do this more efficiently another way.
The key point is that we dynamically figure out how many zero's we need, and then use a format string of the form X:dY where X = format ordinal and Y = the number of zeros you wish to pad.
var match = Regex.Match("ABC12", #"([^\d]+)(\d+)");
var letters = match.Groups[1].Value;
var numbers = int.Parse(match.Groups[2].Value);
var formatString = "{0}{1:d" + (15 - letters.Length) + "}";
var longForm = string.Format(formatString, letters, numbers);
Related
I would like to allow users to choose the exact length, or less than / more than count o characters to be generated (in a password generator).
For example i have done:
// the longivity of the generated string
var stringChars = new char[int.Parse(TextBox2.Text)];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
// abc has been declared before, it is simply ABCD... for character generation
stringChars[i] = abc[random.Next(abc.Length)];
}
var finalString = new String(stringChars);
// this is the result box
TextBox1.Text = finalString;
Now my problem is if user enters for eg. 10 and wants less than 10 characters of generated string, what should I do?
You could do for example something like this (with the power of Linq):
public string GeneratePassword(string abc, int minLenght, int maxLenght)
{
var random = new Random();
var chars = Enumerable
.Range(0, random.Next(minLenght, maxLenght + 1)) // Generate a range between the min and max.
.Select(x => abc[random.Next(abc.Length)]) // Select a random character from the abc.
.ToList();
// Concatenate the string.
return string.Join(string.Empty, chars);
}
You have to using the System.Linq
Usage:
var input = 10;
var abc = "abcde";
var maxPasswordLength = 100;
var minPasswordLength = 1;
// More than the input.
GeneratePassword(abc, input + 1, maxPasswordLength);
// Less than the input.
GeneratePassword(abc, minPasswordLength, input - 1);
// Exact length.
GeneratePassword(abc, input, input);
public class Program
{
private const int MAX_LENGTH = 50;
static void Main(string[] args)
{
var less = GeneratedLessThan(12);
var more = GeneratedMoreThan(12);
Console.WriteLine($"Less Than : {less} ({less.Length})");
Console.WriteLine($"More Than : {more} ({more.Length})");
Console.ReadLine();
}
static char[] ABC()
{
List<char> list = new List<char>();
for (char i = 'A'; i <= 'Z'; i++)
{
list.Add(i);
}
return list.ToArray();
}
static string GeneratedLessThan(int max) => GeneratedString(0, max);
static string GeneratedMoreThan(int min) => GeneratedString(min, MAX_LENGTH);
static string GeneratedString(int min, int max)
{
StringBuilder builder = new StringBuilder();
var abc = ABC();
var rnd = new Random();
for (int i = 0; i <= rnd.Next(min, max); i++)
{
builder.Append(abc[rnd.Next(abc.Length)]);
}
return builder.ToString();
}
}
Maybe you dont need ABC function.
Ouput :
Less Than : IORS (4)
More Than : BSVPFZVQRWZTSPYDI (17)
How do I get all alpha-number combo's in a given alpha-number combo range using c#?
For getting all numbers in a range I'll do something like below
int x = 10;
int y = 15;
int z=y-x+1;
var range =Enumerable.Range(x,z);
foreach (var element in range)
{
Console.WriteLine(element.ToString()+"-->"+x.ToString()+"-"+y.ToString());
}
Console.ReadLine();
But when the value of x is like 1x and y is like 2b how do I get the range of strings like below?
1x
1y
1z
2a
2b
First, parse the string to get the numerical value and the character. Then, loop for each number from the start to the end. Inside, loop for each character in the alphabet from the start to the current end.
Here you go:
string x = "1x";
string y = "2b";
char startCharacter = x.Substring(x.Length-1)[0];
char endCharacter = y.Substring(y.Length-1)[0];
int startNumber = int.Parse(x.Substring(0, x.Length - 1));
int endNumber = int.Parse(y.Substring(0, y.Length - 1));
var range = new List<string>();
string alphabet = "abcdefghijklmnopqrstuvwxyz";
for(int i = startNumber; i <= endNumber; ++i) {
int currentCharEnd = (i == endNumber) ? alphabet.IndexOf(endCharacter) : alphabet.Length - 1;
for(int j = alphabet.IndexOf(startCharacter); j <= currentCharEnd; ++j) {
range.Add(i.ToString() + alphabet[j]);
}
startCharacter = 'a';
}
// range is now { "1x", "1y", "1z", "2a", "2b" }
You can start by doing this, and extend it to achieve your task fully.
string[] abc = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" };
string x = "1g";
string y = "2b";
string strx = Regex.Match(x, #"\d+").Value;
string stra = Regex.Match(x, #"[a-z]+").Value;
int intx = Int32.Parse(strx);
string stry = Regex.Match(y, #"\d+").Value;
string strb = Regex.Match(x, #"[a-z]+").Value;
int inty = Int32.Parse(stry);
Console.WriteLine(strx);
Console.WriteLine(stra);
Console.WriteLine("----");
int len = inty - intx + 1;
List<string> xycombinations = new List<string>();
string[] ycombinations = new string[] { };
if (len >= 0)
{
int starting = 0;
while (abc[starting] != stra)
{
starting = starting + 1;
}
while (starting < abc.Length)
{
xycombinations.Add(intx.ToString() + abc[starting]);
starting = starting + 1;
}
for (int i = 0; i < xycombinations.Count; i++)
{
Console.WriteLine(xycombinations[i]);
}
}
Console.ReadLine();
It only makes the combination of string x till the end, for instance string x is "1g", so this code makes combinations 1g, 1h, 1i, ij. Similarly you can make combinations of string y by extending. Hope it helps you.
I have to Find the longest SubString without any number and at least one upper case character using c#. If the string is "sdcF01h" then o/p should be "sdcF"
My approach.
String testString = "sdcF01F";
//var splitString = testString.Split("[0-9]");
int startIndex = 0;
int longestStartIndex = 0;
int endIndex = 0;
int index = 0;
int longestLength = int.MinValue;
bool foundUpperCase = false;
while (index <= testString.Length)
{
if (index == testString.Length || char.IsDigit(testString[index]))
{
if (foundUpperCase && index > startIndex && index - startIndex > longestLength)
{
longestLength = index - startIndex;
endIndex = index;
longestStartIndex = startIndex;
}
startIndex = index + 1;
foundUpperCase = false;
}
else if (char.IsUpper(testString[index]))
{
foundUpperCase = true;
}
index++;
}
endIndex--;
var res1 = testString.Substring(longestStartIndex, endIndex);
Console.WriteLine(res1);
But this is not the most optimal solution.
There is problem in your question example:
if the string is "sdch01F" then o/p should be "sdcF" My approach.
The right should be result is F.
I suppose you mean that "sdcF01F" the result is "sdcF" (like in the your code example).
Any way this is my solution*:
private string GetLongestSubstring(string testString)
{
var longestSubstring = string.Empty;
if (string.IsNullOrEmpty(testString))
{
return longestSubstring;
}
var rg = new Regex("[A-Z]");
var currentSubstring = string.Empty;
for (int i = 0; i < testString.Length; i++)
{
var currentChar = testString[i];
var isValidChar = !char.IsDigit(currentChar);
if (!isValidChar)
{
var newSubstring = currentSubstring;
currentSubstring = string.Empty;
var matches = rg.Match(newSubstring);
var iscurrentSubstringContainsAtLeastOneCapitalLetter = matches.Success;
if (iscurrentSubstringContainsAtLeastOneCapitalLetter)
{
if (longestSubstring.Length < newSubstring.Length)
{
longestSubstring = newSubstring;
}
}
continue;
}
currentSubstring += currentChar.ToString();
}
if (currentSubstring.Length > longestSubstring.Length)
{
longestSubstring = currentSubstring;
}
return longestSubstring;
}
Note, the function takes into account that there is no space (" ") in the string.
Just split, sort on length, and test for upper
public static string GetSubset(string input = "LKAH8slfsfjlllj9lkjlkjasdf;lk7ljasdflkasdjsfdljk")
{
if (string.IsNullOrEmpty(input))
return string.Empty;
foreach(String s in input.Split(new Char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }).OrderByDescending(x => x.Length))
{
foreach (char c in s)
if (char.IsUpper(c))
return s;
}
return string.Empty;
}
var abc= Regex.Matches("co12dEname123abP", #"[a-zA-Z]+|\d+")
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
List<string> lst = new List<string>();
for (int i = 0; i < abc.Length; i++)
{
if (abc[i].Any(char.IsDigit))
continue;
if (abc[i].Any(c => char.IsUpper(c)))
lst.Add(abc[i]);
}
var finalOutput =lst.OrderByDescending(x => x.Length).FirstOrDefault();
public void generate()
{
string alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string small_alphabets = "abcdefghijklmnopqrstuvwxyz";
string numbers = "1234567890";
string characters = numbers;
characters += alphabets + small_alphabets + numbers;
int length =6;
string opt = string.Empty;
for (int i = 0; i < length; i++)
{
string character = string.Empty;
do
{
int index = new Random().Next(0, characters.Length);
character = characters.ToCharArray()[index].ToString();
} while (otp.IndexOf(character) != -1);
otp += character;
}
string str= otp;
}
This is my code, which is not working for me.
I want to try small alphabet, capital alphabet and 0 to 9 number combination.
Here is the code :
var chars1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
var stringChars1 = new char[6];
var random1 = new Random();
for (int i = 0; i < stringChars1.Length; i++)
{
stringChars1[i] = chars1[random1.Next(chars1.Length)];
}
var str= new String(stringChars1);
This code will give you numeric otp of n digits.
public static int GenerateOTP(int digits)
{
if (digits < 3)
return new Random().Next(10, 99);
else
return new Random().Next(MultiplyNTimes(digits), MultiplyNTimes(digits + 1) - 1);
}
private static int MultiplyNTimes(int n)
{
if (n == 1)
return 1;
else
return 10 * MultiplyNTimes(n - 1);
}
I'm attempting to subtract two strings (of theoretically infinite length) without the use of libraries like BigIntbut I was wondering if anybody has any good ideas on how to remove the leading zeros in the corner cases like the one below?
static void Main(string[] args)
{
Console.WriteLine(Subtract("10", "10005"));
}
static string ReverseInput(string inputString)
{
char[] charArray = inputString.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
static string Subtract(string firstNumInput, string secondNumInput)
{
string firstNum = String.Empty;
string secondNum = String.Empty;
bool negative = false;
// Reverse order of string input
if (firstNumInput.Length > secondNumInput.Length)
{
firstNum = ReverseInput(firstNumInput);
secondNum = ReverseInput(secondNumInput);
}
else if (firstNumInput.Length < secondNumInput.Length)
{
negative = true;
firstNum = ReverseInput(secondNumInput);
secondNum = ReverseInput(firstNumInput);
}
else if (firstNumInput.Length == secondNumInput.Length)
{
// iterate through string to find largest
}
char[] result = new char[firstNum.Length + 1];
int resultLength = 0;
int carry = 0;
for (int i = 0; i < firstNum.Length; i++)
{
int an = (i < firstNum.Length) ? int.Parse(firstNum[i].ToString()) : 0;
int bn = (i < secondNum.Length) ? int.Parse(secondNum[i].ToString()) : 0;
int rn = an - bn - carry;
if (rn < 0)
{
carry = 1;
rn += 10;
}
else
{
carry = 0;
}
result[resultLength++] = (char)(rn + '0');
}
// create the result string from the char array
string finalResult = ReverseInput(new string(result, 0, resultLength));
if (negative)
{
finalResult = '-' + finalResult;
}
return finalResult;
}
Are you looking for TrimStart?
// create the result string from the char array
string finalResult = ReverseInput(new string(result, 0, resultLength)).TrimStart('0');