Trying to find the smallest number in a 2D array using recursion - c++

I'm trying to find the smallest number in a 2D (pointer to pointer) array using recursion, here is the code so far:
int smallest(int **arr, int row_size, int column_size)
{
if (row_size == 0 && column_size == 0)
{
return *(*(arr + 0) + 0);
}
row_size--;
column_size--;
if ((*(*(arr + 0) + 0)) < (*(*arr + row_size) + column_size))
{
return smallest(arr, row_size, column_size);
}
else
{
*(*(arr + 0) + 0) = *(*(arr + row_size) + column_size);
return smallest(arr, row_size, column_size);
}
}
This works but has 2 drawbacks:
1- Only processes square arrays.
2- Only processes indexes where row & column numbers are the same (such as 1,1 2,2 & 3,3 etc.)
I'm trying to make it process non-square arrays as well but that would require decrementing rows and column numbers at different times, I'm not sure how to go about that. Any clues?

Bored professionals overkill introductory problems, volume 3! This version:
Uses a secondary function to traverse each row (that might be off-limits of the question's rules, but you can combine them and switch on whether the pointers array has only one row)
Works with empty arrays (and returns the maximal value of an int)
Does not use index notation
Is purely recursive
int smallest(int const * const array, int const length) {
return length == 0
? std::numeric_limits<int>::max()
: std::min(*array, smallest(array + 1, length - 1));
}
int smallest(int const * const * const array, int const rows, int const columns) {
return rows == 0
? std::numeric_limits<int>::max()
: std::min(
smallest(*array, columns), // Minimum from the current row
smallest(array + 1, rows - 1, columns) // Minimum from the rest of the rows
);
}
See it live on Coliru

not tested, but I think it would work.
#include <algorithm>
#include <limits>
//call with row = row_size-1, column = column_size -1
int smallest(int **arr, int row, int column)
{
if( row<0 || column<0 )return std::numeric_limits<int>::max();
return std::min( {arr[row][column], smallest(arr,row-1,column), smallest(arr,row,column-1)} );
}
The recursion is

Assumed requirements:
Cannot modify function signature (can be simpler if this is not the case)
Can only have a single function (ditto)
Must be purely recursive (i.e. no loops)
Must use pointer dereferencing (*(arr + 1) instead of arr[1])
Procedure:
Recurse through the first row only (setting rows to 1)
Recurse through all other rows (decrement rows)
Code:
int smallest(int **arr, int rows, int columns)
{
// invalid input
if (rows <= 0 || columns <= 0)
return INT_MAX;
// top-left element
int m = **arr;
// single row recursion
if (rows == 1) {
*arr++; // increment the temporary pointer from below
return min(m, smallest(arr, 1, columns - 1));
}
// create a temporary pointer to the first row
// and start recursion in this single row
int* row = *arr;
m = min(m, smallest(&row, 1, columns));
// rest of array
return min(m, smallest(arr + 1, rows, columns - 1));
}
EDIT: since you are allowed to modify the function signature, you can add an extra index for looping through each row; this removes the need for that extra temporary pointer.
int smallest(int **arr, int rows, int columns, int column_index = 0)
{
// invalid input
if (rows <= 0 || column_index >= columns)
return INT_MAX;
// single row recursion
if (rows == 1)
return min(*(*arr + column_index), // first element of row
smallest(arr, 1, columns - 1,
column_index + 1)); // rest of row
// rest of array
return min(smallest(arr, 1, columns), // start on first row
smallest(arr + 1, rows - 1, columns));
}
Note that external call signatures can still be the same as before due to the default argument value.

You'll need to pass the matrix bounds to the function so you can "move" in one dimension when you reach the end of the other.
Something like this (I find it more natural to count upwards than downwards):
int smallest(int **arr, int row, int column, int row_last, int column_last)
{
if (row == row_last && column == column_last)
{
return arr[row][column];
}
else if (column == column_last)
{
return min(arr[row][column], smallest(arr, row+1, 0, row_last, column_last));
}
else
{
return min(arr[row][column], smallest(arr, row, column+1, row_last, column_last));
}
}
(This is one of those exercises that introduces potentially useful concepts in a situation where they don't serve any purpose. It's not a good use of either recursion or pointer arithmetic.)

Though you can get away without recursion, if this is a purely learning excercise for recursion you could try DFS approach.
Have an entry point to start your search (i,j), from each point exhaust all possible areas you could go, (i+1,j)(i-1,j)(i,j+1)(i,j-1). Each recursion step would also check if you are in within the limits of the array which would be i < 0 || i >= rows || j < 0 || j >= cols || visited[i][j] you would just return at this point.
Notice the visited array. So at each point in the recursion there could be a chance that you return back to the same cell right? that would make it an infinite recrusion to avoid this, you track which cells you have already visited, visited[i][j]. Mark them. Each recrusion call keep track of the minimum element recorded by reference, which will be your minimum element.
void findMinElement(vector<vector<int>>& array, int& minelement, int i, int j, vector<vector<bool>>& visited)
{
if(i < 0 || i >= array.size() || j < 0 || j >= array[0].size() || visited[i][j]) return;
minelement = min(minelement,array[i][j]); // is this the best minimum?
visited[i][j] = true; // done visiting this cell
//lets visits others
findMinElement(array, minelement, i+1, j, visited);
findMinElement(array, minelement, i-1, j, visited);
findMinElement(array, minelement, i, j+1, visited);
findMinElement(array, minelement, i, j-1, visited);
}
int main()
{
vector<vector<int>> array =
{
{9,8,6,4},
{13,4,6,11},
{3,8,3,100}
};
int minElement = INT32_MAX;
//same dimensions as array
vector<vector<bool>> visited(array.size(), vector<bool>(array[0].size(),false));
//start from (0,0)
findMinElement(array,minElement,0,0,visited);
cout << minElement;
}
This now gives you the flexibility to start searching from any location in the array as well. It might be a bit to take in, but it will help you with many problems further down the line.

I couldn't help myself. This is an implementation that will divide the input array into four smaller arrays and calls iself on them (unless they are zero size):
int smallest(int **arr, int row_begin, int row_end, int column_begin, int column_end)
{
if (row_end - row_begin == 1 && column_end - column_begin == 1) return *(*(arr + row_begin) + column_begin);
int row_mid = (row_begin + row_end) / 2;
int column_mid = (column_begin + column_end) / 2;
int minimum = smallest(arr, row_mid, row_end, column_mid, column_end);
if (column_mid > column_begin) {
int m = smallest(arr, row_mid, row_end, column_begin, column_mid);
if (m < minimum) minimum = m;
}
if (row_mid > row_begin) {
int m = smallest(arr, row_begin, row_mid, column_begin, column_end);
if (m < minimum) minimum = m;
}
if (column_mid > column_begin && row_mid > row_begin) {
int m = smallest(arr, row_begin, row_mid, column_begin, column_mid);
if (m < minimum) minimum = m;
}
return minimum;
}
Call it like this:
cout << smallest(test_array, 0, rows, 0, columns);

I would do something like:
int smallest(int **arr, int row_size, int column_size)
{
if (row_size > 0 && column_size > 0)
{
int minRow = arr[0][0];
for (int j = 0; j < row_size; ++j)
{
const int *row = arr[j];
minRow = std::min(minRow, *std::min_element(row, row + column_size));
}
return minRow;
}
else return INT_MAX;
}

Related

couldn't find the determinant of n*n matrix

I have written the following code to calculate the determinant of a N*N matrix. it works perfectly for the matrix 4*4 and 5*5. but it could not find the determinant of the 40*40 matrix named Z_z. The elements of matrix Z_z are presented herein.
#include <iostream>
int const N_M=40;
void getCofactor(double A[N_M][N_M], double A_rc[N_M][N_M], int r,int c, int n)
{ int i = 0, j = 0;
// Looping for each element of the matrix
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
// Copying into temporary matrix only those element
// which are not in given row and column
if (row != r && col != c)
{
A_rc[i][j] = A[row][col];
j=j+1;
// Row is filled, so increase row index and
// reset col index
if (j == n - 1)
{
j = 0;
i=i+1;
}
}
}
}
}
double determinant(double A[N_M][N_M], int n)
{ double D = 0.0; // Initialize result
// Base case : if matrix contains single element
if (n==1) return A[0][0];
else if (n == 2) return (A[0][0]*A[1][1])-(A[0][1]*A[1][0]);
else {
double sub_Matrix_A_0c[N_M][N_M]; // To store cofactors
// Iterate for each element of first row
for (int c = 0; c < n; c++)
{
// Getting Cofactor of A[0][f]
getCofactor(A, sub_Matrix_A_0c, 0, c, n);
D += pow(-1.0,c) * A[0][c] * determinant(sub_Matrix_A_0c, n - 1);
}
return D;}
}
int main () {
double Z_z[N_M][N_M]=
{{-64,16,-4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{-43.7213019529827,12.4106746539480,-3.52287874528034,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,-43.7213019529827,12.4106746539480,-3.52287874528034,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,-27,9,-3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,-27,9,-3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,-16.0579142269798,6.36491716338729,-2.52287874528034,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,-16.0579142269798,6.36491716338729,-2.52287874528034,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,-8,4,-2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-8,4,-2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3.53179897265895,2.31915967282662,-1.52287874528034,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3.53179897265895,2.31915967282662,-1.52287874528034,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,1,-1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,1,-1,1,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0.142956190020121,0.273402182265940,-0.522878745280338,1,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0.142956190020121,0.273402182265940,-0.522878745280338,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.20222621658426,1.69267904961742,1.30102999566398,1},
{37.2320239618439,-7.04575749056068,1,0,-37.2320239618439,7.04575749056068,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,27,-6,1,0,-27,6,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,19.0947514901619,-5.04575749056068,1,0,-19.0947514901619,5.04575749056068,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,12,-4,1,0,-12,4,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.95747901847985,-3.04575749056068,1,0,-6.95747901847985,3.04575749056068,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,-2,1,0,-3,2,-1,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.820206546797821,-1.04575749056068,1,0,-0.820206546797821,1.04575749056068,-1,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,-1,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,2,1,0,-3,-2,-1,0},
{-21.1372724716820,2,0,0,21.1372724716820,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,-18,2,0,0,18,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,-15.1372724716820,2,0,0,15.1372724716820,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,-12,2,0,0,12,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-9.13727247168203,2,0,0,9.13727247168203,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-6,2,0,0,6,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-3.13727247168203,2,0,0,3.13727247168203,-2,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,-2,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,2,0,0,-6,-2,0,0},
{24,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-7.80617997398389,-2,0,0}};
double det=determinant(Z_z, 40);
cout<<det;
system ("pause");
return 0;}
You recursively call determinant() functuon n times at the first stage, then n - 1 times for each of n calls, etc. So total number of call would be closed to n! (factorial).
When n = 4 or n = 5 the number of calls is still acceptable, but at n = 40 you try to make 40! = 815915283247897734345611269596115894272000000000 virtual calls to say nothing about so many operations of any kind. I don't think you can find a machine to handle that.

Recursive length of largest ascending consecutive subarray (C++)

I have an assignment in the university to write a recursive function in C++ that finds the length of the longest ascending consecutive sub array of an array or integers. In addition, I have a code skeleton that I must use for my code and the function must not contain loops & more function.
For example, for the array 1,2,4,6,4,21,21,22,0,1,3,5,100,7
The result will be 5 (because 0 to 100 are 5 numbers).
The skeleton is:
#include <stdio.h>
#define MAX_SIZE 1000
int get_max_series(int a[], int size);
int main() {
int i, size_array, array[MAX_SIZE];
scanf("%d", &size_array);
for (i = 0; i < size_array; i++)
scanf("%d", &array[i]);
printf("%d", get_max_series(array, size_array));
return 0;
}
int get_max_series(int a[], int size) {
// My code should be here
}
I've succeeded to write a function that counts the number of ascending pairs, but failed in reseting the counter when the pair is descending. The code is below:
#include <stdio.h>
#define MAX_SIZE 1000
int get_max_series(int a[], int size);
int main() {
int i, size_array, array[MAX_SIZE];
scanf("%d", &size_array);
for (i = 0; i < size_array; i++)
scanf("%d", &array[i]);
printf("%d", get_max_series(array, size_array));
return 0;
}
int get_max_series(int a[], int size) {
if (size == 1)
return 1;
if (a[0] < a[1])
return 1 + get_max_series(&a[1], size - 1);
return get_max_series(&a[1], size - 1);
}
I'll be happy to get some advice how to get my code work for this scenario, or change the code entirely.
Thanks !
If you don't want to use static/global variables, or a helper function, you can use the following reduction for an array of size > 1 (it will be slow, though, since it does two recursive calls):
If a[0]>=a[1] then we cannot have a[0] in the maximal ascending subarray since it violates our notion of ascendancy so we return get_max_series(a+1, size - 1) like you have on your code.
When a[0]<a[1] we have two cases:
If get_max_series(a+1,size-1)==size-1, then the whole subarray a[1],...,a[size-1] is ascending. This implies a[0],a[1],...,a[size-1] is also ascending so we can return 1 + get_max_series(&a[1], size-1) in this case.
HOWEVER if get_max_series(a+1,size-1)!=size-1 that means that the subarray a[1],...,a[size-1] isn't ascending, so the maximal subarray cannot contain both a[1] and a[size-1] (by contiguity it would have to include everything in between, which would make it non-ascending).
Therefore, you return max(1+get_max_series(&a[0], size-1), get_max_series(&a[1], size-1)).
NOTE that here you do two calls to get_max_series, so your computational cost quickly grows(basically the same inefficiencies that appear when you do the naive recursive implementation of the fibonacci function).
The function would be something like
int get_max_series(int a[], int size) {
if (size <= 1)
return size;
int max_sub = get_max_series(&a[1], size - 1);
if (a[0] >= a[1])
return max_sub;
else{
if (max_sub==(size-1))
return size;
else
return std::max(get_max_series(&a[0], size-1), max_sub);
}
}
I'm using std::max here, but if you don't want to use the algorithm library you can find the maximum of two numbers using if-else.
Here's an O(n) routine that seems to follow your rules (the variable names should help explain what's going on):
#include <stdio.h>
#define MAX_SIZE 1000
int get_max_series(int a[], int size);
int main() {
int i, size_array, array[MAX_SIZE];
scanf("%d", &size_array);
for (i = 0; i < size_array; i++)
scanf("%d", &array[i]);
printf("%d", get_max_series(array, size_array));
return 0;
}
int get_max_series(int a[], int size) {
int i = size - 1;
if (i < 2){
if (a[1] > a[0])
return a[0] = 2;
else
return a[0] = 1;
}
int max = get_max_series(a, i);
int max_up_to_i = a[i - 2];
if (a[i] > a[i - 1]){
a[i - 1] = 1 + max_up_to_i;
if (a[i - 1] > max)
max = a[i - 1];
} else {
a[i - 1] = 1;
}
return max;
}
The longest ascending subarray does not necessarily start at the beginning of the array. Therefore,
return 1 + get_max_series(&a[1], size - 1);
is incorrect. I don't see how you can salvage the approach relying on inspecting just one character, at least within a given signature. Consider finding the longest ascending sequence at the beginning of the array, then recursing into the rest, along the lines of:
int get_max_series(int a[], int size)
{
int n = get_longest_acsending_prefix(a, size);
if (n == size)
return n;
return max(n, get_longest_ascending_prefix(a + n, size - n));
}
That said, I don't see a point of recursion here.

