prefer high index number than lower one in an array - c#

Assuming that I have these two sorted arrays with 5 cells:
The numbers in the array are between 2 and 14 ( 2 and 14 included and they are integers )
Now, I need to give a rank to each array from [0,100] when the lowest array will be:
[2,2,2,2,2] and the highest will be [14,14,14,14,14]
Now the thing is: the index is important so for example if we take a look at this these arrays:
1) [2,2,2,2,10]
2) [8,8,8,8,9]
So the 1st one is better than the the 2nd and will get an higher score.
And if there's a tie in the index ( from right to left ) for example:
1) [3,4,5,10,13]
2) [3,4,7,10,13]
So index numbers: 3 and 4 are the same, but since 7 is higher than 5. so in that case the 2nd array will have an higher score.
I'm struggling with the math, I mean I want to do it efficient, now I can do something like:
2^array[i] but it won't be efficient, so the main thing I managed to do is
double rank = 0;
for (int i = 0; i < 5; i++)
{
rank += (double)array[i] / 14 + i;
}
because if array[i] can be between 2 and 14, so 1/7 <= array[i]/14 <= 1
so I thought that if I'll add + i each iteration, the next iteration will be greater than all the previous ones, but it's mistake.
I'll be glad for some help in here.

You are essentially describing a base-13 number. Each "digit" (array position) represents one of 13 distinct, ordered values.
You can calculate a ranking by converting the array to a 5 digit, base 13 value:
Subtract 2 from each array element's value to normalize the element value to the range 0..12.
Give each array element a score = (normalized element value) * (13 raised to the array index power). 1)
Add up the scores.
1) Or raised to Array.Length - array index, depending on which side of the array should be the least significant.

Related

Finding All Combinations of a Multidimention Array with a Max Value in C#

Let's say I have an int[8,6] array which can have the maximum value of 255 per cell and I want to find all combinations of this array.
What is the most efficient way to accomplish this?
For array size N (1D array for simpliciry, 2D case works similar) and maximum value M there are M^N possible combinations. Every combination corresponds to value in range 0..M^N-1, so we can just walk throug this range and get combination for every value. Of course, it is possible for reasonable small values of N and M.
Python-like pseudocode:
int A[N]
P = M**N #math.intpower(M, N)
for i in range(P):
t = i
for k in range(N): #number of cells, number of digits in counter value
A[k] = t % M # value in k-th cells of result for variant number i
t = t // M #integer division
Note that for base M=256 you perhaps don't need to use division - needed values are just bytes of multibyte representation of big number in base 256

Generate all numbers of length M (1<M<10) with elements from {1,2,...N} with N(1<N<20)

thank you for taking the time to read this.
I'm working on a larger project that needs a function that generates all numbers based on the rules described in the title.
If inputs are M=3 and N=5 Outputs should be: 111,112,113,114,115,121....555
For inputs M=4 and N=2 Outputs should be: 1111,1112,1121...2222
I've been trying to make a function that does this for quite some time but i haven't succeeded. So I'm asking for help. I'm required to write it in C, but if you know how to fix it in C++ or C# I'll probably be able to translate it into C.
I don't have any code to show because thus far I've mostly tried brute-forcing it but it doesn't seem to work
Thank you for the help in advance!
If I understand the question, I would do it with regular expressions. This is all written with C in mind.
First build a regex with all the allowed digits. Posix provides a regex library (https://www.educative.io/edpresso/how-to-write-regular-expressions-in-c appears to be a good intro), so you only have to compose the string that will be parsed by regcomp() by iterating through the numbers from 1 to N. An appropriate regular expression would be, for N=20, ^(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20)+$. This will match strings composed entirely of any of those characters. (Since 0 should match only after 1 or 2 in this case, enumerating the options is simpler than trying to shorten the regex).
Then, iterate over the numbers starting with 10 ^ M and ending when you reach 10^(M+1). Write each number out as a string and see if it matches the regular expression - if it does, you have one of your results.
The problem can be boiled down to starting an M-digit, base-N number at its lowest value for the initial iteration, and incrementing it for subsequent iterations.
The M-digit number can be represented as an array (indexed from 0 to M-1) with one element per digit. One end of the array will hold the lowest order ("rightmost") digit and the other end of the array will hold the highest order ("leftmost") digit. It doesn't really matter which end is chosen to hold the highest order digit, so let's choose element 0 to hold the highest order digit. For generality, let's use digit values from 0 to N-1. (It doesn't really matter that the original problem has digits going from 1 to N since it is easy to map digit values from one scheme to the other.)
We can define a function to set the M-digit number to its lowest value:
void num_init(unsigned int *digits, unsigned int m)
{
while (m--)
{
digits[m] = 0;
}
}
We can define another function to increment the M-digit number and indicate whether the number has wrapped around back to its lowest value:
int num_inc(unsigned int *digits, unsigned int n, unsigned int m)
{
while (m--)
{
if (digits[m] < n - 1)
{
digits[m]++;
return 0;
}
digits[m] = 0; // carry
}
return 1;
}
Example usage:
// Print all M-digit numbers with digits from 1 to N.
void list_nums(unsigned int m, unsigned int n)
{
unsigned int digits[m];
int wrapped = 0;
num_init(digits, m);
while (!wrapped)
{
unsigned int i;
// output an m-digit number
for (i = 0; i < m; i++)
{
// Note: Add 1 to each digit so digits run from 1 to n instead of 0 to n-1.
printf("%u", digits[i] + 1);
}
// get next number
wrapped = num_inc(digits, n, m);
if (!wrapped)
{
printf(",");
}
}
printf("\n");
}
Note: The output of list_nums(m, n) will be strange when n is greater than 9.

