Given a NxN matrix, I would like to linearly index into its upper right triangle,
following a diagonal by diagonal pattern, starting after the main diagonal.
For example, given a 4x4 matrix
X 0 3 5
X X 1 4
X X X 2
X X X X
I'm looking for a non recursive (closed form) function mapping linear indices from 0 to 5 to (x,y) achieving
f(0) = (0, 1)
f(1) = (1, 2)
f(2) = (2, 3)
f(3) = (0, 2)
f(4) = (1, 3)
f(5) = (0, 3)
Related for row by row runs:
Linear index upper triangular matrix
algorithm for index numbers of triangular matrix coefficients
Thanks to #loopy-walt's observation, we have an answer!
Using the result from Linear index upper triangular matrix, a transformation of the result
(i, j) |-> (j-i-1, j)
Gives the expected outcome.
Here is a C++ implementation.
#include<tuple>
#include<cmath>
// Linear indexing of the upper triangle, row by row
std::tuple<size_t, size_t> k2ij(size_t n, size_t k){
size_t i = n - 2 - (size_t)std::floor(std::sqrt(4*n*(n-1) - (8*k) -7)/2.0 - 0.5);
size_t j = k + i + 1 - n*(n-1)/2 + (n-i)*((n-i)-1)/2;
return {i,j};
}
// Linear indexing of the upper triangle, diagonal by diagonal
std::tuple<size_t, size_t> d2ij(size_t n, size_t d){
const auto [i, j] = k2ij(n, d);
return {j-i-1, j}; // Conversion from row by row to diag by diag
}
#include<iostream>
#include<set>
int main(int argc, char** argv) {
size_t n = 4;
size_t top = n*(n-1)/2;
for(size_t d=0; d<top; ++d){
const auto [i,j] = d2ij(n, d);
std::cout << "d2ij(" << n << ", " << d << ") = (" << i << ", " << j << ")" << std::endl;
}
return 0;
}
Producing
d2ij(4, 0) = (0, 1)
d2ij(4, 1) = (1, 2)
d2ij(4, 2) = (2, 3)
d2ij(4, 3) = (0, 2)
d2ij(4, 4) = (1, 3)
d2ij(4, 5) = (0, 3)
Note: if someone wishes the form f(d) instead, a lambda can be used to capture the dimension 'n'
auto f = [n](size_t d){return d2ij(n, d);};
const auto [i,j] = f(5);
Thanks to everybody that took the time to read and help!
I created a custom method for the array and value you gave.
int a[4][4] ={{-1, 0, 3, 5}, {-1, -1, 1, 4}, {-1, -1, -1, 2}, {-1, -1, -1, -1}};
The code is exactly like this. You give the array And whatever you give to the second value in the Func method, the indexes of the value in the upper diagonal will reach you.
#include <iostream>
using namespace std;
int b[2] ={-1,-1};
int Func(int a[4][4],int n)
{
for(int i =0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(a[i][j]==n)
{
if(i<j)
{
b[0]=i;
b[1]=j;
return 0;
}
}
}
}
}
int main()
{
int a[4][4] ={{-1, 0, 3, 5}, {-1, -1, 1, 4}, {-1, -1, -1, 2}, {-1, -1, -1, -1}};
Func(a,5);
for(int i=0;i<2;i++)
{
cout<<b[i]<<" ";
}
return 0;
}
thank you USEFUL for feedback if it worked for you
Maybe someone can come up with a math formula that doesn't require a loop, but until then I've come up with a O(N) solution:
#include <utility>
constexpr std::pair<int, int> f(int n, int idx)
{
int group_size = n - 1;
int rest = idx + 1;
while (rest > group_size)
{
rest = rest - group_size;
--group_size;
}
return {(rest - 1) % group_size,
n - group_size + (rest - 1) % group_size};
}
/* 3x3
X 0 2
X X 1
X X X
*/
static_assert(f(3, 0) == std::pair{0, 1});
static_assert(f(3, 1) == std::pair{1, 2});
static_assert(f(3, 2) == std::pair{0, 2});
// 4x4
static_assert(f(4, 0) == std::pair{0, 1});
static_assert(f(4, 1) == std::pair{1, 2});
static_assert(f(4, 2) == std::pair{2, 3});
static_assert(f(4, 3) == std::pair{0, 2});
static_assert(f(4, 4) == std::pair{1, 3});
static_assert(f(4, 5) == std::pair{0, 3});
/* 5x5
X 0 4 7 9
X X 1 5 8
X X X 2 6
X X X X 3
X X X X X
*/
static_assert(f(5, 0) == std::pair{0, 1});
static_assert(f(5, 1) == std::pair{1, 2});
static_assert(f(5, 2) == std::pair{2, 3});
static_assert(f(5, 3) == std::pair{3, 4});
static_assert(f(5, 4) == std::pair{0, 2});
static_assert(f(5, 5) == std::pair{1, 3});
static_assert(f(5, 6) == std::pair{2, 4});
static_assert(f(5, 7) == std::pair{0, 3});
static_assert(f(5, 8) == std::pair{1, 4});
static_assert(f(5, 9) == std::pair{0, 4});
So you want the inverse of the following function
Zero-based indexing form of element [i,j] for a n×n upper triangular matrix including the diagonal
index = i*n-i*(i+1)/2+j
i=0..4, j=0..4, index=
| 0 | 1 | 2 | 3 | 4 |
| X | 5 | 6 | 7 | 8 |
| X | X | 9 | 10 | 11 |
| X | X | X | 12 | 13 |
| X | X | X | X | 14 |
The easiest algorithm I can think of is to loop for all rows i and see if there is a match for the column j such that:
i <= j
j>=0
j<n
Here is a sample code given index and n
for(i=0; i<n; i++)
{
j = index - i*n + i*(i+1)/2
if( j>=0 && j<n && j>= i)
{
break;
}
}
And example with n=7 and [i,j]=[1,5] produces index=11. Now the coordinates of this index are
i
j
i<=j && j>=0 && j<7
0
11
1
5
valid
2
0
3
-4
4
-7
5
-9
6
-10
If you want strictly the upper triangular elements, excluding the diagonal then
Zero-based indexing form of element [i,j] for a n×n upper triangular matrix excluding the diagonal
index = i*n-i*(i+3)/2+j-1
i=0..3, j=0..4, index=
| X | 0 | 1 | 2 | 3 |
| X | X | 4 | 5 | 6 |
| X | X | X | 7 | 8 |
| X | X | X | X | 9 |
| X | X | X | X | X |
The algorithm now is to loop for all rows i and see if there is a match for the column j such that:
i < j
j>0
j<n
Here is a sample code given index and n
for(i=0; i<n; i++)
{
j = index - i*n + i*(i+3)/2 + 1
if( j>0 && j<n && j>i)
{
break;
}
}
And example with n=7 and [i,j]=[1,5] produces index=9. Now the coordinates of this index are
i
j
i<j && j>0 && j<7
0
10
1
5
valid
2
1
3
-2
4
-4
5
-5
Related
Given an array A of integers N, and after inputting the integers into the array, I need to make the difference between the neighboring less or equal to D and we need to do that in minimal moves. In the end print out the sum of the numbers that have been added or subtracted.
For every 0 < i < N, |S[i] - S[i - 1]| <= D
You can increase and decrease the number of the array element
Example 1: If we have an array like this
N = 7, D = 3 [2, 10, 2, 6, 4, 3, 3], then in this array we have to make the difference between the neighboring elements less or equal than 3. We don't modify the first array element, we skip over to the second array elements where we modify it from 10 down to 5 (since A[0] + 3 = 5), then we don't change the third element, we change the fourth element from 6 down to 5 (because A[3] + 3 = 5) and we don't change the rest of the elements because the difference between them is less than D. In the end we have to print out 6 (s = 0; 10 -> 5, s = 5; 6 -> 5, s = 6)
Example 2: If we have an array like this
N = 7, D = 0 [1, 4, 1, 2, 4, 2, 2]. Since D in this case is 0, by some logic we have to make all of the numbers the same. The most optimal (and in the fewest steps to solve this) way is we start with the last elements, we leave A[6] and A[5], we skip over to A[4]. Since A[4] is 4 and A[5] is 2, we have to change the 4 down to 2. Now since A[4] is 2, we skip over A[3] and we go to A[3] we change it from 1 up to 2. Then we change A[1] from 4 down to 2 and in the end, we change A[0] from 1 up to 2. In the end we have to print out 6 (s = 0; 4 -> 2, s = 2; 1 -> 2, s = 3; 4 -> 2, s = 5; 1 -> 2, s = 6).
Some other test cases:
N = 7, D = 1 [2, 10, 0, 2, 4, 3, 3] Solution: 10
N = 5, D = 1 [6, 5, 4, 3, 2] Solution: 0
I am unable to find an algorithm or an approach to this problem. I have tried several solutions and the closest I have come to solving it was 7/30 test cases.
My code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
int n, d, s1 = 0, s2 = 1;
cin >> n >> d;
int a[n], b[n];
for(int i = 0; i < n; i++) {
cin >> a[i];
b[i] = a[i];
}
reverse(b, b + n);
for(int i = 1; i < n; i++) {
if(a[i] - a[i - 1] <= d) {
continue;
} else {
if(a[i] > a[i - 1] + d) {
while(a[i] > a[i - 1] + d) {
a[i]--;
s1++;
}
} else if(a[i - 1] - d > a[i]) {
while(a[i - 1] - d > a[i]) {
a[i]++;
s1++;
}
}
}
}
for(int i = 1; i < n; i++) {
if(b[i] - b[i - 1] <= d) {
continue;
} else {
if(b[i] > b[i - 1] + d) {
while(b[i] > b[i - 1] + d) {
b[i]--;
s2++;
}
} else if(b[i - 1] - d > b[i]) {
while(b[i - 1] - d > b[i]) {
b[i]++;
s2++;
}
}
}
}
if(s1 >= s2)
cout << s2;
else
cout << s1;
return 0;
}
I'm trying to solve the Hackerrank problem "Connected Cells in a Grid". The task is to find the largest region (connected cells consisting of ones) in the grid.
My approach was to add the number of ones I find only if the element hasn't been visited yet, then I take the maximum of several paths. It doesn't seem to be working for the following test case:
5
5
1 1 0 0 0
0 1 1 0 0
0 0 1 0 1
1 0 0 0 1
0 1 0 1 1
Is there something wrong with my approach?
#include <vector>
#include <algorithm>
using namespace std;
#define MAX 10
bool visited[MAX][MAX];
int maxRegion(vector<vector<int>> const& mat, int i, int j) {
int result;
if ((i == 0 && j == 0) || visited[i][j]) {
result = 0;
}
else if (i == 0) {
result = mat[i][j-1] + maxRegion(mat, i, j-1);
}
else if (j == 0) {
result = mat[i-1][j] + maxRegion(mat, i-1, j);
}
else {
result = mat[i-1][j-1] +
max({maxRegion(mat, i-1, j),
maxRegion(mat, i, j-1),
maxRegion(mat, i-1, j-1)});
}
visited[i][j] = true;
return result;
}
I think it's very natural to formulate this program as a connected components problem. Specifically, I've used boost::graph for this.
The idea is to build a graph whose each entry in the matrix is a node, and there are edges between horizontal and vertical 1 entries. Once such a graph is built, all that is needed is to run the connected components algorithm, and find the biggest component.
The following code does so:
#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
using namespace std;
using namespace boost;
int main()
{
vector<vector<int>> v{{1, 1, 0, 0, 0}, {0, 1, 1, 0, 0}, {0, 0, 1, 0, 1}, {1, 0, 0, 0, 1}, {0, 1, 0, 1, 1}};
typedef adjacency_list <vecS, vecS, undirectedS> graph;
graph g(v.size() * v.size());
// Populate the graph edges
for(size_t i = 0; i < v.size() - 1; ++i)
for(size_t j = 0; j < v[i].size() - 1; ++j)
{
if(v[i][j] == 1 && v[i + 1][j] == 1)
add_edge(i * v.size() + j, (i + 1) * v.size() + j, g);
else if(v[i][j] == 1 && v[i][j + 1] == 1)
add_edge(i * v.size() + j, i * v.size() + j + 1, g);
}
// Run the connected-components algorithm.
vector<int> component(num_vertices(g));
int num = connected_components(g, &component[0]);
// Print out the results.
std::vector<int>::size_type i;
for(i = 0; i != component.size(); ++i)
cout << "Vertex (" << i / v.size() << ", " << i % v.size() << ") is in component " << component[i] << endl;
cout << endl;
}
The output is
Vertex (0, 0) is in component 0
Vertex (0, 1) is in component 0
Vertex (0, 2) is in component 1
Vertex (0, 3) is in component 2
Vertex (0, 4) is in component 3
Vertex (1, 0) is in component 4
Vertex (1, 1) is in component 0
Vertex (1, 2) is in component 0
Vertex (1, 3) is in component 5
Vertex (1, 4) is in component 6
Vertex (2, 0) is in component 7
Vertex (2, 1) is in component 8
Vertex (2, 2) is in component 0
Vertex (2, 3) is in component 9
Vertex (2, 4) is in component 10
Vertex (3, 0) is in component 11
Vertex (3, 1) is in component 12
Vertex (3, 2) is in component 13
Vertex (3, 3) is in component 14
Vertex (3, 4) is in component 15
Vertex (4, 0) is in component 16
Vertex (4, 1) is in component 17
Vertex (4, 2) is in component 18
Vertex (4, 3) is in component 19
Vertex (4, 4) is in component 20
Note that the program encodes i, j (for the case where the dimension is 5) by 5 i + j. This is easily invertible.
You can represent the matrix as an undirected graph and use DFS or BFS to find the connected component with the most nodes: every cell containing 1 can become a node, and there is an edge between two nodes if the corresponding cells are adjacent.
If you still need some guidance with the solution, here is mine in Python - passed all tests :) (visit my github to see other challenges that I've solved there in C++ as well)
def getBiggestRegion(grid, n, m):
max_region = 0
region_size = 0
for i in xrange(n):
for j in xrange(m):
if grid[i][j] == 1:
region_size = mark_region(grid, i, j, n, m)
#region_size += 1
if region_size > max_region:
max_region = region_size
return max_region
def push_if_valid(stack, i, j, n, m):
if 0 <= i < n and 0 <= j < m:
stack.append((i, j))
dirs = [[1,0], [0,1], [-1,0], [0,-1], [-1,-1], [-1, 1], [1,1], [1, -1]]
def mark_region(grid, i, j, n, m):
stack = []
stack.append((i, j))
region_size = 0
while stack:
curr = stack.pop()
ci = curr[0]
cj = curr[1]
if grid[ci][cj] == 1:
grid[ci][cj] = 2
region_size += 1
#this for loop is for going in all the directions
#North, South, East, West, NW, SW, SE, NE
#in my C++ Pacman sol, I have the actual lines instead
for dir in dirs:
push_if_valid(stack, ci + dir[0], cj + dir[1], n, m)
return region_size
n = int(raw_input().strip())
m = int(raw_input().strip())
grid = []
for grid_i in xrange(n):
grid_t = list(map(int, raw_input().strip().split(' ')))
grid.append(grid_t)
print(getBiggestRegion(grid, n, m))
Just for fun, I'm trying to implement the pseudocode from this StackOverflow answer for the highly factorized Sieve of Eratosthenes in C++. I can't figure out why my code returns both prime and non-prime numbers. Am I implementing these for loops incorrectly? Should I be using while loops instead? I suspect that I'm not incrementing the for loops properly. Any help would be greatly appreciated. I've spent several hours trying to hunt down the flaw.
GordonBGood's pseudocode is inserted as comments, and I've used all the same variable names.
#include <iostream>
#include <vector>
#include <cmath>
const int limit = 1000000000;
const std::vector<int> r {23,29,31,37,41,43,47,53, 59,61,67,71,73,79,83, //positions + 19
89,97,101,103,107,109,113,121,127, 131,137,139,
143,149,151,157,163,167,169,173,179,181,187,191,193,
197,199,209,211,221,223,227,229};
int main()
{
// an array of length 11 times 13 times 17 times 19 = 46189 wheels initialized
// so that it doesn't contain multiples of the large wheel primes
// for n where n ← 210 × w + x where w ∈ {0,...46189}, x in r: // already
// if (n mod cp) not equal to 0 where cp ∈ {11,13,17,19}: // no 2,3,5,7
// mstr(n) ← true else mstr(n) ← false // factors
std::vector<bool> mstr(limit);
int n;
for (int w=0; w <= 46189; ++w) {
for (auto x = begin(r); x != end(r); ++x) {
n = 210*w + *x;
if (n % 11 != 0 && n % 13 != 0 && n % 17 != 0 && n % 19 != 0)
mstr[n]=true;
else
mstr[n]=false;
}
}
// Initialize the sieve as an array of the smaller wheels with
// enough wheels to include the representation for limit
// for n where n ← 210 × w + x, w ∈ {0,...(limit - 19) ÷ 210}, x in r:
// sieve(n) ← mstr(n mod (210 × 46189)) // init pre-culled primes.
std::vector<bool> sieve(limit+1000);
for (int w=0; w <= (limit-19)/210; ++w) {
for (auto x = begin(r); x != end(r); ++x) {
n = 210*w + *x;
sieve[n] = mstr[(n % (210*46189))];
}
}
// Eliminate composites by sieving, only for those occurrences on the
// wheel using wheel factorization version of the Sieve of Eratosthenes
// for n² ≤ limit when n ← 210 × k + x where k ∈ {0..}, x in r
// if sieve(n):
// // n is prime, cull its multiples
// s ← n² - n × (x - 23) // zero'th modulo cull start position
// while c0 ≤ limit when c0 ← s + n × m where m in r:
// c0d ← (c0 - 23) ÷ 210, cm ← (c0 - 23) mod 210 + 23 //means cm in r
// while c ≤ limit for c ← 210 × (c0d + n × j) + cm
// where j ∈ {0,...}:
// sieve(c) ← false // cull composites of this prime
int s, c, c0, c0d, cm, j;
for ( auto x = begin(r); x != end(r); ++x) {
for ( int k=0; (n=210*k + (*x)) <= sqrt(limit); ++k){
if (sieve[n]) {
s = n*n - n*((*x)-23);
for ( auto m = begin(r); (c0=s+n*(*m)) <= limit && m != end(r); ++m) {
c0d = (c0-23)/210;
cm = (c0-23)%210 + 23;
for ( int j=0; (c=210*(c0d+n*j)+cm) <= limit; ++j) {
sieve[c] = false;
}
}
}
}
}
// output 2, 3, 5, 7, 11, 13, 17, 19,
// for n ≤ limit when n ← 210 × k + x where k ∈ {0..}, x in r:
// if sieve(n): output n
std::cout << "2\n3\n5\n7\n11\n13\n17\n19\n";
for ( auto x = begin(r); x != end(r); ++x) {
for ( int k = 0; (n=210*k + (*x)) <= limit; ++k) {
if (sieve[n]);
std::cout << n << std::endl;
}
}
std::cout << std::endl;
return 0;
}
The following returns the number 7. My problem is that im not exactly sure why 7 is the number returned. I tried running in in debug mode to break it down but
unfortunately that did not help.
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
bool even_first( int x, int y ){
if( (x % 2 == 0) && (y % 2 != 0) ) return true;
if( (x % 2 != 0) && (y % 2 == 0) ) return false;
return x < y;
}
struct BeforeValue {
int bound;
BeforeValue( int b ) : bound( b ) { }
bool operator()( int value ) { return even_first( value, bound ); }
};
int main(){
list<int> my_list = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int count = count_if( my_list.begin( ), my_list.end( ), BeforeValue( 5) );
cout << count << "\n";
}
To function even_first you pass 2 parameters: first parameter x is equal to successive values from my_list and the second parameter y is always 5.
And in the even_first function we have 3 conditions:
if( (x % 2 == 0) && (y % 2 != 0) ) return true;
y is equal to 5 so y % 2 != 0 is always true
x % 2 == 0 is true for: 0, 2, 4, 6, 8
if( (x % 2 != 0) && (y % 2 == 0) ) return false;
It is always false because y = 5 so y % 2 == 0 is false. We go to point 3
return x < y;
To this statement we go only with values: 1, 3, 5, 7, 9
and it is true for: 1 and 3
So finally the even_first returns true for: 0, 1, 2, 3, 4, 6, 8. And the size of this set is 7
I'm looking for an explanation for how the recursive version of pascal's triangle works
The following is the recursive return line for pascal's triangle.
int get_pascal(const int row_no,const int col_no)
{
if (row_no == 0)
{
return 1;
}
else if (row_no == 1)
{
return 1;
}
else if (col_no == 0)
{
return 1;
}
else if (col_no == row_no)
{
return 1;
}
else
{
return(get_pascal(row_no-1,col_no-1)+get_pascal(row_no-1,col_no));
}
}
I get how the algorithm works
What I wonder is how the recursion does the work.
Your algorithm contains a couple of unnecessary predicates for the base cases. It can be stated more simply as follows:
int pascal(int row, int col) {
if (col == 0 || col == row) {
return 1;
} else {
return pascal(row - 1, col - 1) + pascal(row - 1, col);
}
}
This of course assumes that you're guaranteeing that the arguments passed to the function are non-negative integers; you can always include an assertion if you can't impose such a guarantee from outside the function.
Pascal's triangle is essentially the sum of the two values immediately above it....
1
1 1
1 2 1
1 3 3 1
etc
In this, the 1's are obtained by adding the 1 above it with the blank space (0)
For code, all the 1's are occupied in either the first column (0), or when the (col == row)
For these two border conditions, we code in special cases (for initialization). The main chunk of the code (the recursive part) is the actual logic.
(The condition 'row == 1' is not necessary)
The most optimized way is this one:
int pascal(int row, int col) {
if (col == 0 || col == row) return 1;
else if(col == 1 || (col + 1) == row) return row;
else return pascal(row - 1, col - 1) + pascal(row - 1, col);
}
Unlike Fox's algorithm it prevents recursive calls for values which can be easily computed right from the input values.
Refer to the page for the source code:
#include <stdio.h>
int main()
{
int n, x, y, c, q;
printf("Pascal Triangle Program\n");
printf("Enter the number of rows: ");
scanf("%d",&n);
for (y = 0; y < n; y++)
{
c = 1;
for(q = 0; q < n - y; q++)
{
printf("%3s", " ");
}
for (x = 0; x <= y; x++)
{
printf(" %3d ",c);
c = c * (y - x) / (x + 1);
}
printf("\n");
}
printf("\n");
return 0;
}
The output would be,
Pascal Triangle Program
Enter the number of rows: 11
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
Pascal's triangle can be got from adding the two entries above the current one.
| 0 1 2 3 column
--+----------------------------------------------
0 | 1 (case 1)
1 | 1 (case 2) 1 (case 2)
2 | 1 (case 3) 2 (sum) 1 (case 4)
3 | 1 (case 3) 3 (sum) 3 (sum) 1 (case 4)
row
etc., for example column 2, row 3 = column 2, row 2 + column 1, row 2, where the cases are as follows:
if (row_no == 0) // case 1
{
return 1;
}
else if (row_no == 1) // case 2
{
return 1;
}
else if (col_no == 0) // case 3
{
return 1;
}
else if (col_no == row_no) // case 4
{
return 1;
}
else // return the sum
return pascalRecursive(height-1,width)+pascalRecursive(height-1,width-1);
Here is the code of #kathir-softwareandfinance
with more readable and more meaning variable names
#include <stdio.h>
int main()
{
int nOfRows, cols, rows, value, nOfSpace;
printf("Pascal Triangle Program\n");
printf("Enter the number of rows: ");
scanf("%d",&nOfRows);
for (rows = 0; rows < nOfRows; rows++)
{
value = 1;
for(nOfSpace = 0; nOfSpace < nOfRows - rows; nOfSpace++)
{
printf("%3s", " ");
}
for (cols = 0; cols <= rows; cols++)
{
printf(" %3d ",value);
value = value * (rows - cols) / (cols + 1);
}
printf("\n");
}
printf("\n");
return 0;
}
Here is how the recursion works
We call v(i, j), it calls v(i - 1, j), which calls v(i - 2, j) and so on,
until we reach the values that are already calculated (if you do caching),
or the i and j that are on the border of our triangle.
Then it goes back up eventually to v(i - 1, j), which now calls v(i - 2, j - 1),
which goes all the way to the bottom again, and so on.
....................................................................
_ _ _ _ call v(i, j) _ _ _ _ _
/ \
/ \
/ \
call v(i - 1, j) v(i - 1, j - 1)
/ \ / \
/ \ / \
call v(i - 2, j) v(i - 2, j - 1) v(i - 2, j - 1) v(i - 2, j - 2)
....................................................................
If you need to get the value often, and if you have enough memory:
class PascalTriangle
# unlimited size cache
public
def initialize
#triangle = Array.new
end
def value(i, j)
triangle_at(i, j)
end
private
def triangle_at(i, j)
if i < j
return nil
end
if #triangle[i].nil?
#triangle[i] = Array.new(i + 1)
else
return #triangle[i][j]
end
if (i == 0 || j == 0 || i == j)
#triangle[i][j] = 1
return #triangle[i][j]
end
#triangle[i][j] = triangle_at(i - 1, j) + triangle_at(i - 1, j - 1)
end
end
Using ternary approach for optimization; only 1 return command needed.
int f(int i, int j) {
return (
(i <= 1 || !j || j == i) ? 1 :
(f(i - 1, j - 1) + f(i - 1, j))
);
}
see explanation