Equality test function

Below is a function which aims to perform an equality test between adjacent numbers in a one dimensional vector.
This 1D vector will have values which will represent an nxn grid. [ v is the vector]
When they are equal it returns false.
For example consider this 3x3 grid:
i\j| 0 | 1 | 2
0 | 1 | 2 | 3
1 | 4 | 5 | 6
2 | 7 | 8 | 9
The issue with the code I wrote is that not all of the numbers in the grid will have 4 other adjacent numbers and testing for indexes which don't exist e.g when trying to compare the number above the top left number in the grid (1 in the example) might lead to some inaccurate outcomes.
In addition to this what I wrote seems not to be the most efficient way to go about it. Surely there could be a simpler way to do this than having to list 5 new variables?
for( int i= 0; i < n ; i++ ){
for( int j = 0; j < n; j++){
int x = v[convert(i, j, n)];
int c = v[convert(i-1, j, n)];
int s = v[convert(i+1, j, n)];
int b = v[convert(i, j+1, n)];
int n = v[convert(i, j-1, n)];
if (x == c || x == s || x == b || x == n ) {
return false;
}
}
}
//another function used to convert 2d into 1D index
int convert(int row, int col, int rowlen){
return row*rowlen+col;
}
I would appreciate any help.
If you want an efficient way to do this, you should consider the cache locality of your values, how much index conversion you do, how many bounds tests you do, and how many comparisons are needed.
First thing to note is that you do not need to compare to the left and above when you're already comparing to the right and below. This is because the left/up test will happen when testing to the right/down on the next iteration. So immediately, that halves the amount of testing.
A first optimization would be to split the operation into row tests and column tests:
// Test adjacency in rows
for (const int *rowptr = v, *end = v + n * n;
rowptr != end;
rowptr += n)
{
for (int col = 1; col < n; col++) {
if (rowptr[col-1] == rowptr[col]) return false;
}
}
// Test adjacency in columns
for (const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n;
row1ptr != end;
row0ptr = row1ptr, row1ptr += n)
{
for (int col = 0; col < n; col++) {
if (row0ptr[col] == row1ptr[col]) return false;
}
}
To avoid making two passes through the entire array, you'd need to combine these, but it starts getting a bit messy. Notice how the two separate passes currently have different bounds (the row-tests loop from column 1 to n, whereas the column tests loop from row 0 to n-1).
Combining the loops would only make sense if n is quite large and if it's absolutely critical that this piece of code is fast. The idea is to perform a single pass through the entire array, avoiding any issues with stuff like L1 cache misses on the second pass.
It would look something like this:
const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n
for ( ; row1ptr != end; row0ptr = row1ptr, row1ptr += n)
{
// Test first column
if (row0ptr[0] == row1ptr[0]) return false;
// Test row0 and remaining columns
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
if (row0ptr[col] == row1ptr[col]) return false;
}
}
// Test last row
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
}
First I'd recommend breaking up the logic because it's getting quite convoluted. But something like this works, it avoids going outside the grid by adding extra checks on i and j and it may avoid unnecessary calls to convert since if one of the earlier tests is true the later tests aren't performed.
int x = v[convert(i, j, n)];
if (i > 0 && x == v[convert(i-1, j, n)])
return false;
if (i < n - 1 && x == v[convert(i+1, j, n)])
return false;
if (j > 0 && x == v[convert(i, j-1, n)])
return false;
if (j < n - 1 && x == v[convert(i, j+1, n)])
return false;