C# - Constantly adding 9 digits

As the title says, I'm developing in C#.
I'd like to generate a number which has more than 9 numbers, so I thought about generating numbers, follow by 9.
For instance, if I want to generate a number which has 10 digits - I'd generate first a number which has 9 numbers, and then a number which has 1 digit.
If I generate the number 20, I'd generate first 2 numbers with 9 digits each, and then a number with 2 digits.
This is what I've tried:
for (int i = 0, j = (int.Parse(inputRandom.Text) % 9 == 0 ? int.Parse(inputRandom.Text) % 9 : int.Parse(inputRandom.Text) % 9 + 1); i < j; i++)
if (i < (int.Parse(inputRandom.Text) % 9 == 0 ? j % 9 : j % 9 + 1) - 1)
numToSend += (BigInteger)r.Next(int.Parse(1 + Zero((int.Parse(inputRandom.Text) % 9 + 8) * (inputRandom.Text.Length - 1))));
else
numToSend += (BigInteger)r.Next(int.Parse(1 + Zero(int.Parse(inputRandom.Text) % 9 * 9)));
The method Zero returns a string with 0, times the number specified in. I.e Zero(1) would return: "0"
I need this method because the method Next(Int32) can return a number, up to what specified between the brackets. I.e Next(10) would return a number between 0 and 9.
My goal
I want to generate a number with a number of digit above 9, and put the number into the string numToSend. I cannot simply do this, because the method Next() can only generate ints.
Even after your edit, I don't find the question very clear. However, I do think I understand that you are essentially trying to generate a random BigInteger value, and that you want the random value to be within a range defined by some specific number of digits.
For example, if you ask for a 10-digit value, some value between 0 and 9999999999 should be returned. If you ask for a 20-digit value, some value between 0 and 99999999999999999999 should be returned.
Based on that understanding, I believe this method should accomplish what you are asking:
BigInteger NextRandom(Random random, int digitCount)
{
BigInteger result = 0;
while (digitCount-- > 0)
{
result = result * 10 + random.Next(10);
}
return result;
}
Note that the number returned could have fewer than digitCount actual digits in it. In fact, there's always a 1-in-10 chance of that happening. And a 1-in-100 chance of the result having fewer than (digitCount - 1) digits, etc.
If you want something different from that, please be more specific about the exact requirements of the output you want (read https://stackoverflow.com/help/how-to-ask for advice on how to present your question in a clear, answerable way).
For example, the above won't generate a random value within some arbitrary range; the (exclusive) max value can only ever be a power of 10. Also, due to the way BigInteger works, if you are looking for a value with a specific number of binary digits, you can do that simply by using the Random.NextBytes() method, passing the resulting array (making modifications as appropriate to ensure e.g. positive values).
See also C# A random BigInt generator for more inspiration (I would've voted as that for a duplicate, but it seems from your description that you might be looking for a slightly different result than what's requested in that question).

C# formula to determine index

I have a maths issue within my program. I think the problem is simple but I'm not sure what terms to use, hence my own searches returned nothing useful.
I receive some values in a method, the only thing I know (in terms of logic) is the numbers will be something which can be duplicated.
In other words, the numbers I could receive are predictable and would be one of the following
1
2
4
16
256
65536
etc
I need to know at what index they appear at. In othewords, 1 is always at index 0, 2 at index 1, 4 at index 3, 16 is at index 4 etc.
I know I could write a big switch statement but I was hoping a formula would be tidier. Do you know if one exists or any clues as the names of the math forumula's I'm using.
The numbers you listed are powers of two. The inverse function of raising a number to a power is the logarithm, so that's what you use to go backwards from (using your terminology here) a number to an index.
var num = 256;
var ind = Math.Log(num, 2);
Above, ind is the base-2 logarithm of num. This code will work for any base; just substitute that base for 2. If you are only going to be working with powers of 2 then you can use a special-case solution that is faster based on the bitwise representation of your input; see What's the quickest way to compute log2 of an integer in C#?
Try
Math.Log(num, base)
where base is 2
MSDN: http://msdn.microsoft.com/en-us/library/hd50b6h5.aspx
Logarithm will return to You power of base from you number.
But it's in case if your number really are power of 2,
otherwise you have to understand exactly what you have, what you need
It also look like numbers was powered to 2 twice, so that try this:
private static int getIndexOfSeries(UInt64 aNum)
{
if (aNum == 1)
return 0;
else if (aNum == 2)
return 1;
else
{
int lNum = (int)Math.Log(aNum, 2);
return 1+(int)Math.Log(lNum, 2);
}
}
Result for UInt64[] Arr = new UInt64[] { 1, 2, 4, 16, 256, 65536, 4294967296 } is:
Num[0] = 1
Num[1] = 2
Num[2] = 4
Num[3] = 16
Num[4] = 256
Num[5] = 65536
Num[6] = 4294967296 //65536*65536
where [i] - index
You should calculate the base 2 logarithm of the number
Hint: For the results:
0 2
1 4
2 16
3 256
4 65536
5 4294967296
etc.
The formula is, for a give integer x:
Math.Pow(2, Math.Pow(2, x));
that is
2 to the power (2 to the power (x) )
Once the formula is known, one could solve it for x (I won't go through that since you already got an answer).

Array.BinarySearch() return value

I have the following array:
double[] list = new double[] {0,0,100,100}
Why if I search for 29.6 I get -3?
Array.BinarySearch(list, 29.6)
I expected +1 or -1.
The Array.BinarySearch() documentation for the return parameter says:
The index of the specified value in the specified array, if value is found. If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value. If value is not found and value is greater than any of the elements in array, a negative number which is the bitwise complement of (the index of the last element plus 1).
But it does not says too much to me.
If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value.
The first element which is larger than 29.6 is 100, which has index of 2.
~2 is -3.
You can use the '~' to take the bitwise complement which will give you the index of the first item larger than the search item.
If the Array does not contain the specified value, the method returns
a negative integer. You can apply the bitwise complement operator (~)
to the negative result (in Visual Basic, Xor the negative result with
-1) to produce an index. If this index is greater than or equal to the size of the array, there are no elements larger than value in the
array. Otherwise, it is the index of the first element that is larger
than value.
From the MSDN
Thus if you had:
var pos = Array.BinarySearch(list, 29.6);
You can check:
if (pos < 0)
{
Console.WriteLine("Not found, the result was {0} which is index {1}", pos, ~pos);
}
Which, in your case, means your -3 would indicate the index 2 is the first item larger than your search target.
Here is your answer:
"a negative number which is the bitwise complement of the index of the first element that is larger than value."
So in your case, your searched value (29.6) is less then 100 which is the 3rd element in your array list, the complement of 3 is -3, which is the answer you got.
Here I extended your example and created another array list (list2) with some different values then I searched same value like you 29.6, now this 29.6 value is smaller then 100 but greater then 25, and in my array list 100 is on position 4 and its complement is -4.
So I get the result -4, if I have searched 20 in my array list I would have get answer -3.
double[] list = new double[] { 0, 0, 100, 100 };
double[] list2 = new double[] { 10, 15, 25, 100 };
int result = Array.BinarySearch(list, 29.6);
int result2 = Array.BinarySearch(list2, 29.6);
Response.Write("Your answer result:" + result.ToString() + "<br/>");
Response.Write("Your answer result2:" + result2.ToString());
My Code result:
Your answer result : -3
Your answer result2: -4
I hope this helps.

Categories

Resources