Identify consecutive repetition in two-dimensional array [C] - recursion

I have a 2-dimensional array that looks like this:
1 1 0 0 1
1 0 1 1 0
0 0 1 1 0
1 1 0 1 1
0 0 1 1 1
I'm trying to figure out a way to identify the longest contiguous chain of 1's going either across or down. In this case, it starts at column 4, row 2, and its length is 4, going down.
I was thinking of using recursion, but I'm running into some issues keeping track of position, especially when encountering a 0.
So far, I have something along the lines of this (for checking across only):
main() {
...
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
if (G[i][j] == 1) {
CheckAcross(i, j, n);
}
...
}
void CheckAcross (int i, int j, int n) {
if (i < 0 || i >= n || j < 0 || j >= n) return; // outside of grid
if (G[i][j] == 0 ) return; //0 encountered
G[i][j] = WordCount + 1;
CheckAcross(i, j + 1, n);
}
where G[][] is the 2-dimensional array containing the 1's and 0's, n is the number of rows/columns, i is the row number and j is the column number.
Thanks for any assistance in advance!

Your current answer will take O(n3) time; to evaluate a single line, you check every possible start and end position (O(n) possibilities for each), and there are n lines.
Your algorithm is correct, but let's see if we can improve on the running time.
The problem might become simpler if we break it into simpler problems, i.e. "What is the longest contiguous chain of 1s in this 1-dimensional array?". If we solve it 2n times, then we have our answer, so we just need to get this one down to smaller than O(n2) for an improvement.
Well, we can simply go through the line, remembering the position (start and end) and length of the longest sequence of 1s. This takes O(n) time, and is optimal (if the sequence is all 1s or 0s, we would have to read every element to know where the start/end of the longest sequence is).
Then we can simply solve this for every row and every column, in O(n2) time.

Create a new n-by-n matrix called V. This will store, for each cell, the number of 1s at that cell and immediately above it. This will be O(n^2).
checkAllVertical(int n) {
V = malloc(....) // create V, an n-by-n matrix initialized to zero
for(int r=0; r<n; r++) {
for(int c=0; c<n; c++) {
if(G[r][c]=1) {
if(r==0)
V[r][c] = 1;
else
V[r][c] = 1 + V[r][c];
}
}
}
}
You don't really need to allocate all of V. One row at a time would suffice.

Related

Carmichael Number using Pari

Trying to write Pari code to solve the above question.
I've got no experience in using Pari, but here's some useful advice:
n is Carmichael if and only if it is composite and, for all a with 1 < a < n which are relatively prime to n, the congruence a^(n-1) = 1 (mod n) holds. To use this definition directly, you need:
1) An efficient way to test if a and n are relatively prime
2) An efficient way to compute a^(n-1) (mod n)
For the first -- use the Euclidean algorithm for greatest common divisors. It is most efficiently computed in a loop, but can also be defined via the simple recurrence gcd(a,b) = gcd(b,a%b) with basis gcd(a,0) = a. In C this is just:
unsigned int gcd(unsigned int a, unsigned int b){
return b == 0? a : gcd(b, a%b);
}
For the second point -- almost the worst possible thing you can do when computing a^k (mod n) is to first compute a^k via repeated multiplication and to then mod the result by n. Instead -- use exponentiation by squaring, taking the remainder (mod n) at intermediate stages. It is a divide-and-conquer algorithm based on the observation that e.g. a^10 = (a^5)^2 and a^11 = (a^5)^2 * a. A simple C implementation is:
unsigned int modexp(unsigned int a, unsigned int p, unsigned int n){
unsigned long long b;
switch(p){
case 0:
return 1;
case 1:
return a%n;
default:
b = modexp(a,p/2,n);
b = (b*b) % n;
if(p%2 == 1) b = (b*a) % n;
return b;
}
}
Note the use of unsigned long long to guard against overflow in the calculation of b*b.
To test if n is Carmichael, you might as well first test if n is even and return 0 in that case. Otherwise, step through numbers, a, in the range 2 to n-1. First check if gcd(a,n) == 1 Note that if n is composite then you must have at least one a before you reach the square root of n with gcd(a,n) > 1). Keep a Boolean flag which keeps track of whether or not such an a has been encountered and if you exceed the square root without finding such an a, return 0. For those a with gcd(a,n) == 1, compute the modular exponentiation a^(n-1) (mod n). If this is ever different from 1, return 0. If your loop finishes checking all a below n without returning 0, then the number is Carmichael, so return 1. An implementation is:
int is_carmichael(unsigned int n){
int a,s;
int factor_found = 0;
if (n%2 == 0) return 0;
//else:
s = sqrt(n);
a = 2;
while(a < n){
if(a > s && !factor_found){
return 0;
}
if(gcd(a,n) > 1){
factor_found = 1;
}
else{
if(modexp(a,n-1,n) != 1){
return 0;
}
}
a++;
}
return 1; //anything that survives to here is a carmichael
}
A simple driver program:
int main(void){
unsigned int n;
for(n = 2; n < 100000; n ++){
if(is_carmichael(n)) printf("%u\n",n);
}
return 0;
}
output:
C:\Programs>gcc carmichael.c
C:\Programs>a
561
1105
1729
2465
2821
6601
8911
10585
15841
29341
41041
46657
52633
62745
63973
75361
This only takes about 2 seconds to run and matches the initial part of this list.
This is probably a somewhat practical method for checking if numbers up to a million or so are Carmichael numbers. For larger numbers, you should probably get yourself a good factoring algorithm and use Korseldt's criterion as described in the Wikipedia entry on Carmichael numbers.

