I am just working on a recursive function to verify if a matrix is symmetric or not. The matrix must be square and I am considering max n = 20. I could develop the function:
int verifySymmetric(int m[20][20], int i, int j, int n) {
if (!((n == i) || (n == j))) {
if (m[i][j] != m[j][i]) {
return 0;
} else {
return (verifySymmetric(m, i + 1, j, n) && verifySymmetric(m, i, j + 1, n));
}
}
return 1;
}
Below is a code to run:
#include <stdio.h>
#include <stdlib.h>
int verifySymmetric(int m[20][20], int i, int j, int n) {
if (!((n == i) || (n == j))) {
if (m[i][j] != m[j][i]) {
return 0;
} else {
return (verifySymmetric(m, i + 1, j, n) && verifySymmetric(m, i, j + 1, n));
}
}
return 1;
}
int main() {
int n, r, c, m[20][20], t[20][20], flag, i, j;
i = j = 0;
printf("Enter matrix order >> ");
scanf("%d", &n);
printf("\nEnter the elements \n");
for (r = 0; r < n; r++) {
for (c = 0; c < n; c++) {
printf("m[%d][%d]: ", r + 1, c + 1);
scanf("%d", &m[r][c]);
}
}
for (r = 0; r < n; r++)
for (c = 0; c < n; c++)
t[c][r] = m[r][c];
flag = verifySymmetric(m, i, j, n);
if (flag == 1)
printf("Matrix is symmetric ");
if (flag == 0)
printf("Matrix is not symmetric ");
return 0;
}
My main concern is about the line
return (verifySymmetric(m, i + 1, j, n) && verifySymmetric(m, i, j + 1, n));
The program seem to work but I noticed that many m[row][column] is printed when I run the code. Something like this
Enter the elements
m[1][1]: m[1][2]: m[1][3]: m[1][4]: m[1][5]: m[1][6]: m[1][7]: m[1][8]: m[1][9]: m[1][10]: m[1]
[11]: m[1][12]: m[1][13]: m[1][14]: m[1][15]: m[1][16]: m[1][17]: m[1][18]: m[1][19]: m[1][20]:
m[1][21]: m[1][22]: m[1][23]: m[1][24]: m[1][25]: m[1][26]: m[1][27]: m[1][28]: m[1][29]: m[1]
[30]: m[1][31]: m[1][32]: m[1][33]: m[1][34]: m[1][35]: m[1][36]: m[1][37]: m[1][38]: m[1][39]:
m[1][40]: m[1][41]: m[1][42]: m[1][43]: m[1][44]: m[2][1]: m[2][2]: m[2][3]: m[2][4]: m[2][5]:
m[2][6]: m[2][7]: m[2][8]: m[2][9]: m[2][10]: m[2][11]: m[2][12]: m[2][13]: m[2][14]: m[2][15]:
m[2][16]: m[2][17]: m[2][18]: m[2][19]: m[2][20]: m[2][21]: m[2][22]: m[2][23]: m[2][24]:
What would be wrong with the function?
What would be another approach?
Edit
This is not a good approach, using recursion for a function like this, but I was curious about it and couldn't find an example in the internet. It is basically for learning purposes.
I am using Visual Studio Code and the strange behavior described above is when I click to Run Code two times. Running once, it runs as I expected, printing Enter matrix order >> , but once I click it for the second time without entering the matrix order, the misbehavior happens.
The code seems to work but it is very inefficient as the recursive approach will cause many redundant comparisons. The time complexity is O(n4) instead of O(n2)
You reason you get this misleading output is you prompt for each matrix value to stdout, but the input is read from a file and not echoed to stdout.
Here is a simpler non-recursive approach:
#include <stdio.h>
int verifySymmetric(int m[20][20], int n) {
for (int r = 0; r < n; r++) {
for (int c = 0; c < r; c++) {
if (m[r][c] != m[c][r])
return 0;
}
}
return 1;
}
int main() {
int n, m[20][20];
printf("Enter matrix order >> ");
if (scanf("%d", &n) != 1) {
printf("missing input\n");
return 1;
}
if (n < 1 || n > 20) {
printf("invalid dimension %d\n", n);
return 1;
}
printf("\nEnter the elements\n");
for (int r = 0; r < n; r++) {
for (int c = 0; c < n; c++)
if (scanf("%d", &m[r][c]) != 1) {
printf("missing input\n");
return 1;
}
}
}
if (verifySymmetric(m, n)) {
printf("Matrix is symmetric\n");
else
printf("Matrix is not symmetric\n");
return 0;
}
If for some reason the implementation is required to be recursive, here is a modified version without redundant comparisons:
int verifySymmetric(int m[20][20], int i, int j, int n) {
if (j == n) {
return 1;
} else
if (i < j) {
return (m[i][j] == m[j][i]) && verifySymmetric(m, i + 1, j, n);
} else {
return verifySymmetric(m, 0, j + 1, n);
}
}
Related
I want to find all the decompositions of a number using only odd numbers and up to N numbers max.
For example for the number 7 and N = 3, I can only get 1+1+5, 1+3+3, 7. I can't get 1+1+1+1+3 because it's greater then N.
They hint us to use backtracking.
I strated writing the code and I am stuck. If someone can explian to me how to solve this problem it will be great.
int T(int n, int k)
{
if (k == 0)
{
return;
}
int arr[N];
int f;
for (f = 0; f < N; f++)
{
arr[f] = 0;
}
int sum = 0;
int j = 1;
int i = 1;
int c = 0;
while (j < k) {
sum = sum + i;
arr[c] = i;
if (sum == n)
{
for (f = 0; f < N; f++)
{
if (arr[f] != 0)
{
printf("%d ", arr[f]);
}
}
printf("\n");
}
else if (sum > n)
{
arr[c] = 0;
sum = sum - i;
i = i - 2;
}
else
{
i = i + 2;
j++;
c++;
}
}
T(n, k - 1);
}
Please compile with warnings (-Wall) and fix all of them (-Werror helps make sure you do this). I didn't build your code, but int T(int n, int k) says it returns an int, yet the function code is void.
With backtracking, you can't print at each node because the current node in the graph might not actually lead to a solution. It's premature to commit anything to the result set until you actually reach it.
It's best not to print in functions that perform logical tasks anyway, but it can make the coding easier while developing the logic so I'll stick wiith it.
The backtracking suggestion is a good one. Here's the logic:
The "found result" base case is when n == 0 && k >= 0, if you're decrementing n and k and using them to represent the remaining value to reach the goal and the number of choices left. If you're incrementing variables to count up to n and k, that's fine too, in which case the base case is current_total == n && taken_so_far <= k.
Next, the "failure" base case is k < 0 || n < 0 because we've either overshot n or run out of numbers to take.
After that, the recursive case is, in English, "try taking each odd number i up to n, recursing on the possibility that i might be part of the solution". Per your spec, we don't accept any sequence of descending numbers which prunes the recursion tree a bit.
Here's the code; again, returning a result is an exercise. I'm using a k-sized array to store potential results, then dumping it to stdout only when a result was found.
#include <stdio.h>
#include <stdlib.h>
void odd_decomposition_search(
int n, const int k, int taken_length, int *taken
) {
if (n == 0 && taken_length <= k && taken_length > 0) {
for (int i = 0; i < taken_length - 1; i++) {
printf("%d+", taken[i]);
}
printf("%d\n", taken[taken_length-1]);
}
else if (n > 0 && taken_length < k) {
int i = taken_length ? taken[taken_length-1] : 1;
for (; i <= n; i += 2) {
taken[taken_length] = i;
odd_decomposition_search(n - i, k, taken_length + 1, taken);
}
}
}
void odd_decomposition(const int n, const int k) {
if (n <= 0 || k <= 0) {
return;
}
int taken[k];
odd_decomposition_search(n, k, 0, taken);
}
int main() {
int n = 7;
int k = 3;
odd_decomposition(n, k);
return 0;
}
If you're having trouble understanding the call stack, here's a visualizer you can run in the browser:
const oddDecomp = (n, k, taken=[]) => {
console.log(" ".repeat(taken.length), `[${taken}]`);
if (n === 0 && taken.length <= k && taken.length) {
console.log(" ".repeat(taken.length), "-> found result:", taken.join("+"));
}
else if (n > 0 && taken.length < k) {
for (let i = taken.length ? taken[taken.length-1] : 1; i <= n; i += 2) {
taken.push(i);
oddDecomp(n - i, k, taken);
taken.pop(i);
}
}
};
oddDecomp(7, 3);
The problem is to find the number of times a word occurs in a given N x N matrix of alphabets. We can move from any cell to other adjacent cell. The first line has one integer N and then a N x N matrix. Next line has M (size of the word) and then a string to be found in the matrix.
Input:
4
ABCD
ABCD
ABCD
ABCD
2
BC
Expected output:
10
I have written the following code for the same and used recursion for solving the problem. The function adj checks if the character is adjacent in the matrix with the previous character using their indexes. The function check increases the count whenever the string is completed. The 2-d array keeps a check on the visited and unvisited elements.
I am getting the output as
OUPUT
1
EDIT 1: This output is just because of the debugging print statement, so the if statement is being visited only once. It does not mean that the count variable is 1 after many recursion calls.
EDIT 2: There shouldn't be & in the scanf statement for word. But still the output is not the desired one.
EDIT 3:
Another input
7
SHELDON
HSTYUPQ
EHGXBAJ
LMNNQQI
DTYUIOP
OZXCVBN
NQWERTY
7
SHELDON
Expected output:
5
My output - 1
EDIT 4(Solved!): So the problem was in writing the no. of columns as 500 for the grid matrix, changing it to 5 did the job! Thanks to #gsamaras
Code
#include <stdio.h>
int vis[500][500], count;
int adj(int a, int b, int c, int d) {
if((c == a - 1) && (d == b - 1)) {
return 1;
}
else if((c == a - 1) && (d == b)) {
return 1;
}
else if((c == a) && (d == b - 1)) {
return 1;
}
else if((c == a - 1) && (d == b + 1)) {
return 1;
}
else if((c == a + 1) && (d == b)) {
return 1;
}
else if((c == a + 1) && (d == b + 1)) {
return 1;
}
else if((c == a) && (d == b + 1)) {
return 1;
}
else if((c == a + 1) && (d == b - 1)) {
return 1;
}
else {
return 0;
}
}
void check(char grid[][500],int i, int j, int id, char word[], int n, int m) {
if(id == m) {
count++;
printf("%d\n", count); // just to debug
}
else {
for(int p = 0; p < n; p++) {
for(int q = 0;q < n; q++) {
if((grid[p][q] == word[id]) && (adj(i, j, p, q)) && (vis[p][q] != 1)) {
vis[p][q] = 1;
check(grid, p, q, id + 1, word, n, m);
vis[p][q] = 0;
}
}
}
}
}
int main() {
int n, m, id = 0;
char blank;
scanf("%d", &n);
scanf("%c", &blank);
char grid[n][n+1];
for(int i = 0; i < n; i++) {
scanf("%s", grid[i]);
grid[i][n] = '\0';
}
scanf("%d", &m);
char word[m+1];
scanf("%s", &word);
for(int i = 0; i < n; i++) {
for(int j = 0;j < n; j++) {
if(grid[i][j] == word[id]) {
vis[i][j] = 1;
check(grid, i, j, id + 1, word, n, m);
vis[i][j] = 0;
}
}
}
printf("%d\n", count);
return 0;
}
Change this:
void check(char grid[][500], ......
to this:
void check(char grid[][5], ....... // that should be equal to N + 1 (5 in your case)
since your grid is of size N x N + 1. With the 500 as the dimension, you distorted the grid, and when trying to search into it recursively, you wouldn't traverse the grid that you would expect to traverse..
As you see this is not flexible, since N can vary. You cannot declare grid as global, since its dimensions are not fixed. Dynamic memory allocation should be used instead.
Change this:
scanf("%s", &word);
to this:
scanf("%s", word);
since word is an array of characters.
Complete example with Dynamic Memory Allocation:
#include <stdio.h>
#include <stdlib.h>
int vis[500][500], count;
char **get(int N, int M) { /* Allocate the array */
int i;
char **p;
p = malloc(N*sizeof(char *));
for(i = 0 ; i < N ; i++)
p[i] = malloc( M*sizeof(char) );
return p;
}
void free2Darray(char** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int adj(int a, int b, int c, int d) {
// Same as in your question
}
void check(char** grid, int i, int j, int id, char word[], int n, int m) {
if(id == m) {
count++;
printf("count = %d\n", count); // just to debug
}
else {
for(int p = 0; p < n; p++) {
for(int q = 0;q < 499; q++) {
//printf("p = %d, q = %d, id = %d, grid[p][q] = %c, word[id] = %c\n", p, q, id, grid[p][q], word[id]);
if((grid[p][q] == word[id]) && (adj(i, j, p, q)) && (vis[p][q] != 1)) {
vis[p][q] = 1;
check(grid, p, q, id + 1, word, n, m);
vis[p][q] = 0;
}
}
}
}
}
int main() {
int n, m, id = 0;
char blank;
scanf("%d", &n);
scanf("%c", &blank);
char** grid = get(n, n + 1);
for(int i = 0; i < n; i++) {
scanf("%s", grid[i]);
grid[i][n] = '\0';
}
scanf("%d", &m);
char word[m+1];
scanf("%s", word);
for(int i = 0; i < n; i++) {
for(int j = 0;j < n; j++) {
//printf("i = %d, j = %d, id = %d\n", i, j, id);
if(grid[i][j] == word[id]) {
vis[i][j] = 1;
check(grid, i, j, id + 1, word, n, m);
vis[i][j] = 0;
}
}
}
printf("%d\n", count);
free2Darray(grid, n);
return 0;
}
Output (for your 1st input):
count = 1
count = 2
count = 3
count = 4
count = 5
count = 6
count = 7
count = 8
count = 9
count = 10
10
PS: Not a problem, just a suggestion about readability: count is initialized to 0, because it's a global variable, but it's always best to explicitly initialize your variables, when it matters.
I need to find the sum of all numbers that are less or equal with my input number (it requires them to be palindromic in both radix 10 and 2). Here is my code:
#include <stdio.h>
#include <stdlib.h>
int pal10(int n) {
int reverse, x;
x = n;
while (n != 0) {
reverse = reverse * 10 + n % 10;
n = n / 10;
}
if (reverse == x)
return 1;
else
return 0;
}
int length(int n) {
int l = 0;
while (n != 0) {
n = n / 2;
l++;
}
return l;
}
int binarypal(int n) {
int v[length(n)], i = 0, j = length(n);
while (n != 0) {
v[i] = n % 2;
n = n / 2;
i++;
}
for (i = 0; i <= length(n); i++) {
if (v[i] == v[j]) {
j--;
} else {
break;
return 0;
}
}
return 1;
}
int main() {
long s = 0;
int n;
printf("Input your number \n");
scanf("%d", &n);
while (n != 0) {
if (binarypal(n) == 1 && pal10(n) == 1)
s = s + n;
n--;
}
printf("Your sum is %ld", s);
return 0;
}
It always returns 0. My guess is I've done something wrong in the binarypal function. What should I do?
You have multiple problems:
function pal10() fails because reverse is not initialized.
function binarypal() is too complicated, you should use the same method as pal10().
you should avoid comparing boolean function return values with 1, the convention in C is to return 0 for false and non zero for true.
you should avoid using l for a variable name as it looks very similar to 1 on most constant width fonts. As a matter of fact, it is the same glyph for the original Courier typewriter font.
Here is a simplified and corrected version with a multi-base function:
#include <stdio.h>
#include <stdlib.h>
int ispal(int n, int base) {
int reverse = 0, x = n;
while (n > 0) {
reverse = reverse * base + n % base;
n = n / base;
}
return reverse == x;
}
int main(void) {
long s = 0;
int n = 0;
printf("Input your number:\n");
scanf("%d", &n);
while (n > 0) {
if (ispal(n, 10) && ispal(n, 2))
s += n;
n--;
}
printf("Your sum is %ld\n", s);
return 0;
}
in the function pal10 the variable reverse is not initialized.
int pal10(int n)
{
int reverse,x;
^^^^^^^
x=n;
while(n!=0)
{
reverse=reverse*10+n%10;
n=n/10;
}
if(reverse==x)
return 1;
else
return 0;
}
In the function binarypal this loop is incorrect because the valid range of indices of an array with length( n ) elements is [0, length( n ) - 1 ]
for(i=0;i<=length(n);i++)
{
if(v[i]==v[j])
{
j--;
}
else
{
break;
return 0;
}
}
And as #BLUEPIXY pointed out you shall remove the break statement from this else
else
{
break;
return 0;
}
I am try to write a A recursive implementation, but it dont work. Can you help me to find mistake. I need just a recursive solution on C.
void findsum(int arr[],int i, int k){
if (k <= 0 || arr[i] > k) return;
if (arr[i] <= k) {
k -= arr[i];
if (k == 0) {
NSLog(#"Summ %d, %d",arr[i], arr[i]); return;
}
}
if (i == (25)) return;
for (int a=i ;a<25; a ++ ) {
findsum(arr, a, k);
}
}
int main()
{
int set[] = {18897109, 12828837, 9461105, 6371773, 5965343, 5946800, 5582170, 5564635, 5268860, 4552402, 4335391, 4296250, 4224851, 4192887, 3439809, 3279833, 3095313, 2812896, 2783243, 2710489, 2543482, 2356285, 2226009, 2149127, 2142508, 2134411};
int sum = 100000000;
int n = sizeof(set)/sizeof(set[0]);
for (int i = 0; i < n; i++) {
findsum(set, i, sum);
}
}
You code not stop because every time you assign i=0 by loop
for (i = 0 ;i<26; i ++ ) {
findsum(arr, i, k);
}
In findsum function.
So as per my suggestion you can make some changes as like
first in main
int main()
{
int set[] = {18897109, 12828837, 9461105, 6371773, 5965343, 5946800, 5582170, 5564635, 5268860, 4552402, 4335391, 4296250, 4224851, 4192887, 3439809, 3279833, 3095313, 2812896, 2783243, 2710489, 2543482, 2356285, 2226009, 2149127, 2142508, 2134411};
int sum = 100000000,i;
int n = sizeof(set)/sizeof(set[0]);
findsum(set, n, sum);
}
And second in findsum like
void findsum(int arr[],int i, int k)
{
if (k <= 0 || arr[i] > k) return;
if (arr[i] <= k)
{
k -= arr[i];
if (k == 0) {
NSLog(#"Summ %d, %d",arr[i], arr[i]); return;
}
}
if (i == 25) return;
findsum(arr, i, k);
}
I've been doing a few of the challenges on the Sphere Online Judge (SPOJ), but I can't seem to get the second problem (the prime generator) to run within the time limit. How can the speed of the following code be increased?
#include <stdio.h>
#include <math.h>
int is_prime(int n);
void make_sieve();
void fast_prime(int n);
int primes[16000];
int main()
{
int nlines;
int m, n;
make_sieve();
scanf("%d", &nlines);
for (; nlines >= 1; nlines--) {
scanf("%d %d", &m, &n);
if (!(m % 2)) {
m++;
}
for ( ; m < n; m+=2) {
fast_prime(m);
}
printf("\n");
}
return 0;
}
/* Prints a number if it's prime. */
inline void fast_prime(int n)
{
int j;
for (int i = 0; ((j = primes[i]) > -1); i++) {
if (!(n % j)) {
return;
}
}
printf("%d\n", n);
}
/* Create an array listing prime numbers. */
void make_sieve()
{
int j = 0;
for (int i = 0; i < 16000; i++) {
primes[i] = -1;
}
for (int i = 2; i < 32000; i++) {
if (i % 2) {
if (is_prime(i)) {
primes[j] = i;
j++;
}
}
}
return;
}
/* Test if a number is prime. Return 1 if prime. Return 0 if not. */
int is_prime(int n)
{
int rootofn;
rootofn = sqrt(n);
if ((n <= 2) || (n == 3) || (n == 5) || (n == 7)) {
return 1;
}
if (((n % 2) == 0) || ((n % 3) == 0) || ((n % 5) == 0) || ((n % 7) == 0)) {
return 0;
}
for (int i = 11; i < rootofn; i += 2) {
if ((n % i) == 0) {
return 0;
}
}
return 1;
}
isprime() does not make use of the prime number table primes[].
Plus, implement a search of the primes array that will complete quickly using a binary search algorithm. The standard library has one.
To see where your time is spent in code you can use profiling
gcc example
gcc -p -g - o mycode mycode.c
===run the code--
gprof mycode
Currently, your problem isn't time limit. Its the fact that your program never print any numbers.
The most obvious error is that in fast_prime you are checking if n is divisible by prime[0], prime[1],... up to prime[k]. Even if n is prime, you won't print it, because n is somewhere in primes[], and so you'll get that n is divisible by some number...
To correct this, you need to check that n is divisible by some prime number up to the square root of n (this will also have the side effect of speeding up the code, as less numbers will be checked before deciding some number is a prime)
change fast_prime to
inline void fast_prime(int n)
{
int j;
int rootofn;
rootofn = sqrt(n);
for (int i = 0; ((j = primes[i]) > -1) && (j<rootofn); i++) {
if (!(n % j)) {
return;
}
}
printf("%d\n", n);
}