Function for calculating maximum value of limited width number - c#

For example to calculate the maximum value of a 3 character long base26 encoding the expression would be (((26 * 26) + 26) * 26) + 26), but if I simply wanted to calculate the amount of permutations of the same length with a zero-based numeral system then I could use the Pow method in the Math class like Math.Pow(26, 3). Is there any method in the Math class to do the prior?
For anyone's interest, here is my encoding method for Base26:
public static string ToBase26(uint u)
{
char[] cx = new char[7];
int index = 0;
while (u > 0)
{
u--;
cx[index++] = (char)(65 + (u % 26));
u /= 26;
}
Array.Resize(ref cx, index);
Array.Reverse(cx);
return new string(cx);
}

Using letter combinations of up to n letters to label something, like columns in a spreadsheet table, will indeed give
26+26^2+26+3+...+26^n
different labels. The compact formula is the geometric sum
26*(26^n-1)/25
Each block of exactly k letters can be interpreted as the numbers 0 to 26^k-1 in base-26 in a zero-padded format. Using the letters 0,1,2,3, the 3 letter block would look like
000, 001, 002, 003, 010, ..., 033, 100, ..., 333
the corresponding encoding using letters A,B,C,D would be
AAA, AAB, AAC, AAD, ABA, ..., ADD, BAA, ..., DDD

Related

Shift bits of an integer only if the number of bits of its binary presentation is greater then given value