Dynamic Programming: Child running up a staircase

I'm starting to practice Dynamic Programming and I just can't wrap my head around this question:
Question:
A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time. Implement a method to count how many possible ways the child can run up the stairs.
The solution from the cracking the coding interview book is like this:
"If we thought about all the paths to the nth step, we could just build them off the paths to the three previous steps. We can get up to the nth stop by any of the following:
Going to the (n-1) step and hopping 1 step
Going to the (n-2) step and hopping 2 steps
Going to the (n-3) step and hopping 3 steps"
Therefor to find the solution you just add the number of these path together !
That's what loses me ! Why isn't the answer like this: add number of those paths then add 3 ? Since if you are on step n-1 or n-2 or n-3, there are 3 ways to get the nth step? I understand that if you write down the answers for the first 4 bases cases (assuming that n=0 returns 1) You can see the fibonacci-like pattern. But you may not also see it so it's difficult.
And then they came up with this code:
public static int countWaysDP(int n, int[] map) {
if (n < 0)
return 0;
else if (n == 0)
return 1;
else if (map[n] > -1)
return map[n];
else {
map[n] = countWaysDP(n - 1, map) + countWaysDP(n - 2, map) + countWaysDP(n - 3, map);
return map[n]; }
}
So my second question. How does it return 1 when n == 0. Even if I accept that fact, I still can't figure out a way to solve it if I return 0 when n == 1.
Hope this makes sense.
Thank you
Here is how I wrapped my head around this-
From the book -
On the very last hop, up to the nth step, the child could have
done either a single, double, or triple step hop. That is, the last
move might have been a single step hop from step n-1, a double
step hop from step n-2, or a triple step hop from n-3. The
total number of ways of reaching the last step is therefore the sum of
the number of ways of reaching each of the last three steps
You are correctly contemplating -
Why isn't the answer like this: add number of those paths then add 3 ?
Since if you are on step n-1 or n-2 or n-3, there are 3 ways to get
the nth step?
The problem with such a base case is that it will be applicable only if n >= 3. You clearly will not add 3 if there are only 2 steps.
Let's break down the individual cases and understand what exactly is the base case here.
n=0
There are no stairs to climb.
Total number of ways = 0
n=1
Total number of ways = 1StepHop from (n-1)
Number of ways to do 1StepHop from Step 0(n-1) = 1
Total number of ways = 1
n=2
Total number of ways = 2StepHop from (n-2) + 1StepHop from (n-1)
Number of ways to do 2StepHop to reach Step 2 from Step 0(n-2) = 1
Number of ways to do 1StepHop to reach Step 2 from Step 1(n-1) = 1 (Previous answer for n=1)
Total number of ways = 1 + 1 = 2
n=3
Total number of ways = 3StepHop from (n-3) + 2StepHop from (n-2) + 1StepHop from (n-1)
Number of ways to do 3StepHop to reach Step 3 from Step 0(n-3) = 1
Number of ways to do 2StepHop to reach Step 3 from Step 1(n-2) = 2 (From previous answer for n = 2)
Number of ways to do 1StepHop to reach Step 3 from Step 2 = 1 (From previous answer for n=1)
Total number of ways = 1 + 2 + 1 = 4
Observation -
As you can see from above, we are correctly accounting for the last step in each case. Adding one for each of -> 1StepHop from n-1, 2StepHop from n-2 and 3StepHop from n-3.
Now looking at the code, the case where we return 1 if n==0 is a bit counter-intuitive since we already saw that the answer should be 0 if n==0. -
public static int countWaysDP(int n, int[] map) {
if (n < 0)
return 0;
else if (n == 0)
return 1; <------------- this case is counter-intuitive
else if (map[n] > -1)
return map[n];
else {
map[n] = countWaysDP(n - 1, map) + countWaysDP(n - 2, map) + countWaysDP(n - 3, map);
return map[n];
}
From the observation, you can see that this counter intuitive case of n==0 is actually the one which is accounting for the final step - 1StepHop from n-1, 2StepHop from n-2 and 3StepHop from n-3.
So hitting n==0 case makes sense only during recursion - which will happen only when the initial value of n is greater than 0.
A more complete solution to this problem may have a driver method which handles that case outside of the core recursive algorithm -
int countWays(int n) {
if (n <= 0 ) return 0;
int[] map = new int[n+1];
for(int i = 0; i<n+1; i++){
map[i] = -1;
}
return countWaysDP(n, map);
}
Hope this is helpful.
You can find the solution on
https://github.com/CrispenGari/Triple-Step-Algorithim/blob/master/main.cpp .
int count_Ways(int n){
if(n<0){
return 0;
}else if(n==0){
return 1;
}else{
return count_Ways(n-1) +count_Ways(n-2) + count_Ways(n-3);
}
}
int main(){
cout<<"Enter number of stairs: ";
int n;
cin>>n;
cout<<"There are "<< count_Ways(n)<<" possible ways the child can run up
thestairs."<<endl;
return 0;
}

Confused about prime number checking function

I came across a question on stack overflow about how to check if a number is prime. The answer was the code below. The function int is_prime(int num) returns 1 when the number is prime 0 is returned otherwise.
int is_prime(int num)
{
if (num <= 1) return 0;
if (num % 2 == 0 && num > 2) return 0;
for(int i = 3; i < num / 2; i+= 2)
{
if (num % i == 0)
return 0;
}
return 1;
}
All the logic in the if statements makes sense to me except for the for loop expressions. I don't get why the division i < num / 2 happens and why i+= 2 is being used. Sure one is there to advance the counter and the other is to halt the loop. but why half the number and why increment by two. Any reasonable explanation will be appreciated. Thanks.
Regarding the loop's increment:
The second if (if (num % 2 == 0)) checks if the number is even, and terminates the function if it is. If the function isn't terminated, we know that it's odd, and thus, may only be divisible by other odd numbers. Hence, the loop starts at 3 and checks the number against a series of odd numbers - i.e., increments the potential divisor by 2 on each iteration.
Regarding the loop's stop condition:
The smallest integer larger than 1 is 2. Thus, the largest integer that could ever divide an integer n is n/2. Thus, the loop works it's way up to num/2. If it didn't find a divisor for num by the time it reaches num/2, it has no chance to ever find such a divisor, so it's pointless to keep on going.

Sum of combinations of numbers

I want to solve a mathematical problem in a fastest possible way.
I have a set of natural numbers between 1 to n, for example {1,2,3,4,n=5} and I want to calculate a formula like this:
s = 1*2*3*4+1*2*3*5+1*2*4*5+1*3*4*5+2*3*4*5
as you can see, each element in the sum is a multiplications of n-1 numbers in the set. For example in (1*2*3*4), 5 is excluded and in (1*2*3*5), 4 is excluded. I know some of the multiplications are repeated, for example (1*2) is repeated in 3 of the multiplications. How can I solve this problem with least number of multiplications.
Sorry for bad English.
Thanks.
Here is a way that does not "cheat" by replacing multiplication with repeated addition or by using division. The idea is to replace your expression with
1*2*3*4 + 5*(1*2*3 + 4*(1*2 + 3*(1 + 2)))
This used 9 multiplications for the numbers 1 through 5. In general I think the multiplication count would be one less than the (n-1)th triangular number, n * (n - 1) / 2 - 1. Here is Python code that stores intermediate factorial values to reduce the number of multiplications to just 6, or in general 2 * n - 4, and the addition count to the same (but half of them are just adding 1):
def f(n):
fact = 1
term = 2
sum = 3
for j in range(2, n):
fact *= j
term = (j + 1) * sum
sum = fact + term
return sum
The only way to find which algorithm is the fastest is to code all of them in one language, and run each using a timer.
The following would be the most straightforward answer.
def f(n):
result = 0
nList = [i+1 for i in range(n)]
for i in range(len(nList)):
result += reduce(lambda x, y: x*y,(nList[:i]+nList[i+1:]))
return result
Walkthrough - use the reduce function to multiply all list's of length n-1 and add to the variable result.
If you just want to minimise the number of multiplications, you can replace all the multiplications by additions, like this:
// Compute 1*2*…*n
mult_all(n):
if n = 1
return 1
res = 0
// by adding 1*2*…*(n-1) an entirety of n times
for i = 1 to n do
res += mult_all(n-1)
return res
// Compute sum of 1*2*…*(i-1)*(i+1)*…*n
sum_of_mult_all_but_one(n):
if n = 1
return 0
// by computing 1*2*…*(n-1) + (sum 1*2*…*(i-1)*(i+1)*…*(n-1))*n
res = mult_all(n-1)
for i = 1 to n do
res += sum_of_mult_all_but_one(n-1)
return res
Here is an answer that would work with javascript. It is not the fastest way because it is not optimized, but it should work if you want to just find the answer.
function combo(n){
var mult = 1;
var sum = 0;
for (var i = 1; i <= n; i++){
mult = 1;
for (var j = 1; j<= n; j++){
if(j != i){
mult = mult*j;
}
}
sum += mult;
}
return (sum);
}
alert(combo(n));

Dynamic programming problems using iteration

I have spent a lot of time to learn about implementing/visualizing dynamic programming problems using iteration but I find it very hard to understand, I can implement the same using recursion with memoization but it is slow when compared to iteration.
Can someone explain the same by a example of a hard problem or by using some basic concepts. Like the matrix chain multiplication, longest palindromic sub sequence and others. I can understand the recursion process and then memoize the overlapping sub problems for efficiency but I can't understand how to do the same using iteration.
Thanks!
Dynamic programming is all about solving the sub-problems in order to solve the bigger one. The difference between the recursive approach and the iterative approach is that the former is top-down, and the latter is bottom-up. In other words, using recursion, you start from the big problem you are trying to solve and chop it down to a bit smaller sub-problems, on which you repeat the process until you reach the sub-problem so small you can solve. This has an advantage that you only have to solve the sub-problems that are absolutely needed and using memoization to remember the results as you go. The bottom-up approach first solves all the sub-problems, using tabulation to remember the results. If we are not doing extra work of solving the sub-problems that are not needed, this is a better approach.
For a simpler example, let's look at the Fibonacci sequence. Say we'd like to compute F(101). When doing it recursively, we will start with our big problem - F(101). For that, we notice that we need to compute F(99) and F(100). Then, for F(99) we need F(97) and F(98). We continue until we reach the smallest solvable sub-problem, which is F(1), and memoize the results. When doing it iteratively, we start from the smallest sub-problem, F(1) and continue all the way up, keeping the results in a table (so essentially it's just a simple for loop from 1 to 101 in this case).
Let's take a look at the matrix chain multiplication problem, which you requested. We'll start with a naive recursive implementation, then recursive DP, and finally iterative DP. It's going to be implemented in a C/C++ soup, but you should be able to follow along even if you are not very familiar with them.
/* Solve the problem recursively (naive)
p - matrix dimensions
n - size of p
i..j - state (sub-problem): range of parenthesis */
int solve_rn(int p[], int n, int i, int j) {
// A matrix multiplied by itself needs no operations
if (i == j) return 0;
// A minimal solution for this sub-problem, we
// initialize it with the maximal possible value
int min = std::numeric_limits<int>::max();
// Recursively solve all the sub-problems
for (int k = i; k < j; ++k) {
int tmp = solve_rn(p, n, i, k) + solve_rn(p, n, k + 1, j) + p[i - 1] * p[k] * p[j];
if (tmp < min) min = tmp;
}
// Return solution for this sub-problem
return min;
}
To compute the result, we starts with the big problem:
solve_rn(p, n, 1, n - 1)
The key of DP is to remember all the solutions to the sub-problems instead of forgetting them, so we don't need to recompute them. It's trivial to make a few adjustments to the above code in order to achieve that:
/* Solve the problem recursively (DP)
p - matrix dimensions
n - size of p
i..j - state (sub-problem): range of parenthesis */
int solve_r(int p[], int n, int i, int j) {
/* We need to remember the results for state i..j.
This can be done in a matrix, which we call dp,
such that dp[i][j] is the best solution for the
state i..j. We initialize everything to 0 first.
static keyword here is just a C/C++ thing for keeping
the matrix between function calls, you can also either
make it global or pass it as a parameter each time.
MAXN is here too because the array size when doing it like
this has to be a constant in C/C++. I set it to 100 here.
But you can do it some other way if you don't like it. */
static int dp[MAXN][MAXN] = {{0}};
/* A matrix multiplied by itself has 0 operations, so we
can just return 0. Also, if we already computed the result
for this state, just return that. */
if (i == j) return 0;
else if (dp[i][j] != 0) return dp[i][j];
// A minimal solution for this sub-problem, we
// initialize it with the maximal possible value
dp[i][j] = std::numeric_limits<int>::max();
// Recursively solve all the sub-problems
for (int k = i; k < j; ++k) {
int tmp = solve_r(p, n, i, k) + solve_r(p, n, k + 1, j) + p[i - 1] * p[k] * p[j];
if (tmp < dp[i][j]) dp[i][j] = tmp;
}
// Return solution for this sub-problem
return dp[i][j];;
}
We start with the big problem as well:
solve_r(p, n, 1, n - 1)
Iterative solution is only to, well, iterate all the states, instead of starting from the top:
/* Solve the problem iteratively
p - matrix dimensions
n - size of p
We don't need to pass state, because we iterate the states. */
int solve_i(int p[], int n) {
// But we do need our table, just like before
static int dp[MAXN][MAXN];
// Multiplying a matrix by itself needs no operations
for (int i = 1; i < n; ++i)
dp[i][i] = 0;
// L represents the length of the chain. We go from smallest, to
// biggest. Made L capital to distinguish letter l from number 1
for (int L = 2; L < n; ++L) {
// This double loop goes through all the states in the current
// chain length.
for (int i = 1; i <= n - L + 1; ++i) {
int j = i + L - 1;
dp[i][j] = std::numeric_limits<int>::max();
for (int k = i; k <= j - 1; ++k) {
int tmp = dp[i][k] + dp[k+1][j] + p[i-1] * p[k] * p[j];
if (tmp < dp[i][j])
dp[i][j] = tmp;
}
}
}
// Return the result of the biggest problem
return dp[1][n-1];
}
To compute the result, just call it:
solve_i(p, n)
Explanation of the loop counters in the last example:
Let's say we need to optimize the multiplication of 4 matrices: A B C D. We are doing an iterative approach, so we will first compute the chains with the length of two: (A B) C D, A (B C) D, and A B (C D). And then chains of three: (A B C) D, and A (B C D). That is what L, i and j are for.
L represents the chain length, it goes from 2 to n - 1 (n is 4 in this case, so that is 3).
i and j represent the starting and ending position of the chain. In case L = 2, i goes from 1 to 3, and j goes from 2 to 4:
(A B) C D A (B C) D A B (C D)
^ ^ ^ ^ ^ ^
i j i j i j
In case L = 3, i goes from 1 to 2, and j goes from 3 to 4:
(A B C) D A (B C D)
^ ^ ^ ^
i j i j
So generally, i goes from 1 to n - L + 1, and j is i + L - 1.
Now, let's continue with the algorithm assuming that we are at the step where we have (A B C) D. We now need to take into account the sub-problems (which are already calculated): ((A B) C) D and (A (B C)) D. That is what k is for. It goes through all the positions between i and j and computes the sub problems.
I hope I helped.
The problem with recursion is the high number of stack frames that need to be pushed/popped. This can quickly become the bottle-neck.
The Fibonacci Series can be calculated with iterative DP or recursion with memoization. If we calculate F(100) in DP all we need is an array of length 100 e.g. int[100] and that's the guts of our used memory. We calculate all entries of the array pre-filling f[0] and f[1] as they are defined to be 1. and each value just depends on the previous two.
If we use a recursive solution we start at fib(100) and work down. Every method call from 100 down to 0 is pushed onto the stack, AND checked if it's memoized. These operations add up and iteration doesn't suffer from either of these. In iteration (bottom-up) we already know all of the previous answers are valid. The bigger impact is probably the stack frames; and given a larger input you may get a StackOverflowException for what was otherwise trivial with an iterative DP approach.

Resources