I was playing around with the following problem:
Given a 2-d array find all the possible ways we can move from the top
left cell [0][0] to the bottom right cell [N-1][N-1] given that we
can only move either downward or rightward?
I defined the following:
For an array such as [ [ 1 ] ] there is only 1 way to go from the start cell to the destination cell. We are already there.
Otherwise it the total number of ways is the total number of ways we go from the cell to the right to the destination plus 1 (there is 1 way to go from current cell to the next cell) plus the total number of ways we go from the cell bellow to the destination plus 1 (there is 1 way to go from current cell to the bellow cell)
So for an array such as:
[
[1, 2]
[3, 4]
]
the answer would be 4 (1->2, 2->4, 1->3, 3->4).
For an array such as:
[
[1, 2, 3],
[3, 4, 5],
]
The answer should be 8. 4 comes from the subarray to the right + 1 to go for (1)->(2) plus 1->3 3->4 4->5 total 3.
So 5 + 3 = 7.
The following code seems to me correct but I am messing something up and I get the wrong result.
my $array = [
[1, 2, 3],
[3, 4, 5],
];
sub number_of_ways {
my ( $input, $source_row, $source_col, $dest_row, $dest_col ) = #_;
if ( $source_row == $dest_row && $source_col == $dest_col ) {
return 1;
}
if ( $source_row >= scalar #$input) {
return 0;
}
if ( $source_col >= scalar #{$input->[$source_row]} ) {
return 0;
}
my $ways_down = number_of_ways($input, $source_row + 1, $source_col, $dest_row, $dest_col);
my $ways_right = number_of_ways($input, $source_row, $source_col + 1, $dest_row, $dest_col);
my $total = $ways_right + 1 if ( $ways_right );
$total += $ways_down + 1 if ( $ways_down );
return $total;
}
print "Number of ways: " . number_of_ways($array, 0, 0, 1, 2). "\n";
This give me 11.
Is the logic wrong?
Update:
With the help of #m69 I found the problem.
In recursion is a bad idea to do the iteration if we already can check if it is going to fail. In this case, even after changing the code after the comments of #m69 it failed because there is no distinction between 0 because we are in an subarray with 1 element (source and destination are the same) or outside of the array.
The following code seems to be correct.
sub number_of_ways {
my ( $input, $source_row, $source_col, $dest_row, $dest_col ) = #_;
if ( $source_row == $dest_row && $source_col == $dest_col ) {
return 0;
}
my $total = 0;
if ( $source_row < #$input - 1) {
my $ways_down = number_of_ways($input, $source_row + 1, $source_col, $dest_row, $dest_col);
$total += $ways_down + 1;
}
if ( $source_col < #{$input->[$source_row]} - 1 ) {
my $ways_right = number_of_ways($input, $source_row, $source_col + 1, $dest_row, $dest_col);
$total += $ways_right + 1;
}
return $total;
}
print "Number of ways: " . number_of_ways($array, 0, 0, 1, 2). "\n";
Your algorithm uses this recursion:
0 1 2 0---1 2 0
= + |
3 4 5 4 5 3 4 5
which then goes on to:
1 2 1---2 1
= + | AND
4 5 5 4 5 3 4 5 = 3---4 5
and then:
2 2
= | AND AND
5 5 4 5 = 4---5 4 5 = 4---5
and finally:
5 AND 5 AND 5
In itself, this is a useful way of recursing in the 3x2 grid, but the way you then add the steps is problematic; e.g. after receiving 4 as the result of the recursion with the 2x2 grid [[1,2][4,5]], you add 1 to it because it takes 1 step to go from position 0 to the 2x2 grid. However, there are two paths through the 2x2 grid, so you should add the 1 step twice. Knowing how many paths there were through the 2x2 grid requires calculating the Taxicab distance through it, and then dividing the number of steps by this distance. You'll see that this results in a lot of unnecessary calculations, because the number of steps in each complete path is always the same. So it's much easier to just find the number of paths, and then multiply them by the number of steps per path.
You can use the recursion you have to find the number of paths; from the breakdown into steps of the recursion above you'll see that you end up with the 1x1 grid [5] three times. This is because there are three paths that lead to position 5. If you simply count how many times you recurse with that 1x1 grid), you know the number of paths. To know the number of steps you can then multiply by (width - 1) + (height - 1) which is the number of steps in each path.
The disadvantage of simply incrementing a variable outside the scope of the recursion is that you cannot easily turn it into a dynamic programming solution, because you have to go through with every recursion to the end, to count how many times you get to the bottom-right corner. So it's probably better to pass the results back up the recursion chain.
If you return 1 when the input is a 1x1 grid, and the sum of the right and down result in a larger grid (without adding anything to it), this also gives you the total number of paths. Then you can memoize the results by storing that a 2x1 and 1x2 grid return 1, a 2x2 grid returns 2, a 3x2 and 2x3 grid returns 3, a 3x3 grid returns 6, and use these stored values instead of recursing over grids with the same size again.
You'll see that the number of paths through any size grid is given by this table:
1 1 1 1 1 ...
1 2 3 4 5
1 3 6 10 15
1 4 10 20 35
1 5 15 35 70
where each value is the sum of the values above and to the left of it, which also points to a simple non-recursive way to calculate the number of paths (or steps) through any size grid.
This code snippet in JavaScript uses the recursion method from your code to count the number of paths, and then calculates the total number of steps:
function count_paths(grid, x, y) {
x = x || 0; y = y || 0;
var height = grid.length - y;
var width = grid[0].length - x;
if (width == 0 || height == 0) return 0;
if (width == 1 && height == 1) return 1;
return count_paths(grid, x + 1, y) + count_paths(grid, x, y + 1);
}
var grid = [[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]];
var paths = count_paths(grid);
var steps = paths * (grid.length - 1 + grid[0].length - 1);
document.write("paths: " + paths + "<br>steps: " + steps);
To integrate the calculation of the total number of steps into the recursion, you'd have to return the number of paths and the number of steps, so that you can multiply the step it takes to go right or down by the number of paths that that step leads to:
function count_steps(grid, x, y) {
x = x || 0; y = y || 0;
var height = grid.length - y;
var width = grid[0].length - x;
if (width == 0 || height == 0) return {paths: 0, steps: 0};
if (width == 1 && height == 1) return {paths: 1, steps: 0};
var right = count_steps(grid, x + 1, y);
var down = count_steps(grid, x, y + 1);
var paths = right.paths + down.paths;
var steps = right.steps + down.steps + paths;
return {paths: paths, steps: steps};
}
var grid = [[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]];
var count = count_steps(grid);
document.write("paths: " + count.paths + "<br>steps: " + count.steps);
Related
I have a number n and i want to find number of ways i can create an array having n distinct elements from 1 to n such that for no index i we have A[i] = i.
For example
n = 4 we have 9 permutations
[ 2 1 4 3 ] ,[ 2 3 4 1 ],[ 2 4 1 3 ],[ 3 1 4 2 ],[ 3 4 1 2 ],[ 3 4 2 1 ],[ 4 1 2 3 ],[ 4 3 1 2 ],[ 4 3 2 1 ].
I know the brute force approach which will have time complexity O(n!). Is there any other optimized way of doing this? Something in O(n) or O(nlogn) complexity.
A permutation of {1,2,...,n} in which no element occurs in its position is called a derangement. You are looking for the number of derangements of an n-element set, for which there is a formula (which can be obtained using the inclusion-exclusion principle). The formula is $n! \sum_{i=0}^n (-1)^i / i!$. See the Wikipedia article on derangements, which derives this formula.
In the limit, this value approaches n!/e, which is approximately 0.37 n!, i.e 37% of the n! permutations would be derangements.
The Counting Derangements problem can be solved in linear time O(n) using dynamic programming, thanks to Euler who proved the recurrence relation :
!n = (n-1) * (!(n-1) + !(n-2))
This allows to solve the problem from bottom up instead of recursively, keeping track of the 2 preceding terms !(n-1) and !(n-2) (eg. in javascript) :
function a(n) {
if (n < 3) {
return n < 0 ? undefined : Math.abs(n-1);
}
// For n = 3, we got :
let x = 1; // !(n-1)
let y = 0; // !(n-2)
for (let k=3; k<=n; k++) {
const fk = (k - 1) * (x + y);
[x, y] = [fk, x];
}
return x;
}
Euler also proved another recurrence relation :
!n = n * !(n-1) + (-1)^n
Using the same technique, there is only one preceding term (variable) to track. This translates to :
function a(n) {
if (n < 3) {
return n < 0 ? undefined : Math.abs(n-1);
}
let x = 1; // !(n-1) for n = 3
for (let k=3; k<=n; k++) {
x = k*x + (-1)**k;
}
return x;
}
I have a matrix A like this:
A = [ 1 0 2 4; 2 3 1 0; 0 0 3 4 ]
A has only unique row elements except zero, and each row has at least 2 non-zero elements.
I want to create a new matrix B from A,where each row in B contains the first two non-zero elements of the corresponding row in A.
B = [ 1 2 ; 2 3 ; 3 4 ]
It is easy with loops but I need vectorized solution.
Here's a vectorized approach:
A = [1 0 2 4; 2 3 1 0; 0 0 3 4]; % example input
N = 2; % number of wanted nonzeros per row
[~, ind] = sort(~A, 2); % sort each row of A by the logical negation of its values.
% Get the indices of the sorting
ind = ind(:, 1:N); % keep first N columns
B = A((1:size(A,1)).' + (ind-1)*size(A,1)); % generate linear index and use into A
Here is another vectorised approach.
A_bool = A > 0; A_size = size(A); A_rows = A_size(1);
A_boolsum = cumsum( A_bool, 2 ) .* A_bool; % for each row, and at each column,
% count how many nonzero instances
% have occurred up to that column
% (inclusive), and then 'zero' back
% all original zero locations.
[~, ColumnsOfFirsts ] = max( A_boolsum == 1, [], 2 );
[~, ColumnsOfSeconds ] = max( A_boolsum == 2, [], 2 );
LinearIndicesOfFirsts = sub2ind( A_size, [1 : A_rows].', ColumnsOfFirsts );
LinearIndicesOfSeconds = sub2ind( A_size, [1 : A_rows].', ColumnsOfSeconds );
Firsts = A(LinearIndicesOfFirsts );
Seconds = A(LinearIndicesOfSeconds);
Result = horzcat( Firsts, Seconds )
% Result =
% 1 2
% 2 3
% 3 4
PS. Matlab / Octave common subset compatible code.
Given an array {1,3,5,7}, its subparts are defined as {1357,135,137,157,357,13,15,17,35,37,57,1,3,5,7}.
I have to find the sum of all these numbers in the new array. In this case sum comes out to be 2333.
Please help me find a solution in O(n). My O(n^2) solution times out.
link to the problem is here or here.
My current attempt( at finding a pattern) is
for(I=0 to len) //len is length of the array
{
for(j=0 to len-i)
{
sum+= arr[I]*pow(10,j)*((len-i) C i)*pow(2,i)
}
}
In words - len-i C i = (number of integers to right) C weight. (combinations {from permutation and combination})
2^i = 2 power (number of integers to left)
Thanks
You can easily solve this problem with a simple recursive.
def F(arr):
if len(arr) == 1:
return (arr[0], 1)
else:
r = F(arr[:-1])
return (11 * r[0] + (r[1] + 1) * arr[-1], 2 * r[1] + 1)
So, how does it work? It is simple. Let say we want to compute the sum of all subpart of {1,3,5,7}. Let assume that we know the number of combinatiton of {1,3,5} and the sum of subpart of {1,3,5} and we can easily compute the {1,3,5,7} using the following formula:
SUM_SUBPART({1,3,5,7}) = 11 * SUM_SUBPART({1,3,5}) + NUMBER_COMBINATION({1,3,5}) * 7 + 7
This formula can easily be derived by observing. Let say we have all combination of {1,3,5}
A = [135, 13, 15, 35, 1, 3, 5]
We can easily create a list of {1,3,5,7} by
A = [135, 13, 15, 35, 1, 3, 5] +
[135 * 10 + 7,
13 * 10 + 7,
15 * 10 + 7,
35 * 10 + 7,
1 * 10 + 7,
3 * 10 + 7,
5 * 10 + 7] + [7]
Well, you could look at at the subparts as sums of numbers:
1357 = 1000*1 + 100*3 + 10*5 + 1*7
135 = 100*1 + 10*3 + 1*5
137 = 100*1 + 10*3 + 1*7
etc..
So, all you need to do is sum up the numbers you have, and then according to the number of items work out what is the multiplier:
Two numbers [x, y]:
[x, y, 10x+y, 10y+x]
=> your multiplier is 1 + 10 + 1 = 12
Three numbers [x, y, z]:
[x, y, z,
10x+y, 10x+z,
10y+x, 10y+z,
10z+x, 10z+y,
100x+10y+z, 100x10z+y
.
. ]
=> you multiplier is 1+10+10+1+1+100+100+10+10+1+1=245
You can easily work out the equation for n numbers....
If you expand invisal's recursive solution you get this explicit formula:
subpart sum = sum for k=0 to N-1: 11^(N-k) * 2^k * a[k]
This suggests the following O(n) algorithm:
multiplier = 1
for k from 0 to N-1:
a[k] = a[k]*multiplier
multiplier = multiplier*2
multiplier = 1
sum = 0
for k from N-1 to 0:
sum = sum + a[k]*multiplier
multiplier = multiplier*11
Multiplication and addition should be done modulo M of course.
TLDR: (part 1) Need to print out the best composition of weights to reach a target weight. (part 2) Don't know what approach to choose. (part 3) Also, recursion is not my friend.
I am not asking for a solution, I am just looking for a direction.
PART 1
Some text first.
The input to the program is:
a number of weights
weights themselves
target weights I am supposed to compose
There always has to be a weight that = 1, so all the weights can be composed exactly.
I am supposed to print out the optimal composition of weights, for example
number of weights: 4
weights: 1, 3, 7, 10
target weight: 4
output: 2 x 7
PART 2
The first thing that came to my mind was the unbounded knapsack problem, where I would set all the values for weights to "1" and then I'd look for the lowest possible value in the knapsack. The problem is, my programming skills don't reach that level and my googling skills failed me when I wanted to find a fine article/code/video/whatever to understand it.
Then someone pointed out the making-change problem. The problem there is that it usually uses an array and I am expecting really large numbers, I cannot afford to alloc an array of size = target weight. Also, it seems to require quite a lot of magic if I want not only the lowest possible number of weights, but the exact counts.
My solution now, shall I?
sort the weights in descending order
count the number of weights yielded from the greedy algorithm
remove one biggest weight used and try to compose the weight without it
repeat 3 until I have removed all the "biggest weights" or the number of weights started to grow again
(for weights = 1, 3, 7, 10 and target = 14, greedy would give me 1 x 10 + 1 x 3 + 1 x 1, after the third step I would get (0 x 10 +) 2 x 7)
I got here. Only I need to repeat this not outside the recursive function (like I was doing until I realised it still doesn't give me the right results) but I need to move the loop into the recursive function.
PART 3
This is how parts of my code looks now:
for ( i = 0; i < weights_cnt; i ++ )
for ( j = 0; j <= weight / *(weights + i); j ++ )
{
*counter = 0;
if ( (res = greedyMagicImproved(weights + i, weight / *(weights + i) - j, weight, counter, min)) == 0 || min > *counter ) break;
else min = *counter;
}
It's a mess, I know. (the first recursive function I've ever written, sorry for that)
int greedyMagicImproved (int * weights, int limit, int weight, int * counter, int min)
{
if ( *counter > min ) return 0;
else if ( weight % *weights == 0 )
{
printf ("%d * %d\n", limit, *weights);
*counter += limit;
return *counter;
}
else if ( weight == 0 ) return *counter;
else if ( weight / *weights )
{
printf ("%d * %d + ", limit, *weights);
*counter += limit;
return (greedyMagicImproved(weights + 1, (weight - *weights * limit) / *(weights + 1), (weight - *weights * limit) % *weights, counter, min));
}
else return greedyMagicImproved(weights + 1, weight / *(weights + 1), weight, counter, min);
}
This one produces something like this:
Number of weights:
8
Actual weights of weights:
1 2 4 5 10 20 60 95
Weights to be composed:
124
GREEDY = 1 * 95 + 1 * 20 + 1 * 5 + 1 * 4
IMP = 1 * 95 + 1 * 20 + 1 * 5 + 1 * 4
2 * 60 + 1 * 4
6 * 20 + 1 * 4
... some more irrelevant results I'll deal with later
28
GREEDY = 1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
IMP = 1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
2 * 10 + 1 * 5 + 1 * 2 + 1 * 1
5 * 5 + 1 * 2 + 1 * 1
... some more results as well
While I get to see the correct result in the first case, I do not in the second.
So basically, my question is: Should I try to move the loop part into the recursion (and write it basically all over again because I have no idea how to do it) or should I go stealing/packing and making change?
Here is a DP formulation:
Let w[i], i=0,1,...p be the coin weights and f(t,i) be the number of coins needed to hit target t using only w[k], k >= i. When there is no possible way to make change, then f(t,i) is infinite. With this we know
f(t,i) = min_{n} [ n + f(t - n * w[i], i + 1) ]
In English, to hit the target with the minimum of coins using only coins i, i+1, ... p, choose all possible quantities n of coin i and then use the same DP to make change for the remaining amount using only coins i+1,i+2,..., finally choosing the solution that produced the minimum.
The base cases are common sense. For example f(0,_) = 0. You don't need any coins to hit a target of zero.
If T is the problem target, then the answer will be f(T,0).
Since you don't want the answer, I'll let you convert this to code. It's likely you'll get to answers faster if the weights are sorted in descending order.
I have the following array:
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
I use it for some visual stuff like this:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now I want to sort the array like this to have a "zig-zag" when rendering later.
// rearrange the array according to this schema
1 3 6 10
2 5 9 13
4 8 12 15
7 11 14 16
// the original array should look like this:
a = [1,5,2,9,6,3,13,10,7,4,14,11,8,15,12,16]
// the second index to draw should be the first index in the second row,
// which is represent by 5 in the original 1D Array
Yeah, now I'm looking for a smart formula to do that
ticker = 0;
rows = 4; // can be n
cols = 4; // can be n
originalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
newArray = [];
while(ticker < originalArray.length)
{
//do the magic here
ticker++;
}
You can leave it sorted in the original order, you just have to step through it differently. EDIT: Turns out that my naive implementation didn't account for the differing step size based on the diagonal. The code below does and has been tested in C#.
var diagonals = new [] { 1, 2, 3, 4, 4, 3, 2, 1 };
for (int i = 0, m = 0; m < 4; i = i + m, ++m) {
for (int j = m, k = 0; k < 4; j = j + diagonals[m+k+1], ++k) {
Console.Write( i+j+1 );
Console.Write( " " );
}
Console.WriteLine();
}
Obviously, you could use this algorithm to fill a new array if you needed to keep that ordering around. It should also scale -- you just need to change the termination conditions to the square root of the array size and automate the generation of the diagonals.
Look at the structure of your matrix:
1 3
| / /
| / /
|/ / ...
2 / 5
/ /
/ /
4
The 1st row starts at 1
The 2nd row starts at 2 = 1 + 1 (# elements in 1st zig)
The 3rd row starts at 4 = 1
+ 1 (# elements in 1st zig)
+ 2 (# elements in 2nd zig)
...
The 3rd row ends at 6 = start of 3rd row + row num
= 4 + 3 = 7
You can derive a closed form formula for the ith row and go ahead.