I need to shift the bits of an integer to the right only if the number of bits is greater then a certain number. For the example Lets take 10.
If the integer is 818 the then binary representation of the integer is 1100110010, In that case i do nothing.
If the Integer is 1842 the binary representation of the integer is 11100110010 which is greater then 10 by one, So i need to shift one bit to the right(Or setting bit at index 10 to 0 which gives the same result as far as i know, Maybe im wrong).
What i did until now is make an integer array of ones and zeros represent the int, But i`m sure there is more elegant way of doing this
int y = 818;
string s = Convert.ToString(y, 2);
int[] bits = s.PadLeft(8, '0')
.Select(c => int.Parse(c.ToString()))
.ToArray();
if (bits.Length > 10)
{
for (int i = 10; i < bits.Length; i++)
{
bits[i] = 0;
}
}
I also tried to do this:
if(bits.Length > 10){ y = y >> (bits.Length - 10)}
but for some reason i got 945 (1110110001) when the input was 1891 (11101100011)
There's no need to do this with strings. 2 to the power of 10 has 11 binary digits, so
if (y >= Math.Pow(2, 10))
{
y = y >> 1;
}
seems to do what you want.

How to convert a base 10-number to 3-base in net (Special case)

I'm looking for a routine in C# that gives me the following output when putting in numbers:
0 - A
1 - B
2 - C
3 - AA
4 - AB
5 - AC
6 - BA
7 - BB
8 - BC
9 - CA
10 - CB
11 - CC
12 - AAA
13 - etc
I'm using letters, so that it's not so confusing with zero's.
I've seen other routines, but they will give me BA for the value of 3 and not AA.
Note: The other routines I found was Quickest way to convert a base 10 number to any base in .NET? and http://www.drdobbs.com/architecture-and-design/convert-from-long-to-any-number-base-in/228701167, but as I said, they would give me not exactly what I was looking for.
Converting between systems is basic programming task and logic doesn't differ from other systems (such as hexadecimal or binary). Please, find below code:
//here you choose what number should be used to convert, you wanted 3, so I assigned this value here
int systemNumber = 3;
//pick number to convert (you can feed text box value here)
int numberToParse = 5;
// Note below
numberToParse++;
string convertedNumber = "";
List<char> letters = new List<char>{ 'A', 'B', 'C' };
//basic algorithm for converting numbers between systems
while(numberToParse > 0)
{
// Note below
numberToParse--;
convertedNumber = letters[numberToParse % systemNumber] + convertedNumber;
//append corresponding letter to our "number"
numberToParse = (int)Math.Floor((decimal)numberToParse / systemNumber);
}
//show converted number
MessageBox.Show(convertedNumber);
NOTE: I didn't read carefully at first and got it wrong. I added to previous solution two lines marked with "Note below": incrementation and decrementation of parsed number. Decrementation enables A (which is zero, thus omitted at the beginning of numbers) to be treated as relevent leading digit. But this way, numbers that can be converted are shifted and begin with 1. To compensate that, we need to increment our number at the beginning.
Additionaly, if you want to use other systems like that, you have to expand list with letter. Now we have A, B and C, because you wanted system based on 3. In fact, you can always use full alphabet:
List<char> letters = new List<char> {'A','B','C', 'D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
and only change systemNumber.
Based on code from https://stackoverflow.com/a/182924 the following should work:
private string GetWeirdBase3Value(int input)
{
int dividend = input+1;
string output = String.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 3;
output = Convert.ToChar('A' + modulo).ToString() + output;
dividend = (int)((dividend - modulo) / 3);
}
return output;
}
The code should hopefully be pretty easy to read. It essentially iteratively calculates character by character until the dividend is reduced to 0.

How to flip bits in C#?

I have a binary number in the form of a string as
string input = "10110101101";
Now I need to flip (0 to 1 and 1 to 0) the first 3 bits of it.
The resultant output will be 01010101101
How to do so in C#?
This works:
string input = "10110101101";
string output =
new string(
input
.Take(3)
.Select(c => c == '0' ? '1' : '0')
.Concat(input.Skip(3))
.ToArray());
It gives the result:
01010101101
Another alternative is to do this:
string input = "10110101101";
string flips = "11100000000";
int value = Convert.ToInt32(input, 2) ^ Convert.ToInt32(flips, 2);
string output = Convert.ToString(value, 2).PadLeft(input.Length, '0');
Make StringBuilder out of your string, flip the initial three characters, and convert StringBuilder back to string:
var sb = new StringBuilder(input);
Debug.Assert(sb.Length >= 3);
for (int i = 0 ; i != 3 ; i++) {
sb[i] = sb[i] == '0' ? '1' : '0';
}
var res = sb.ToString();
There are various "smart" ways of flipping the characters without conditional, but given that the number is in a string making the flip smarter wouldn't buy you much CPU cycles.
Demo.
An alternate way using Convert.ToInt32, Convert.ToString (which otherwise unknown and unused), and bitwise-XOR
string input = "10110101101";
int flipNo = 3;
int output = Convert.ToInt32(input, 2);
for (int i = input.Length - 1; i >= input.Length - flipNo; --i)
output ^= 1 << i;
Simply use the output, or if you want to display the output in string, you could do:
string display = Convert.ToString(output, 2).PadLeft(input.Length, '0');
Suppose you are given an array a of size N. The elements of the array are a[0], a[1], ... a[N - 1], where each a is either 0 or 1. You can perform one transformation on the array: choose any two integers L, and R, and flip all the elements between (and including) the Lth and Rth bits. In other words, L and R represent the left-most and the right-most index demarcating the boundaries of the segment whose bits you will decided to flip. ('Flipping' a bit means, that a 0 is transformed to a 1 and a 1 is transformed to a 0.)
What is the maximum number of '1'-bits (indicated by S) which you can obtain in the final bit-string?
Input Format:
The first line has a single integerN
The next N lines contains the N elements in the array, a[0], a[1], ... a[N - 1], one per line.
For instance consider
1 ≤ N ≤ 100,000.
d can be either 0 or 1. It cannot be any other integer.
0 ≤ L ≤ R < N
Sample Input:
810010010
Sample Output:
6
Explanation:
We can get a maximum of 6 ones in the given binary array by performing either of the following operations:
Flip [1, 5] ⇒ 1 1 1 0 1 1 1 0
or
Flip [1, 7] ⇒ 1 1 1 0 1 1 0 1
Solution:
The bits array will only contain 0 and 1. So we can view 0 as -1, then the task is to find the
minimum sum of subArray in bits, which is the subArray that has the largest value of
(number of 0s- number of 1s).
We can use the same method as find maximum sum subArray to find minimum sum subArray. Before that,
we need to traverse bits first to get original number of 1s. Suppose the minimum sum is minRes and
original number of 1s is currentOne. Then minRes should be a negative number, so return currentOne-minRes.
Edge case:
All edge cases can be handled using the above method. If all elements are 0, then we add all -1 together.
If all elements are 1, then the minRes should be 0, which means we do not do flip any bit.
Time: O(n) Space: O(1)
using System;
using System.Linq;
public class Test
{
public static int FlippingBits(int[] bits){
int currentOne = 0; //original number of 1s in bits
foreach(int i in bits){
if(i==1)
currentOne++;
}
int minRes = MinSubArray(bits); //minRes is negative number
return currentOne-minRes;
}
//find the min sum of subArray in bits
private static int MinSubArray(int[] bits){
int minRes = 0, minHere=0;
foreach(int i in bits){
if(i==0)
minHere-=1;
else
minHere+=1;
minHere = Math.Min(minHere,0); //keep minHere<=0
minRes = Math.Min(minHere, minRes);
}
return minRes; //-minRes is the number of 1 can be added to the array after flipping
}
public static void Main()
{
int num = int.Parse(Console.ReadLine());
for(int i=0;i<num;i++){
string[] input = Console.ReadLine().Split();
int[] bits = input.Select(y=>int.Parse(y)).ToArray();
Console.WriteLine(FlippingBits(bits));
}
}
}
The solution is quite simple; just XOR the values with 1 (0 works too).
Steps:
For the first x characters, XOR with 1 and get the return value (simple for loop).
Replace the old string with the new one.

"Substring" a Numeric Value

In C#, what is the best way to "substring" (for lack of a better word) a long value.
I need to calculate a sum of account numbers for a trailer record but only need the 16 least significant characters.
I am able to this by converting the value to string but wondered if there is a better way in which it can be done.
long number = 1234567890123456789L;
const long _MAX_LENGTH = 9999999999999999L;
if (number > _MAX_LENGTH)
{
string strNumber = number.ToString();
number = Convert.ToInt64(strNumber.Substring(strNumber.Length - 16));
}
This will return the value 4567890123456789.
You could do:
long number = 1234567890123456789L;
long countSignificant = 16;
long leastSignificant = number % (long) Math.Pow(10, countSignificant);
How does this work? Well, if you divide by 10, you drop off the last digit, right? And the remainder will be that last digit? The same goes for 100, 1000 and Math.Pow(1, n).
Let's just look at the least significant digit, because we can do this in our head:
1234 divided by 10 is 123 remainder 4
In c#, that would be:
1234 / 10 == 123;
1234 % 10 == 4;
So, the next step is to figure out how to get the last n significant digits. It turns out, that that is the same as dividing by 10 to the power of n. Since c# doesn't have an exponent operator (like ** in python), we use a library function:
Math.Pow(10, 4) == 1000.0; // oops: a float!
We need to cast that back to a long:
(long) Math.Pow(10, 4) == 1000;
I think now you have all the pieces to create a nice function of your own ;)
You could use modulo (the % operator in C#). For example:
123456 % 100000 = 23456
or
123456 % 1000 = 456
As a quick guide I keep remembering that you get as many digits as there are zeros in the divisor. Or, vice versa, the divisor needs as many zeros as you want to keep digits.
So in your case you'd need:
long number = 1234567890123456789L;
long divisor = 10000000000000000L;
long result = number % divisor;
Complete Code, use modulo operator:
long number = 1234567890123456789L;
const long _MAX_LENGTH = 9999999999999999L;
number = number % (_MAX_LENGTH + 1);
Console.WriteLine (number);
Live test: http://ideone.com/pKB6w
Until you are enlightened with modulo approach, you can opt for this one instead for the meantime:
long number = 1234567890123456789L;
const long _MAX_LENGTH = 9999999999999999L;
if (number > _MAX_LENGTH) {
long minus = number / (_MAX_LENGTH + 1) * (_MAX_LENGTH + 1);
number = number - minus;
}
Console.WriteLine(number);
Live test: http://ideone.com/oAkcy
Note:
Strongly recommended, use modulo approach, don't use subtraction. Modulo approach is the best, no corner case, i.e. no need to use if statement.

Fastest way to sum digits in a number

Given a large number, e.g. 9223372036854775807 (Int64.MaxValue), what is the quickest way to sum the digits?
Currently I am ToStringing and reparsing each char into an int:
num.ToString().Sum(c => int.Parse(new String(new char[] { c })));
Which is surely horrifically inefficent. Any suggestions?
And finally, how would you make this work with BigInteger?
Thanks
Well, another option is:
int sum = 0;
while (value != 0)
{
int remainder;
value = Math.DivRem(value, 10, out remainder);
sum += remainder;
}
BigInteger has a DivRem method as well, so you could use the same approach.
Note that I've seen DivRem not be as fast as doing the same arithmetic "manually", so if you're really interested in speed, you might want to consider that.
Also consider a lookup table with (say) 1000 elements precomputed with the sums:
int sum = 0;
while (value != 0)
{
int remainder;
value = Math.DivRem(value, 1000, out remainder);
sum += lookupTable[remainder];
}
That would mean fewer iterations, but each iteration has an added array access...
Nobody has discussed the BigInteger version. For that I'd look at 101, 102, 104, 108 and so on until you find the last 102n that is less than your value. Take your number div and mod 102n to come up with 2 smaller values. Wash, rinse, and repeat recursively. (You should keep your iterated squares of 10 in an array, and in the recursive part pass along the information about the next power to use.)
With a BigInteger with k digits, dividing by 10 is O(k). Therefore finding the sum of the digits with the naive algorithm is O(k2).
I don't know what C# uses internally, but the non-naive algorithms out there for multiplying or dividing a k-bit by a k-bit integer all work in time O(k1.6) or better (most are much, much better, but have an overhead that makes them worse for "small big integers"). In that case preparing your initial list of powers and splitting once takes times O(k1.6). This gives you 2 problems of size O((k/2)1.6) = 2-0.6O(k1.6). At the next level you have 4 problems of size O((k/4)1.6) for another 2-1.2O(k1.6) work. Add up all of the terms and the powers of 2 turn into a geometric series converging to a constant, so the total work is O(k1.6).
This is a definite win, and the win will be very, very evident if you're working with numbers in the many thousands of digits.
Yes, it's probably somewhat inefficient. I'd probably just repeatedly divide by 10, adding together the remainders each time.
The first rule of performance optimization: Don't divide when you can multiply instead. The following function will take four digit numbers 0-9999 and do what you ask. The intermediate calculations are larger than 16 bits. We multiple the number by 1/10000 and take the result as a Q16 fixed point number. Digits are then extracted by multiplication by 10 and taking the integer part.
#define TEN_OVER_10000 ((1<<25)/1000 +1) // .001 Q25
int sum_digits(unsigned int n)
{
int c;
int sum = 0;
n = (n * TEN_OVER_10000)>>9; // n*10/10000 Q16
for (c=0;c<4;c++)
{
printf("Digit: %d\n", n>>16);
sum += n>>16;
n = (n & 0xffff) * 10; // next digit
}
return sum;
}
This can be extended to larger sizes but its tricky. You need to ensure that the rounding in the fixed point calculation always works correctly. I also did 4 digit numbers so the intermediate result of the fixed point multiply would not overflow.
Int64 BigNumber = 9223372036854775807;
String BigNumberStr = BigNumber.ToString();
int Sum = 0;
foreach (Char c in BigNumberStr)
Sum += (byte)c;
// 48 is ascii value of zero
// remove in one step rather than in the loop
Sum -= 48 * BigNumberStr.Length;
Instead of int.parse, why not subtract '0' from each digit to get the actual value.
Remember, '9' - '0' = 9, so you should be able to do this in order k (length of the number). The subtraction is just one operation, so that should not slow things down.

Categories