I have a vector that includes a value for every possible combination of two numbers out of a bigger group of n numbers (from 0 to (n-1)), excluding combinations where both numbers are the same.
For instance, if n = 4, combinations will be the ones shown in columns number1 and number2.
number1 number2 vector-index value
0 1 0 3
0 2 1 98
0 3 2 0
1 0 3 44
1 2 4 6
1 3 5 3
2 0 6 2
2 1 7 43
2 3 8 23
3 0 9 11
3 1 10 54
3 2 11 7
There are always n*(n-1) combinations and therefore that is the number of elements in the vector (12 elements in the example above).
Problem
In order to access the values in the vector I need a expression that allows me to figure out the corresponding index number for every combination.
If combinations where number1=number2 were included, the index number could be figured our using:
index = number1*(n-1)+number2
This question is related but includes also combinations where number1=number2.
Is there any expression to calculate the index in this case?
First, notice that all the pairs can be grouped into blocks of size (n-1), where n is the number of different indices. This means that given a pair (i, j), the index of the block containing it will be i(n-1). Within that block the indices are laid out sequentially, skipping over index i. If j < i, then we just look j steps past the start of the block. Otherwise, we look j-1 steps past it. Overall this gives the formula
int index = i * (n - 1) + (j < i? j : j - 1);
Note that the only difference is when number2 is greater than number1, when this happens a value from number2 sequence was skipped, so you will need to decrease the count, something like this:
index = number1 * (n - 1) + number2 - (number2 > number1 ? 1 : 0)
Related
Given the number n and a sequence of numbers from 1 to n^2 how to split it in n subsequences so all of the subsequences have the same sum and length of n ?
For example if n = 3 answer could be:
3 4 8 = 15
2 6 7 = 15
1 5 9 = 15
So I feel this problem can be solved by making few observations to the problem.
For example, let's say we have n=3. Then n^2=9.
Now total sum of all the numbers from 1 to 9 = 9 * (9+1) / 2 = 45.
So, now we can split 45 into three equal groups each having sum = 45/3 = 5.
Similarly:-
n = 4, sum of 1 to 16 numbers = 16 * 17/2 = 136. each group sum = 136/4 = 34.
n = 5, sum of 1 to 25 numbers = 25 * 26/2 = 25*13. each group sum = 25*13/5 = 65.
Now, we know what should be sum of each set of groups in order to split numbers into n sub sequences.
Now Another observation that we make is whether our n is odd or even.
For n being even, the splitting it very easy.
n = 2, so we have numbers 1 to 4.
1 4
2 3.
Let's assume a matrix of n x n , in above case it will be 2 x 2.
Rules for even n:-
1. Keep a counter = 1.
2. Fill the first column (1 to n), incrementing the counter by 1.
3. When we reach at the bottom of the column, for column 2, we do a reverse iteration (n to 1) and fill them with counter by incrementing it by 1.
You can verify this technique will work by taking n=2,4,6 ... and filling the array.
Now let's see how to fill this matrix n x n for n odd.
Rules for odd n:-
1. Keep a counter = 1.
2. Fill the first column (1 to n), incrementing the counter by 1.
3. Now this case is slightly different from even case, from the next column onwards,
we don't reverse our calculation from n to 1 but we keep moving ahead in column.
Let's understand this step by looking at an example.
Let's take n=3.
Our first column will be 1,2,3.
Now for the second column we start at bottom column which is n in our example it's 3.
Fill the n = 3 with value 4. next row value = (n+1)%n = 0, which gets 5, next row = (n+1+1)%n = 1 , which gets value 6. Now all the column 2 values are filled, let's move onto next column i.e third.
We will start at row = 1 , so row 1 column 3 will get 7, then row 2 column 3 will get 8 and then row 0 column 3 will get 9.
Hope this helps!
The problem is to find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product 6.
Why does the following work? Can anyone provide any insight on how to prove its correctness?
if(nums == null || nums.Length == 0)
{
throw new ArgumentException("Invalid input");
}
int max = nums[0];
int min = nums[0];
int result = nums[0];
for(int i = 1; i < nums.Length; i++)
{
int prev_max = max;
int prev_min = min;
max = Math.Max(nums[i],Math.Max(prev_max*nums[i], prev_min*nums[i]));
min = Math.Min(nums[i],Math.Min(prev_max*nums[i], prev_min*nums[i]));
result = Math.Max(result, max);
}
return result;
Start from the logic-side to understand how to solve the problem. There are two relevant traits for each subarray to consider:
If it contains a 0, the product of the subarray is aswell 0.
If the subarray contains an odd number of negative values, it's total value is negative aswell, otherwise positive (or 0, considering 0 as a positive value).
Now we can start off with the algorithm itself:
Rule 1: zeros
Since a 0 zeros out the product of the subarray, the subarray of the solution mustn't contain a 0, unless only negative values and 0 are contained in the input. This can be achieved pretty simple, since max and min are both reset to 0, as soon as a 0 is encountered in the array:
max = Math.Max(0 , Math.Max(prev_max * 0 , prev_min * 0));
min = Math.Min(0 , Math.Min(prev_max * 0 , prev_min * 0));
Will logically evaluate to 0, no matter what the so far input is.
arr: 1 1 1 1 0 1 1 1 0 1 1 1 0 1 1 0
result: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
min: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
max: 1 1 1 1 0 1 1 1 0 1 1 1 0 1 1 0
//non-zero values don't matter for Rule 1, so I just used 1
Rule 2: negative numbers
With Rule 1, we've already implicitly splitted the array into subarrays, such that a subarray consists of either a single 0, or multiple non-zero values. Now the task is to find the largest possible product inside that subarray (I'll refer to that as array from here on).
If the number of negative values in the array is even, the entire problem becomes pretty trivial: just multiply all values in the array and the result is the maximum-product of the array. For an odd number of negative values there are two possible cases:
The array contains only a single negative value: In that case either the subarray with all values with smaller index than the negative value or the subarray with all values with larger index than the negative value becomes the subarray with the maximum-value
The array contains at least 3 negative values: In that case we have to eliminate either the first negative number and all of it's predecessors, or the last negative number and all of it's successors.
Now let's have a look at the code:
max = Math.Max(nums[i] , Math.Max(prev_max * nums[i] , prev_min * nums[i]));
min = Math.Min(nums[i] , Math.Min(prev_max * nums[i] , prev_min * nums[i]));
Case 1: the evaluation of min is actually irrelevant, since the sign of the product of the array will only flip once, for the negative value. As soon as the negative number is encountered (= nums[i]), max will be nums[i], since both max and min are at least 1 and thus multiplication with nums[i] results in a number <= nums[i]. And for the first number after the negative number nums[i + 1], max will be nums[i + 1] again. Since the so far found maximum is made persistent in result (result = Math.Max(result, max);) after each step, this will automatically result in the correct result for that array.
arr: 2 3 2 -4 4 5
result: 2 6 12 12 12 20
max: 2 6 12 -4 4 20
//Omitted min, since it's irrelevant here.
Case 2: Here min becomes relevant too. Before we encounter the first negative value, min is the smallest number encountered so far in the array. After we encounter the first positive element in the array, the value turns negative. We continue to build both products (min and max) and swap them each time a negative value is encountered and keep updating result. When the last negative value of the array is encountered, result will hold the value of the subarray that eliminates the last negative value and it's successor. After the last negative value, max will be the product of the subarray that eliminates the first negative value and it's predecessors and min becomes irrelevant. Now we simply continue to multiply max with the remaining values in the array and update result until the end of the array is reached.
arr: 2 3 -4 3 -2 5 -6 3
result: 2 6 6 6 144 770 770 770
min: 2 6 -24 -72 -6 -30 -4620 ...
max: 2 6 -4 3 144 770 180 540
//min becomes irrelevant after the last negative value
Putting the pieces together
Since min and max are reset every time we encounter a 0, we can easily reuse them for each subarray that doesn't contain a 0. Thus Rule 1 is applied implicitly without interfering with Rule 2. Since result isn't reset each time a new subarray is inspected, the value will be kept persistent over all runs. Thus this algorithm works.
Hope this is understandable (To be honest, I doubt it and will try to improve the answer, if any questions appear). Sry for that monstrous answer.
Lets take assume the contiguous subarray, which produces the maximal product, is a[i], a[i+1], ..., a[j]. Since it is the array with the largest product, it is also the one suffix of a[0], a[1], ..., a[j], that produces the largest product.
The idea of your given algorithm is the following: For every prefix-array a[0], ..., a[j] find the largest suffix array. Out of these suffix arrays, take the maximal.
At the beginning, the smallest and biggest suffix-product are simply nums[0]. Then it iterates over all other numbers in the array. The largest suffix-array is always build in one of three ways. It's just the last numbers nums[i], it's the largest suffix-product of the shortened list multiplied by the last number (if nums[i] > 0), or it's the smallest (< 0) suffix-product multiplied by the last number (if nums[i] < 0). (*)
Using the helper variable result, you store the maximal such suffix-product you found so far.
(*) This fact is quite easy to proof. If you have a different case, for instance there exists a different suffix-product that produces a bigger number, than together with the last number nums[i] you create an even bigger suffix, which would be a contradiction.
I'd like to create a function where for an arbitrary integer input value (let's say unsigned 32 bit) and a given number of d digits the return value will be a d digit B base number, B being the smallest base that can be used to represent the given input on d digits.
Here is a sample input - output of what I have in mind for 3 digits:
Input Output
0 0 0 0
1 0 0 1
2 0 1 0
3 0 1 1
4 1 0 0
5 1 0 1
6 1 1 0
7 1 1 1
8 0 0 2
9 0 1 2
10 1 0 2
11 1 1 2
12 0 2 0
13 0 2 1
14 1 2 0
15 1 2 1
16 2 0 0
17 2 0 1
18 2 1 0
19 2 1 1
20 0 2 2
21 1 2 2
22 2 0 2
23 2 1 2
24 2 2 0
25 2 2 1
26 2 2 2
27 0 0 3
28 0 1 3
29 1 0 3
30 1 1 3
.. .....
The assignment should be 1:1, for each input value there should be exactly one, unique output value. Think of it as if the function should return the nth value from the list of strangely sorted B base numbers.
Actually this is the only approach I could come up so far with - given an input value, generate all the numbers in the smallest possible B base to represent the input on d digits, then apply a custom sorting to the results ('penalizing' the higher digit values and putting them further back in the sort), and return the nth value from the sorted array. This would work, but is a spectacularly inefficient implementation - I'd like to do this without generating all the numbers up to the input value.
What would be an efficient approach for implementing this function? Any language or pseudocode is fine.
MBo's answer shows how to find the smallest base that will represent an integer number with a given number of digits.
I'm not quite sure about the ordering in your example. My answer is based on a different ordering: Create all possible n-digit numbers up to base b (e.g. all numbers up to 999 for max. base 10 and 3 digits). Sort them according to their maximum digit first. Numbers are sorted normalls within a group with the same maximum digit. This retains the characteristic that all values from 8 to 26 must be base 3, but the internal ordering is different:
8 0 0 2
9 0 1 2
10 0 2 0
11 0 2 1
12 0 2 2
13 1 0 2
14 1 1 2
15 1 2 0
16 1 2 1
17 1 2 2
18 2 0 0
19 2 0 1
20 2 0 2
21 2 1 0
22 2 1 1
23 2 1 2
24 2 2 0
25 2 2 1
26 2 2 2
When your base is two, life is easy: Just generate the appropriate binary number.
For other bases, let's look at the first digit. In the example above, five numbers start with 0, five start with 1 and nine start with 2. When the first digit is 2, the maximum digit is assured to be 2. Therefore, we can combine 2 with a 9 2-digit numbers of base 3.
When the first digit is smaller than the maximum digit in the group, we can combine it with the 9 2-digit numbers of base 3, but we must not use the 4 2-digit numbers that are ambiguous with the 4 2-digit numbers of base 2. That gives us five possibilites for the digits 0 and 1. These possibilities – 02, 12, 20, 21 and 22 – can be described as the unique numbers with two digits according to the same scheme, but with an offset:
4 0 2
5 1 2
6 2 0
7 2 1
8 2 2
That leads to a recursive solution:
for one digit, just return the number itself;
for base two, return the straightforward representation in base 2;
if the first number is the maximum digit for the determined base, combine it with a straighforward representations in that base;
otherwise combine it with a recursively determined representation of the same algorithm with one fewer digit.
Here's an example in Python. The representation is returned as list of numbers, so that you can represent 2^32 − 1 as [307, 1290, 990].
import math
def repres(x, ndigit, base):
"""Straightforward representation of x in given base"""
s = []
while ndigit:
s += [x % base]
x /= base
ndigit -= 1
return s
def encode(x, ndigit):
"""Encode according to min-base, fixed-digit order"""
if ndigit <= 1:
return [x]
base = int(x ** (1.0 / ndigit)) + 1
if base <= 2:
return repres(x, ndigit, 2)
x0 = (base - 1) ** ndigit
nprev = (base - 1) ** (ndigit - 1)
ncurr = base ** (ndigit - 1)
ndiff = ncurr - nprev
area = (x - x0) / ndiff
if area < base - 1:
xx = x0 / (base - 1) + x - x0 - area * ndiff
return [area] + encode(xx, ndigit - 1)
xx0 = x0 + (base - 1) * ndiff
return [base - 1] + repres(x - xx0, ndigit - 1, base)
for x in range(32):
r = encode(x, 3)
print x, r
Assuming that all values are positive, let's make simple math:
d-digit B-based number can hold value N if
Bd > N
so
B > N1/d
So calculate N1/d value, round it up (increment if integer), and you will get the smallest base B.
(note that numerical errors might occur)
Examples:
d=2, N=99 => 9.95 => B=10
d=2, N=100 => 10 => B=11
d=2, N=57 => 7.55 => B=8
d=2, N=33 => 5.74 => B=6
Delphi code
function GetInSmallestBase(N, d: UInt32): string;
const
Digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
Base, i: Byte;
begin
Base := Ceil(Power(N, 1/d) + 1.0E-12);
if Base > 36 then
Exit('Big number, few digits...');
SetLength(Result, d);
for i := d downto 1 do begin
Result[i] := Digits[1 + N mod Base]; //Delphi string is 1-based
N := N div Base;
end;
Result := Result + Format(' : base [%d]', [Base]);
end;
begin
Memo1.Lines.Add(GetInSmallestBase(99, 2));
Memo1.Lines.Add(GetInSmallestBase(100, 2));
Memo1.Lines.Add(GetInSmallestBase(987, 2));
Memo1.Lines.Add(GetInSmallestBase(1987, 2));
Memo1.Lines.Add(GetInSmallestBase(87654321, 6));
Memo1.Lines.Add(GetInSmallestBase(57, 2));
Memo1.Lines.Add(GetInSmallestBase(33, 2));
99 : base [10]
91 : base [11]
UR : base [32]
Big number, few digits...
H03LL7 : base [22]
71 : base [8]
53 : base [6]
I want to convert a number in base 10 into a special base form like this:
A*2^2 + B*3^1 + C*2^0
A can take on values of [0,1]
B can take on values of [0,1,2]
C can take on values of [0,1]
For example, the number 8 would be
1*2^2 + 1*3 + 1.
It is guaranteed that the given number can be converted to this specialized base system.
I know how to convert from this base system back to base-10, but I do not know how to convert from base-10 to this specialized base system.
In short words, treat every base number (2^2, 3^1, 2^0 in your example) as weight of an item, and the whole number as the capacity of a bag. This problem wants us to find a combination of these items which they fill the bag exactly.
In the first place this problem is NP-complete. It is identical to the subset sum problem, which can also be seen as a derivative problem of the knapsack problem.
Despite this fact, this problem can however be solved by a pseudo-polynomial time algorithm using dynamic programming in O(nW) time, which n is the number of bases, and W is the number to decompose. The details can be find in this wikipedia page: http://en.wikipedia.org/wiki/Knapsack_problem#Dynamic_programming and this SO page: What's it called when I want to choose items to fill container as full as possible - and what algorithm should I use?.
Simplifying your "special base":
X = A * 4 + B * 3 + C
A E {0,1}
B E {0,1,2}
C E {0,1}
Obviously the largest number that can be represented is 4 + 2 * 3 + 1 = 11
To figure out how to get the values of A, B, C you can do one of two things:
There are only 12 possible inputs: create a lookup table. Ugly, but quick.
Use some algorithm. A bit trickier.
Let's look at (1) first:
A B C X
0 0 0 0
0 0 1 1
0 1 0 3
0 1 1 4
0 2 0 6
0 2 1 7
1 0 0 4
1 0 1 5
1 1 0 7
1 1 1 8
1 2 0 10
1 2 1 11
Notice that 2 and 9 cannot be expressed in this system, while 4 and 7 occur twice. The fact that you have multiple possible solutions for a given input is a hint that there isn't a really robust algorithm (other than a look up table) to achieve what you want. So your table might look like this:
int A[] = {0,0,-1,0,0,1,0,1,1,-1,1,1};
int B[] = {0,0,-1,1,1,0,2,1,1,-1,2,2};
int C[] = {0,1,-1,0,2,1,0,1,1,-1,0,1};
Then look up A, B, C. If A < 0, there is no solution.
I've been searching for an algorithm for the solution of all possible matrices of dimension 'n' that can be obtained with two arrays, one of the sum of the rows, and another, of the sum of the columns of a matrix. For example, if I have the following matrix of dimension 7:
matriz= [ 1 0 0 1 1 1 0
1 0 1 0 1 0 0
0 0 1 0 1 0 0
1 0 0 1 1 0 1
0 1 1 0 1 0 1
1 1 1 0 0 0 1
0 0 1 0 1 0 1 ]
The sum of the columns are:
col= [4 2 5 2 6 1 4]
The sum of the rows are:
row = [4 3 2 4 4 4 3]
Now, I want to obtain all possible matrices of "ones and zeros" where the sum of the columns and the rows fulfil the condition of "col" and "row" respectively.
I would appreciate ideas that can help solve this problem.
One obvious way is to brute-force a solution: for the first row, generate all the possibilities that have the right sum, then for each of these, generate all the possibilities for the 2nd row, and so on. Once you have generated all the rows, you check if the sum of the columns is right. But this will take a lot of time. My math might be rusty at this time of the day, but I believe the number of distinct possibilities for a row of length n of which k bits are 1 is given by the binomial coefficient or nchoosek(n,k) in Matlab. To determine the total number of possibilities, you have to multiply this number for every row:
>> n = 7;
>> row= [4 3 2 4 4 4 3];
>> prod(arrayfun(#(k) nchoosek(n, k), row))
ans =
3.8604e+10
This is a lot of possibilities to check! Doing the same for the columns gives
>> col= [4 2 5 2 6 1 4];
>> prod(arrayfun(#(k) nchoosek(n, k), col))
ans =
555891525
Still a large number, but 'only' a factor 70 smaller.
It might be possible to improve this brute-force method a little bit by seeing if the later rows are already constrained by the previous rows. If in your example, for a particular combination of the first two rows, both rows have a 1 in the second column, the rest of this column should all be 0, since the sum must be 2. This reduces the number of possibilities for the remaining rows a bit. Implementing such checks might complicate things a bit, but they might make the difference between a calculation that takes 2 days or one that takes just 1 hour.
An optimized version of this might alternatively generate rows and columns, and start with those for which the number of possibilities is the lowest. I don't know if there is a more elegant solution than this brute-force method, I would be interested to hear one.