I have searched allot on google without any results I am looking for
I would like to get a numeric value from any string in C#
Ex.
var myString = "Oompa Loompa";
var numericoutput = convertStringToNumericValue(myString);
output/value of numericoutput is something like 612734818
so when I put in another string let say "C4rd1ff InTernaT!onal is # gr3at place#"
the int output will be something like 73572753.
The Values must stay constant, for example so if I enter the same text again of "Oompa Loompa" then I get 612734818 again.
I thought maybe in the way of using Font Family to get the char index of each character, but I don't know where to start with this.
The reason for this is so that I can use this number to generate an index out of a string with other data in it, and with the same input string, get that same index again to recall the final output string for validation.
Any help or point in the right direction would be greatly appreciated
Thanks to Tim I ended up doing the following:
var InputString = "My Test String ~!##$%^&*()_+{}:<>?|";
byte[] asciiBytes = Encoding.ASCII.GetBytes(InputString);
int Multiplier = 1;
int sum = 0;
foreach (byte b in asciiBytes)
{
sum += ((int)b) * Multiplier;
Multiplier++;
}
Obviously this will not work for 1000's of characters, but it is good enough for short words or sentences
int.MaxValue = 2 147 483 647
As an alternative to converting the string to it's bytes, and if a hash won't meet the requirements, here are a couple of shorter ways to accomplish getting a numeric value for a string:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
int sum = 0;
foreach (char c in inputString)
{
sum += ((int)c) * ++multiplier;
}
The above code outputs 46026, as expected. The only difference is it loops through the characters in the string and gets their ASCII value, and uses the prefix ++ operator (Note that multiplier is set to 0 in this case - which is also the default for int).
Taking a cue from Damith's comment above, you could do the same with LINQ. Simply replace the foreach above with:
sum = inputString.Sum(c => c * ++multiplier);
Finally, if you think you'll need a number larger than Int32.MaxValue, you can use an Int64 (long), like this:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
long largeSum = 0;
foreach (char c in inputString)
{
largeSum += ((int)c) * ++multiplier;
}
Related
I have this code which I think I found somewhere on the internet some years ago and it doesn't quite work.
The purpose is to take any string and from that create a string that is lexicographically sorted by a large number - because then inverse (descending) ordering can be achieved by subtracting the number from another even larger number.
private static BigInteger maxSort = new BigInteger(Encoding.Unicode.GetBytes("5335522543087813528200259404529154678271640415603227881439560533607051111046319775598721171814499900"));
public static string GetSortString(string str, bool descending)
{
var sortNumber = new BigInteger(Encoding.Unicode.GetBytes(str));
if (descending)
{
sortNumber = maxSort - sortNumber;
}
return "$SORT!" + sortNumber.ToString().PadLeft(100, '0') + ":" + str;
}
The reason I need this is because I want to use it to insert as RowKey in Azure Table Storage which is the only way to sort in Table Storage. I need to sort any text, any number and any date, both ascending and descending.
Can anyone see the issue with the code or have any code that serves the same purpose?
The question is tagged with C# but of course this is not a question of syntax so if you have the answer in any other code that would be fine too.
Example
I want to convert any string to a number which is lexicographically sorted correctly - because if it's a number, then I can invert it and sort descending.
So for example, if I can convert:
ABBA to 1234
Beatles to 3131
ZZ Top to 9584
Then those numbers would sort them correctly ... and, if I subtract them from a large number, I would be able to invert the sort order:
10000 - 1234 = 8766
10000 - 3131 = 6869
10000 - 9584 = 0416
Of course, to support longer text input, I need to subtract them from a very large number, which is why I use the very large BigInteger.
Current output from this code
ABBA: $SORT!0000000000000000000000018296156958359617:ABBA
Beatles: $SORT!0000000009111360792640460912278748069954:Beatles
ZZ TOP: $SORT!0000000000000096715522885596192519618650:ZZ TOP
As you can see, the longest text gets the highest number. I have also tried to add padding immediately on the input str, but that didnt help either.
Answer
The accepted answer worked. For descending sort order, the "BigInteger" trick from above could be used.
There is some limitation as to how long the sortable string can be.
Here is the final code:
private static BigInteger maxSort = new BigInteger(Encoding.Unicode.GetBytes("5335522543087813528200259404529154678271640415603227881439560533607051111046319775598721171814499900"));
public static string GetSortString(string str, bool descending)
{
BigInteger result = 0;
int maxLength = 42;
foreach (var c in str.ToCharArray())
{
result = result * 256 + c;
}
for (int i = str.Length; i < maxLength; i++)
{
result = result * 256;
}
if (descending)
{
result = maxSort - result;
}
return "$SORT!" + result;
}
If you were looking for a way to give a a value to any string so that you could sort them accordingly to the number and get the same result as above you can't. The reason is that strings don't have any length limit. Because you can always add a char to a string and thereby get a larger number even through it should have a lower lexicographical value.
If they have a length limit you can do something like this
pseudo code
bignum res = 0;
maxLength = 42;
for (char c : string)
res = res * 256 + c
for (int i = string.length; i < maxLength; i++)
res = res *256
If you want to optimize a bit, the last loop could be a lookup table. If your only using a-z, the times 256 could reduced to 26 or 32.
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;
}
So what I'm trying to do, is take a job number, which looks like this xxx123432, and count the digits in the entry, but not the letters. I want to then assign the number of numbers to a variable, and use that variable to provide a check against the job numbers to determine if they are in a valid format.
I've already figured out how to perform the check, but I have no clue how to go about counting the numbers in the job number.
Thanks so much for your help.
Using LINQ :
var count = jobId.Count(x => Char.IsDigit(x));
or
var count = jobId.Count(Char.IsDigit);
int x = "xxx123432".Count(c => Char.IsNumber(c)); // 6
or
int x = "xxx123432".Count(c => Char.IsDigit(c)); // 6
The difference between these two methods see at Char.IsDigit and Char.IsNumber.
Something like this maybe?
string jobId = "xxx123432";
int digitsCount = 0;
foreach(char c in jobId)
{
if(Char.IsDigit(c))
digitsCount++;
}
And you could use LINQ, like this:
string jobId = "xxx123432";
int digitsCount = jobId.Count(c => char.IsDigit(c));
string str = "t12X234";
var reversed = str.Reverse().ToArray();
int digits = 0;
while (digits < str.Length &&
Char.IsDigit(reversed[digits])) digits++;
int num = Convert.ToInt32(str.Substring(str.Length - digits));
This gives num 234 as output if that is what you need.
The other linq/lambda variants just count characters which I think is not completely correct if you have a string like "B2B_MESSAGE_12344", because it would count the 2 in B2B.
But I'm not sure if I understood correctly what number of numbers means. Is it the count of numbers (other answers) or the number that numbers form (this answer).
I found the following C++ code (comments added myself):
// frame_name is a char array
// prefix is std::string
// k is a for loop counter
// frames is a std::vector string
sprintf(frameName, "%s_%0*s.bmp", prefix.c_str(), k, frames[k].c_str());
I then try to translate it to C#
// prefix is string
// k is a for loop counter
// frames is List<string>
string frameName = string.Format("{0}_(what goes in here?).bmp", prefix, k, frames[k]);
Basically, what would be the C# equivalent of the C++ format string "%s_%0*s.bmp"?
Edit, #Mark Byers:
I've tried your code and made a little test program:
static void Main(string[] args)
{
List<string> frames = new List<string>();
frames.Add("blah");
frames.Add("cool");
frames.Add("fsdt");
string prefix = "prefix";
int n = 2;
int k = 0;
string frameName = string.Format("{0}_{1}.bmp", prefix, frames[k].PadLeft(n, '0'));
Console.WriteLine(frameName); // outputs prefix_blah.bmp, should output prefix_00blah.bmp
Console.ReadLine();
}
It's not padding for some reason.
Edit: Got it working; won't pad if n = 2.
To pad a string with zeros use string.PadLeft:
frames[k].PadLeft(n, '0')
In combination with string.Format:
int n = 15; // Get this from somewhere.
string frameName = string.Format("{0}_{1}.bmp",
prefix,
frames[k].PadLeft(n, '0'));
Note that I have changed k to n, as I assume that this is a bug in the original code. I think it's unlikely that the length of the padding on the file name was meant to increase by one in each iteration of the loop.
For formatting details like the 0* in %0*s, I'd do it this way:
string.Format("{0}_{1}.bmp", prefix, frames[k].PadLeft(k,'0'));
If I have it right, it will take frames[k], and left-pad it with 0's.
e.g.:
k=10;
frames[k] = "Hello";
frames[k].PadLeft(k,'0') ==> "00000Hello";
Is that what you're after?
And is there an elegant linqy way to do it?
What I want to do is create string of given length with made of up multiples of another string up to that length
So for length - 9 and input string "xxx" I get "xxxxxxxxx" (ie length 9)
for a non integral multiple then I'd like to truncate the line.
I can do this using loops and a StringBuilder easily but I'm looking to see if the language can express this idea easily.
(FYI I'm making easter maths homework for my son)
No, nothing simple and elegant - you have to basically code this yourself.
You can construct a string with a number of repeated characters, but ot repeated strings,
i.e.
string s = new string("#", 6); // s = "######"
To do this with strings, you would need a loop to concatenate them, and the easest would then be to use substring to truncate to the desired final length - along the lines of:
string FillString(string text, int count)
{
StringBuilder s = new StringBuilder();
for(int i = 0; i <= count / text.Length; i++)
s.Add(text);
return(s.ToString().Substring(count));
}
A possible solution using Enumerable.Repeat.
const int TargetLength = 10;
string pattern = "xxx";
int repeatCount = TargetLength / pattern.Length + 1;
string result = String.Concat(Enumerable.Repeat(pattern, repeatCount).ToArray());
result = result.Substring(0, TargetLength);
Console.WriteLine(result);
Console.WriteLine(result.Length);
My Linqy (;)) solution would be to create an extension method. Linq is language integrated query, so why the abuse? Im pretty sure it's possible with the select statement of linq since you can create new (anonymous) objects, but why...?