Understanding diagonal search of 8 queen puzzle

I was solving the 8 queen problem and tried to look through the internet for comparison solutions to see how my solutions compared to others. I found one very small brute force solution that confused me. And I was wondering if anyone care to explain how the diagonal comparison actually works?
void solve(int n, int col, int *hist)
{
int i;
int j;
if (col == n)
{
print_solution(n, hist);
}
i = 0;
while (i < n)
{
j = 0;
while (j < col && !(hist[j] == i || abs(hist[j] - i) == col - j))
j++;
if (j < col)
{
i++;
continue;
}
hist[col] = i;
solve(n, col + 1, hist);
i++;
}
}
void main(void)
{
int hist[8];
solve(8, 0, hist);
}
The code in particular I have problem visualizing is:
abs(hist[j] - i) == col - j)
From what I understand it checks the diagonals but I don't see it.
Since the first loop condition is j < col, the right hand side of this condition is positive. i corresponds to the current row being checked, and hist[j] is the row of the queen on the j-th column. Thus this checks if the two points (hist[j], j) and (i, col) lie on either a "forward-slash" ( / ) or "back-slash" ( \ ), diagonal, by checking if the horizontal and vertical distances are equal. The abs is to allow both cases to be checked in one go.

Is tail recursion possible if a comparison depends on the return value?

