I have alphanumeric string list.
For example:
1A
2B
7K
10A
I want to get only the numeric part and then compare them, if it is less than 10 I need not to add it in another list.
What I want to know the regex to split the numeric part from the string.
Any help.
What I have done till now is:
if (x == y) // also handles null
return 0;
if (x == null)
return -1;
if (y == null)
return +1;
int ix = 0;
int iy = 0;
while (ix < x.Length && iy < y.Length)
{
if (Char.IsDigit(x[ix]) && Char.IsDigit(y[iy]))
{
// We found numbers, so grab both numbers
int ix1 = ix++;
int iy1 = iy++;
while (ix < x.Length && Char.IsDigit(x[ix]))
ix++;
while (iy < y.Length && Char.IsDigit(y[iy]))
iy++;
string numberFromX = x.Substring(ix1, ix - ix1);
string numberFromY = y.Substring(iy1, iy - iy1);
// Pad them with 0's to have the same length
int maxLength = Math.Max(
numberFromX.Length,
numberFromY.Length);
numberFromX = numberFromX.PadLeft(maxLength, '0');
numberFromY = numberFromY.PadLeft(maxLength, '0');
int comparison = _CultureInfo
.CompareInfo.Compare(numberFromX, numberFromY);
if (comparison != 0)
return comparison;
}
else
{
int comparison = _CultureInfo
.CompareInfo.Compare(x, ix, 1, y, iy, 1);
if (comparison != 0)
return comparison;
ix++;
iy++;
}
}
But I don't want to be so complex in my approach.
So I need a regex to split.
Try IsDigit method of char
var number = int.Parse(new string(someString.Where(char.IsDigit).ToArray()));
if(number<10)
{
someList.Add(number);
}
using All and IsDigit you can take only numeric part of the string, then parse it to int and compare :) There is no need to use Regexes
You can use the code below to split an input string and get the result of number group and alpha group. If one group is not there, the result will be empty string.
string input = "10AAA";
Match m = Regex.Match(input, #"(\d*)(\D*)");
string number = m.Groups[1].Value;
string alpha = m.Groups[2].Value;
you can try it with this one:
string txt="10A";
string re1="(\\d+)"; // Integer Number 1
Regex r = new Regex(re1);
Match m = r.Match(txt);
Are you trying to do this?
int num;
string stringWithNumbers = "10a";
if (int.TryParse(Regex.Replace(stringWithNumbers, #"[^\d]", ""), out num))
{
//The number is stored in the "num" variable, which would be 10 in this case.
if (num >= 10)
{
//Do something
}
}
else
{
//Nothing numeric i the string
}
Related
im trying to learn how to get the coincidence porcentage between two base 64 strings in asp.net c#
i woul like to have
String A
String B
and to get a result like this
coincidence = 80,3454
You can compare char by char, regarding the positions of each pair of chars. Divide the number of coincide chars with the number of chars in that base64 string. You'll get the percentage.
This assumes that both strings will be the same length. And if they're base64 then presumably they're already upper case. But you can adjust either of those requirements as needed.
public static float CoincidenceRate(string a, string b)
{
if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b) || a.Length != b.Length)
{
throw new ArgumentException("Both strings must be non-null, non-empty, and the same length.");
}
float matches = 0;
for (var index = 0; index < a.Length; index++)
{
if (a[index] == b[index])
{
matches++;
}
}
return matches / a.Length;
}
What if they're not the same length? You could do this:
public static float Base64CoincidenceRate(string a, string b)
{
if (a == null || b == null)
{
throw new ArgumentNullException("Neither input may be null.");
}
// prevent division by zero
if (a.Length == 0 && b.Length == 0)
{
return 0; // or throw an exception, or return 1.
}
string paddedA = a.Length >= b.Length ? a : a.PadRight(b.Length, ' ');
string paddedB = b.Length >= a.Length ? b : b.PadRight(a.Length, ' ');
float matches = 0;
for (var index = 0; index < paddedA.Length; index++)
{
if (paddedA[index] == paddedB[index])
{
matches++;
}
}
return matches / paddedA.Length;
}
In this case the inputs must be base64. Otherwise if they're not the same length and the longer one contains spaces the result may be off. As long as neither contains spaces, padding the shorter one with spaces ensures that characters appended to one won't match characters in the other.
I need to get the index of the n-th character of that type in a string.
Example:
string test = "asdfasdfasdf";
int index = test.IndexOf("a", 3);
and index would be 8, since the 3rd a has the index of 8
Is there a function that does that or do you have any idea how to do that in a smart way?
You can do it in a single line, but it is not pretty:
var s = "aabbabhjhjdsfbaxt";
var idx = s.Select((c, i) => new {c, i})
.Where(p => p.c == 'a')
.Skip(2)
.FirstOrDefault()?.i ?? -1;
The idea is to pair up characters with their indexes, filter by character, skip n-1 items, and take the next one if it exists.
Another approach would be to use regex with look-behind:
var idx = Regex.Match(s, "(?<=(a[^a]*){2})a").Index;
This matches an 'a' preceded by two more 'a's, possibly with other characters in the middle.
A simple for loop will do the trick, but you can place the for loop in an extension method to get this functionality as a one-liner throughout your application.
Like this:
public static int NthIndexOf(this string text, char letter, int occurrence)
{
if (text == null) throw new ArgumentNullException(nameof(text));
int count = 0;
for (int index = 0; index < text.Length; index++)
if (text[index] == letter)
{
if (++count == occurrence)
return index;
}
return -1;
}
Usage:
string test = "asdfasdfasdf";
int index = test.IndexOf('a', 3);
You can create an extension method for this like that:
public static int NthIndexOf(this string s, char c, int occurence)
{
if (s == null) throw new ArgumentNullException(nameof(s));
if (occurence <= 0) return -1;
int i = -1, o = 0;
do
{
i = s.IndexOf(c, i+1);
o++;
} while (i >= 0 && o < occurence);
return i;
}
After checking the input arguments it consecutivly uses string.IndexOf() to get the n-th index of the desired character c.
If no further occurence of c is found (IndexOf returns -1) the loop breaks.
Usage:
string test = "asdfasdfasdf";
int index = test.NthIndexOf('a', 3); // 8
Of course you can do the same with a parameter of type string for c instead of char, but would need to change s.IndexOf(c, i+1) to s.IndexOf(c, i+c.Length).
As René Vogt said you should use an extension method chaining calls to IndexOf() for performance reasons:
public static int NthIndexOf(this string s, string value, int n)
{
var index = -1;
for (; n > 0; n--)
index = s.IndexOf(value, index + 1);
return index;
}
This returns the 0-based start index of the (1-based) nth occurence of the string value.
Here is a working example: https://dotnetfiddle.net/xlqf2B
I'm trying to get the largest palindrome that can be formed by k replacements of digits in the string number.
e.g.
number="3943",k=1 --> "3993"
For that exact test case I am getting "393" and for some test cases I am getting an error like
Unhandled Exception: System.InvalidOperationException: Sequence
contains no elements at System.Linq.Enumerable.Last[TSource]
(IEnumerable`1 source) <0x414ec920 + 0x001ab> in :0
at Solution.LargestPalindrome (System.String numstr, Int32 k)
[0x00197] in solution.cs:74 at
Solution+c__AnonStorey0.<>m__0 (System.String str)
[0x00009] in solution.cs:61
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Solution
{
static bool IsPalindrome(string s)
{
// returns true or false depending on whether the string
// s is a palindrome
// e.g. "abba" --> true, "acba" --> false
for(int i = 0, j = s.Length - 1; i < j; ++i, --j)
{
if(s[i] != s[j])
return false;
}
return true;
}
static string Replace(string s, int i, char c)
{
// returns a copy of s with the character at index i
// replaced by character c
// e.g. "george",2,"x" --> "gexrge"
string part1 = s.Length > 0 ? s.Substring(0, i) : string.Empty;
string part2 = i < (s.Length - 1) ? c.ToString() : string.Empty;
string part3 = (i + 1) < (s.Length - 1) ? s.Substring(i + 1, s.Length - i - 1) : string.Empty;
return part1 + part2 + part3;
}
static string LargestPalindrome(string numstr, int k)
{
// numstr: string representation of number
// k: maximum number of digit replacements allowed
// if no digit replacements allowed, return same string
if(k == 0)
return numstr;
// digrange will be {'0', '1', ..., '9'}
List<char> digrange = new List<char>();
for(char c = '0'; c <= '9'; ++c)
digrange.Add(c);
// possibilities will be all possibilities of replacing one digit from numstr
// e.g. numstr="02" --> possibilities={"12","22","32",...,"92","00","01","03","09"}
List<string> possibilities = new List<string>();
for(int i = 0; i < numstr.Length; ++i)
{
foreach(char dig in digrange.Where(d => d != numstr[i]))
{
possibilities.Add(Replace(numstr,i,dig));
}
}
// if k = 1, get all the strings in cumulativePossiblities that are palindromes;
// else, transform each into the largest palindrome formed by k - 1 character
// replacements of itself
var cumulativePossibilities = k == 1
? possibilities.Where(str => IsPalindrome(str))
: possibilities.Select(str => LargestPalindrome(str, k - 1)).Where(str => IsPalindrome(str));
// sort cumulativePossibilities in ascending order of the integer representation
// of the strings
cumulativePossibilities.ToList().Sort((s1,s2) => {
Int64 i1 = Int64.Parse(s1),
i2 = Int64.Parse(s2);
return (i1 > i2) ? 1 : ((i1 == i2) ? 0 : -1);
});
// get the last element of the now-sorted cumulativePossibilities,
// which will be the largest number represented by the possible strings
// or will be null if there are none
string largest = cumulativePossibilities.Last();
// return the largest or "-1" if there were none
return largest != null ? largest : "-1";
}
static void Main(String[] args)
{
string[] tokens_n = Console.ReadLine().Split(' ');
int k = Convert.ToInt32(tokens_n[1]);
string number = Console.ReadLine();
// use brute force algorithm to find largest palindrome of the string
// representation of the number after k replacements of characters
Console.WriteLine(LargestPalindrome(number,k));
}
}
Not very efficient method, but simple to implement; the key feature is using PalindromeSubstitutions (counting how many characters' substitutions prevents string from being palindrome) instead of IsPalindrome (just a fact if string is palindrome or not)
// How many characters should be substituted in order to
// turn the string into palindrom
private static int PalindromeSubstitutions(string value) {
if (string.IsNullOrEmpty(value))
return 0;
int result = 0;
for (int i = 0; i < value.Length / 2; ++i)
if (value[i] != value[value.Length - 1 - i])
result += 1;
return result;
}
// Let's test all substrings of size Length, Length - 1, ... , 2, 1
// until we find substring with required tolerance
private static string BestPalindromeSubstitutions(string value, int tolerance) {
for (int size = value.Length; size >= 1; --size)
for (int start = 0; start <= value.Length - size; ++start)
if (PalindromeSubstitutions(value.Substring(start, size)) <= tolerance)
return value.Substring(start, size);
return "";
}
private static string SubstituteToPalindrome(string value) {
if (string.IsNullOrEmpty(value))
return value;
StringBuilder sb = new StringBuilder(value);
for (int i = 0; i < value.Length / 2; ++i)
sb[value.Length - 1 - i] = sb[i];
return sb.ToString();
}
Test:
string input = "73943";
string best = BestPalindromeSubstitutions(input, 1);
string report =
string.Format("Best palindrome {0} -> {1}", best, SubstituteToPalindrome(best));
Output
Best palindrome 3943 -> 3993
The problem is a quite simple example of greedy algorithm. let's first count how many permutations are required (at minimum) to transform the number into palindrome.
int req = 0;
for(int i = 0; i <= (s.length()-1)/2; i++){
if (s[i] != s[s.length()-1-i] && i != s.length()-1-i) req++;
}
Now once it is done, let's go through digits from left to right once again: i goes through 0 to (s.length()-1)/2 inclusive. Consider the following cases ( here i is not the middle letter, that case we consider separately) :
s[i] == s[s.length()-i-1], it wasn't counted in req, so if k >= req + 2 and s[i] != '9', we change both letters to '9', and reduce k by 2, req remains unchanged. But note that we guaranteed that there are enough operations left to make sure that number can be turned into palindrome (if it was initially possible)
s[i] != s[s.length()-i-1] - now if k == req or one of the letters is '9', then do the following: s[i]=s[s.length()-i-1]=max({s[i], s[s.length()-i-1]}). Reduce both k and req by 1.
Now if k > req and both letters are not '9', we change them both to 9. k -= 2, req -= 1.
Now if i = s.length()-i-1 and k > 0, change this letter s[i] to '9'.
The result u get at the end is what u are looking for.
Total complexity is O(n).
I am trying to work through a scenario I haven't seen before and am struggling to come up with an algorithm to implement this properly. Part of my problem is a hazy recollection of the proper terminology. I believe what I am needing is a variation of the standard "combination" problem, but I could well be off there.
The Scenario
Given an example string "100" (let's call it x), produce all combinations of x that swap out one of those 0 (zero) characters for a o (lower-case o). So, for the simple example of "100", I would expect this output:
"100"
"10o"
"1o0"
"1oo"
This would need to support varying length strings with varying numbers of 0 characters, but assume there would never be more than 5 instances of 0.
I have this very simple algorithm that works for my sample of "100" but falls apart for anything longer/more complicated:
public IEnumerable<string> Combinations(string input)
{
char[] buffer = new char[input.Length];
for(int i = 0; i != buffer.Length; ++i)
{
buffer[i] = input[i];
}
//return the original input
yield return new string(buffer);
//look for 0's and replace them
for(int i = 0; i != buffer.Length; ++i)
{
if (input[i] == '0')
{
buffer[i] = 'o';
yield return new string(buffer);
buffer[i] = '0';
}
}
//handle the replace-all scenario
yield return input.Replace("0", "o");
}
I have a nagging feeling that recursion could be my friend here, but I am struggling to figure out how to incorporate the conditional logic I need here.
Your guess was correct; recursion is your friend for this challenge. Here is a simple solution:
public static IEnumerable<string> Combinations(string input)
{
int firstZero = input.IndexOf('0'); // Get index of first '0'
if (firstZero == -1) // Base case: no further combinations
return new string[] { input };
string prefix = input.Substring(0, firstZero); // Substring preceding '0'
string suffix = input.Substring(firstZero + 1); // Substring succeeding '0'
// e.g. Suppose input was "fr0d00"
// Prefix is "fr"; suffix is "d00"
// Recursion: Generate all combinations of suffix
// e.g. "d00", "d0o", "do0", "doo"
var recursiveCombinations = Combinations(suffix);
// Return sequence in which each string is a concatenation of the
// prefix, either '0' or 'o', and one of the recursively-found suffixes
return
from chr in "0o" // char sequence equivalent to: new [] { '0', 'o' }
from recSuffix in recursiveCombinations
select prefix + chr + recSuffix;
}
This works for me:
public IEnumerable<string> Combinations(string input)
{
var head = input[0] == '0' //Do I have a `0`?
? new [] { "0", "o" } //If so output both `"0"` & `"o"`
: new [] { input[0].ToString() }; //Otherwise output the current character
var tails = input.Length > 1 //Is there any more string?
? Combinations(input.Substring(1)) //Yes, recursively compute
: new[] { "" }; //Otherwise, output empty string
//Now, join it up and return
return
from h in head
from t in tails
select h + t;
}
You don't need recursion here, you can enumerate your patterns and treat them as binary numbers. For example, if you have three zeros in your string, you get:
0 000 ....0..0....0...
1 001 ....0..0....o...
2 010 ....0..o....0...
3 011 ....0..o....o...
4 100 ....o..0....0...
5 101 ....o..0....o...
6 110 ....o..o....0...
7 111 ....o..o....o...
You can implement that with bitwise operators or by treating the chars that you want to replace like an odometer.
Below is an implementation in C. I'm not familiar with C# and from the other answers I see that C# already has suitable standard classes to implement what you want. (Although I'm surprised that so many peolpe propose recursion here.)
So this is more an explanation or illustration of my comment to the question than an implementation advice for your problem.
int binrep(char str[])
{
int zero[40]; // indices of zeros
int nzero = 0; // number of zeros in string
int ncombo = 1; // number of result strings
int i, j;
for (i = 0; str[i]; i++) {
if (str[i] == '0') {
zero[nzero++] = i;
ncombo <<= 1;
}
}
for (i = 0; i < ncombo; i++) {
for (j = 0; j < nzero; j++) {
str[zero[j]] = ((i >> j) & 1) ? 'o' : '0';
}
printf("%s\n", str); // should yield here
}
return ncombo;
}
Here's a solution using recursion, and your buffer array:
private static void Main(string[] args)
{
var a = Combinations("100");
var b = Combinations("10000");
}
public static IEnumerable<string> Combinations(string input)
{
var combinations = new List<string>();
combinations.Add(input);
for (int i = 0; i < input.Length; i++)
{
char[] buffer= input.ToArray();
if (buffer[i] == '0')
{
buffer[i] = 'o';
combinations.Add(new string(buffer));
combinations = combinations.Concat(Combinations(new string(buffer))).ToList();
}
}
return combinations.Distinct();
}
The method adds the raw input as the first result. After that, we replace in a loop the 0s we see as a o and call our method back with that new input, which will cover the case of multiple 0s.
Finally, we end up with a couple duplicates, so we use Distinct.
I know that the earlier answers are better. But I don't want my code to go to waste. :)
My approach for this combinatorics problem would be to take advantage of how binary numbers work. My algorithm would be as follows:
List<string> ZeroCombiner(string str)
{
// Get number of zeros.
var n = str.Count(c => c == '0');
var limit = (int)Math.Pow(2, n);
// Create strings of '0' and 'o' based on binary numbers from 0 to 2^n.
var binaryStrings = new List<string>();
for (int i = 0; i < limit; ++i )
{
binaryStrings.Add(Binary(i, n + 1));
}
// Replace each zero with respect to each binary string.
var result = new List<string>();
foreach (var binaryString in binaryStrings)
{
var zeroCounter = 0;
var combinedString = string.Empty;
for (int i = 0; i < str.Length; ++i )
{
if (str[i] == '0')
{
combinedString += binaryString[zeroCounter];
++zeroCounter;
}
else
combinedString += str[i];
}
result.Add(combinedString);
}
return result;
}
string Binary(int i, int n)
{
string result = string.Empty;
while (n != 0)
{
result = result + (i % 2 == 0 ? '0' : 'o');
i = i / 2;
--n;
}
return result;
}
I have to send a decimal in string format. The maximum length of the string is 15. How can I do this by rounding to the best fit?
eg:
1111111111111119 = "111111111111112"
11111111111111.111 = "11111111111111"
1.11111111111119 = "1.1111111111112"
Thanks
I found a quite inelegant way of doing this, but it handles your test cases and another edge case I found:
static string ToStringOfMaxLength(decimal x) {
const int maxLength = 15;
var str = x.ToString(System.Globalization.CultureInfo.InvariantCulture);
if(str.Length <= maxLength)
return str;
if(str[maxLength] == '.')
return str.Substring(0, maxLength);
if(str[maxLength - 1] == '.')
return str.Substring(0, maxLength - 1);
var digitsToDisplayExceptLast = str.Substring(0, maxLength - 1);
var lastDigitToDisplay = CharToInt(str[maxLength - 1]);
var firstDigitNotDisplayed = CharToInt(str[maxLength]);
if(firstDigitNotDisplayed >= 5)
lastDigitToDisplay++;
return digitsToDisplayExceptLast + lastDigitToDisplay;
}
static int CharToInt(char c) {
return (int)(c - 48);
}
This function should do exactly what you needed (tested on your example values):
string ValueString15(decimal value)
{
while (value >= 1000000000000000M) // for your first example case
value /= 10;
int dotIndex = value.ToString(CultureInfo.InvariantCulture).IndexOf('.');
value = (dotIndex >= 14) ? Math.Round(value) : Math.Round(value, 14 - dotIndex);
return value.ToString(CultureInfo.InvariantCulture);
}
If you need to deal with negative values (i.e. value < 0), you should also add:
|| value <= -100000000000000M
to the while condition.
if you want to cut the string to 15 characters only,
decimal sample = 123456789123456789;
string result = sample.ToString().Substring(0, 15); // this cuts it to 15 characters
**returns 123456789123456**
if you want to round of from the 15 character.
decimal sample = 123456789123456789;
double result2 = Math.Round(sample.ToString().Substring(0, 16));
**returns 123456789123457**