I had a homework assignment that asked for a function that uses direct recursion to find the index of the left-most, lowest, negative integer in an array. Additional requirements were for the parameters of the function to be the array and the size and that the return value for no valid value was -999.
I came up with this:
int LowIndexMinNeg(int src[], int size)
{
if (size == 0)
return -999;
int index = LowIndexMinNeg(src, size - 1);
if (index >= 0)
return (src[size - 1] < src[index]) ? (size - 1) : index;
else
return (src[size - 1] < 0) ? (size - 1) : index;
}
It works, satisfies the requirements, and got me full credit. Can this be implemented with tail recursion?
It seems to me that since you have to take the result from the recursive call to use in a comparison to decide if you pass that one on or update it that it wouldn't be possible but recursion still ties my brain in knots a it so there might be something obvious that I'm missing.
Note: My homework assignment was already turned in and graded.
If you transform the result of recursion before returning, it is not tail recursive.
EDIT: Having said that, if you want to make the function tail recursive:
const int SENTINEL= 0;
int LowIndexMinNeg(int src[], int size, int index)
{
if (size == 0)
{
if (index<0 || src[index]>=0)
return -999;
else
return index;
}
int current_index= size - 1;
int new_index= src[current_index]<=src[index] ? current_index : index;
return LowIndexMinNeg(src, size - 1, new_index);
}
And call as LowIndexMinNeg(src, src_size, src_size - 1)
EDIT2: finding the poorly termed leftmost most negative value. You can probably state that as the index of the first most negative value.
EDIT3: removing most of the conditionals, since it's easier to find the index of the lowest value, then check if it's negative.
You need to store the lowest number found so far somewhere. With your function you're using the stack
to store that.
With a tail recursive function you'll need to store the lowest number found so far elsewhere.
e.g:
As a global variable (ugh..).
As a parameter to the function itself.
As a member variable
The requirement you have for your function probably rules out all those, so you're left with something like the code you have, which cannot be written to be tail-recursive.
To get an idea of e.g. the 2 last point:
int LowIndexMinNeg(int src[], int size,int current_lowest = 0,int lowest_index = 0) {
if(size == 0)
return current_lowest == 0 ? -999 : lowest_index;
int val = src[size - 1] ;
if(val < 0 && val < current_lowest) {
current_lowest = val;
lowest_index = size -1;
}
return LowIndexMin(src,size - 1,current_lowest,lowest_index);
}
And
struct find_smallest {
int current_lowest = 0;
int lowest_index = 0
int LowIndexMinNeg(int src[], int size) {
if(size == 0)
return current_lowest == 0 ? -999 : lowest_index;
int val = src[size - 1] ;
if(val < 0 && val < current_lowest) {
current_lowest = val;
lowest_index = size - 1;
}
return LowIndexMin(src,size - 1);
}
};
Here's how you might implement that using tail recursion:
int LowIndexMinNeg(int src[], int size, int index = 0, int lowest_index = -999, int lowest_value = 0)
{
if (index >= size) {
return lowest_index;
}
if (src[index] < lowest_value) {
return LowIndexMinNeg(src, size, index+1, index, src[index]);
} else {
return LowIndexMinNeg(src, size, index+1, lowest_index, lowest_value);
}
}
This implementation uses default arguments to keep the function all together, but this makes for a messy interface. You can split this into two functions if you like:
static int LowIndexMinNegHelper(int src[], int size, int index, int lowest_index, int lowest_value)
{
if (index >= size) {
return lowest_index;
}
if (src[index] < lowest_value) {
return LowIndexMinNegHelper(src, size, index+1, index, src[index]);
} else {
return LowIndexMinNegHelper(src, size, index+1, lowest_index, lowest_value);
}
}
int LowIndexMinNeg(int src[], int size)
{
return LowIndexMinNegHelper(src, size, 0, -999, 0);
}
In this case, LowIndexMinNegHelper only needs to be a local function (which I've indicated with static above).
I might have a proposal, but of course I had to change the signature :
int LowIndexMinNeg(int src[], int size, int min = -999)
{
if (size == 0)
return min;
const int min_value = (min == -999) ? 0 : src[min];
return LowIndexMinNeg(src, size - 1, src[size - 1] <= min_value ? size - 1 : min);
}
I'm not sure whether the rules for the assignment would have permitted defining an auxiliary function, but that is one standard transformation for achieving tail recursion when the most natural signature of the operation does not permit it. For example:
int LowIndexMinNeg2(int src[], int size, int min)
{
if (size == 0) return min;
src--; size--;
if (min >= 0) min++;
if (src[0] < 0
&& (min < 0 || src[0] <= src[min]))
min = 0;
return LowIndexMinNeg2(src, size, min);
}
int LowIndexMinNeg2(int src[], int size)
{
return LowIndexMinNeg2(src + size, size, -999);
}
This version also reverses the order of traversal to make it possible to distinguish a "real" value of 'min' from the 'not found' value. Other, likely more readable, approaches would involve making use of additional accumulators for the actual minimum value (instead of only an index) and/or the current offset into the array (so that traversal can be done in "normal" order. But of course if I were coding something like this for serious use I wouldn't be using recursion in the first place.
You could do this with two statics...
int LowIndexMinNeg(int src[], int size)
{
static int _min = 0;
static int _index = 0;
if (size == 0) return -999;
if (_index == size) return (src[_min] < 0) ? _min : -999;
if (src[_index] < 0 && src[_index] < src[_min]) _min = _index;
++_index;
return LowIndexMinNeg(src, size);
}