Finding if two arrays have common numbers using recursion - c

The question goes like this:
write a recursive function that gets two positive int arrays and their sizes.
The function returns 0 if there is at least one common object and 1 if there isn't.
int disjoint(int a[], int n1, int b[], int n2)
The requirements are as follows:
no helper functions
no loops
no changing the array
only recursion
I am currently having problems in getting all the combinations for comparison, in other words how to translate nested loops to recursion.
update
this one works but it makes unnecessary iterations.
int disjoint(int g1[], int n1 , int g2[], int n2 ){
if(g1[0]==g2[0])return 0;
if(n2-1>0&&n1-1>=0){
return disjoint(g1+1,n1-1,g2,n2)*disjoint(g1,n1,g2+1,n2-1);
}
return 1;
}

I'm not solving it for you but...
Using pseudo-annotation: The arrays a[0..n] and b[0..m] are disjoint if a[0] != b[0] and if a[1..n] and b[0..m] are disjoint and a[0..n] and b[1..m] are disjoint.
I think I got that right...
Ok, another hint: One of the recursive calls might look like disjoint(a + 1, n1 - 1, b, n2)
When doing recursion, it's (at least for me) better to look at the problem and formulate the solution in terms of the problem itself, rather than writing an iterative solution and then trying to "translate" it.

Related

Finding no. of shifts in Insertion sort for large inputs in C

I'm trying to write a program that counts the number of swaps made by insertion sort. My program works on small inputs, but produces the wrong answer on large inputs. I'm also not sure how to use the long int type.
This problem came up in a setting described at https://drive.google.com/file/d/0BxOMrMV58jtmNF9EcUNQNGpreDQ/edit?usp=sharing
Input is given as
The first line contains the number of test cases T. T test cases follow.
The first line for each case contains N, the number of elements to be sorted.
The next line contains N integers a[1],a[2]...,a[N].
Code I used is
#include <stdio.h>
#include <stdlib.h>
int insertionSort(int ar_size,int * ar)
{
int i,j,t,temp,count;
count=0;
int n=ar_size;
for(i=0;i<n-1;i++)
{
j=i;
while(ar[j+1]<ar[j])
{
temp=ar[j+1];
ar[j+1]=ar[j];
ar[j]=temp;
j--;
count++;
}
}
return count;
}
int main()
{
int _ar_size,tc,i,_ar_i;
scanf("%d", &tc);
int sum=0;
for(i=0;i<tc;i++)
{
scanf("%d", &_ar_size);
int *_ar;
_ar=(int *)malloc(sizeof(int)*_ar_size);
for(_ar_i = 0; _ar_i < _ar_size; _ar_i++)
{
scanf("%d", &_ar[_ar_i]);
}
sum=insertionSort(_ar_size, _ar);
printf("%d\n",sum);
}
return 0;
}
There are two issues that I currently see with the solution you have.
First, there's an issue brought up in the comments about integer overflow. On most systems, the int type can hold numbers up through 231 - 1. In insertion sort, the number of swaps that need to be made in the worst case on an array of length n is n(n - 1) / 2 (details later), so for an array of size 217, you may end up not being able to store the number of swaps that you need inside an int. To address this, consider using a larger integer type. For example, the uint64_t type can store numbers up to roughly 1018, which should be good enough to store the answer for arrays up to length around 109. You mentioned that you're not sure how to use it, but the good news is that it's not that hard. Just add the line
#include <stdint.h>
(for C) or
#include <cstdint>
(for C++) to the top of your program. After that, you should just be able to use uint64_t in place of int without making any other modifications and everything should work out just fine.
Next, there's an issue of efficiency. The code you've posted essentially runs insertion sort and therefore takes time O(n2) in the worst-case. For large inputs - say, inputs around size 108 - this is prohibitively expensive. Amazingly, though, you can actually determine how many swaps insertion sort will make without actually running insertion sort.
In insertion sort, the number of swaps made is equal to the number of inversions that exist in the input array (an inversion is a pair of elements that are out of order). There's a beautiful divide-and-conquer algorithm for counting inversions that runs in time O(n log n), which likely will scale up to work on much larger inputs than just running insertion sort. I think that the "best" answer to this question would be to use this algorithm, while taking care to use the uint64_t type or some other type like it, since it will make your algorithm work correctly on much larger inputs.

Logic challenge: sorting arrays alphabetically in C

I'm new to programming, currently learning C. I've been working at this problem for a week now, and I just can't seem to get the logic straight. This is straight from the book I'm using:
Build a program that uses an array of strings to store the following names:
"Florida"
"Oregon"
"Califoria"
"Georgia"
Using the preceding array of strings, write your own sort() function to display each state's name in alphabetical order using the strcmp() function.
So, let's say I have:
char *statesArray[4] = {"Florida", "Oregon", "California", "Georgia"};
Should I do nested for loops, like strcmp(string[x], string[y])...? I've hacked and hacked away. I just can't wrap my head around the algorithm required to solve this even somewhat efficiently. Help MUCH appreciated!!!
imagine you had to sort the array - think of each state written on a card. HOw would you sort it into order. There are many ways of doing it. Each one is called an algorithm
One way is to find the first state by looking at every card and keeping track in your head of the lowest one you have seen. After looking at each card you will have the lowest one. Put that in a new pile. NOw repeat - trying to find the lowest of the ones you have left.
repeat till no cards left in original pile
This is a well known simple but slow algorithm. Its the one i would do first
there are other ones too
Yes, you can sort by using nested for loops. After you understand how strcmp() works it should be fairly straight forward:
strcmp(char *string1, char *string2)
if Return value is < 0 then it indicates string1 is less than string2
if Return value is > 0 then it indicates string2 is less than string1
if Return value is = 0 then it indicates string1 is equal to string2
You can then choose any of the sorting methods once from this point
This site has a ton of great graphical examples of various sorts being performed and includes the pseudo code for the given algorithms.
Do you need "any" sorting algorithm, or an "efficient" sorting algorithm?
For simplicity, I can show you how to implement an easy, but not efficient, sorting algorithm.
It's the double for method!!
Then, with the same ideas, you can modify it to any other efficient algorithm (like shell, or quicksort).
For numbers, you could put arrays ir order, as follows (as you probably know):
int intcmp(int a, int b) {
return (a < b)? -1: ((a > b)? +1: 0);
}
int main(void) {
int a[5] = {3, 4, 22, -13, 9};
for (int i = 0; i < 5; i++) {
for (int j = i+1; j < 5; j++)
if (intcmp(a[i], a[j]) > 0) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
printf("%d ", a[i]);
}
}
The only thing that has changed now is that you have strings intead integers.
So, you have to consider an array of strings:
char *a[] = {"Florida", "Oregon", "Califoria", "Georgia"};
Then, you have to change the type of temp to char*,
and finally you put the function strcmp() instead of intcmp().
The function strcmp(s1, s2) (from < string.h >)
returns a number < 0 if s1 is a string "less than" s2, == 0 if s1 is
"equal to" s2, and > 1 else.
The program looks like this:
#include <stdio.h>
#include <string.h>
int main(void) {
char *a[] = {"Florida", "Oregon", "Califoria", "Georgia"};
for (int i = 0; i < 4; i++) {
for (int j = i+1; j < 4; j++)
if (strcmp(a[i], a[j]) > 0) {
char* temp = a[i];
a[i] = a[j];
a[j] = temp;
}
printf("%s ", a[i]);
}
getchar();
return 0;
}
Note that for the printf() sentence, we have changed "%d " by "%s ", in order to properly show strings.
Final comment: When you program a better algorithm, like quick-sort, it is enough that you change the comparisson function, because the algorithm it is the same, in despite of the type of data you are comparing.
Remark: I have used a "tricky" method. As you can see, I have defined the variable a as a pointer to string. The initializer has taken a constant array of strings and then initialized the variable a with it. The variable a now can be safely treated and indexed as an array of exactly 4 pointer-to-strings.
That is the reason why the "swap" works fine in the double-for algorithm: The memory addresses are swapped instead the entire strings.
Steps you likely should take:
Populate array with state names
Create method to swap two states in place in the array
At this point you have all the tools necessary to use strcmp to implement any sorting algorithm you choose
Most sorting methods rely on two things.
Being able to rearrange a list (i.e. swap)
Being able to compare items in list to see if they should be swapped
I would work on getting those two things working correctly and the rest should just be learning a particular sorting algorithm
Beware of a little headaching problem: Strings are sorted by ascii numeric representations, so if you sort alphabetically like this, any capital letter will come before a lowercase letter e.g. "alpha", "beta", "gamma", "Theta" will be sorted as:
Theta, alpha, beta, gamma
When it comes to the sample array you have listed here the simple algorithm mentioned earlier might actually be the most efficient. The algorithm I'm referring to is the one where you start with the first element and then compare it to the others and substitute with the smallest you find and then going to the next element to do the same only dont compare it to the already sorted elements.
While this algorithm has an execution time of O(n^2). Where n is the number of elements in the array. It will usually be faster than something like quick sort (execution time O(n*log(n)) for smaller arrays. The reason being that quick sort has more overhead. For larger arrays quick sort will serve you better than the other method, which if memory serves me right is called substitution sort although I see it mentioned as "double for" in a different answer.

Sub-array of integers with given sum, using recursion in C

I have got a pretty hard task I find difficult to handle.
I'm trying to write a recursive function (no loops at all) that, given an array and its length, will print a pair of sub arrays, each of which's sum will be half of the sum of the entire array. In other words, the array is to be divided into two groups of integers so that their sum is equal.
For example, given the array {1,2,2,0,5}, the function should output {1,2,2} {0,5}
I have to do it recursively, with a function that gets only the array itself and its size. I am also only allowed to use one more additional recursive function to solve the problem.
Any thoughts or ideas will be most appreciated.
Hello again!
we got a code in class that goes like this
int SubsetSum(int arr[], int idx, int n, int S) {
if (S==0) return 1; //This is stopping condition #1.
if (S<0 || n==0) return 0; //This is stopping condition #2.
return SubsetSum(arr, idx+1, n-1, S-arr[idx]) || SubsetSum(arr, idx+1, n-1, S);
}
what does the " || " operator means in terms of recursion?
thanks ppl!
You first calculate the sum of the whole array (it'll better be even), and this gives you the half-sum, which you can reach using a binary knapsack routine.
There is also a recursive implementation on Stack Overflow in Java, which isn't too different from C and satisfies your requirements.
Divide the array and sub-arrays from the middle until there is only one element.
Compare the first element with second and find sum of these integers.
After that use these sums for binary elements comparing. When doing this compare find the sum. For example your sub-arrays are {1,2} and {0,3}. Look the first elements 0 and 1. When you see the little element take the other element in that sub-array ( {0,3} ). After that sum is now 3. The other part's sum is 1 and take the other element (2). Now the sum is 3 for both. And you can use this for all sub-arrays.
I'm not sure about the solution. But I think it seems like divide-and-conquer algorithm.

Finding a specific sum of elements from two arrays

Could you please help me with this one? :
"Let A and B are an incrementally ordered arrays of natural numbers and K be some arbitrary natural number. Find an effective algorithm which determines all possible pairs of indexes (i,j) such that A[i]+B[j]=K. Prove algorithm's correctness and estimate its complexity."
Should I just iterate over the first array and do a binary search on the other one?
Thanks :)
No!
Both arrays are ordered, so you do the following:
Place an iterator itA on the beginning of A
Place an iterator itB on the end of B
Move iterators in opposite directions, testing *itA + *itB at each iteration. If the value is equal to K, return both indexes. If the value is smaller than K, increment itA. Else, decrement itB.
When you go through both arrays, you are done, in linear time.
Since, for every A[i] there can only be one B[j], you can find the solution with O(n+m) complexity. You can rely on the fact that, if (A[i1] B[j1]) and (A[i2] B[i2]) are both correct pairs, and i1 is less than i2 then j1 must be greater than j2. Hope this helps.
I don't know if it helps, it's just an idea. Loop A linearly and binary search B, but do A backwards. This might give you a better best case, by being able to exclude some portion of B at each step in A.
If you know that A[i] needed say B[42] to solve for K, you'll know that A[i-1] will need at least B[43] or higher.
EDIT: I would also like to add that if B has fewer elements than A, turn it around and do B linearly instead.
Possible implementation in C++ can look as follows:
#include <iostream>
int main()
{
int A[]={1,2,3,6,7,8,9};
int B[]={0,2,4,5,6,7,8,12};
int K=9;
int sizeB=sizeof B/sizeof(int);
int sizeA=sizeof A/sizeof(int);
int i=0;
int j=sizeB-1;
while(i<sizeA && j>=0)
{
if ((A[i]+B[j])==K){
std::cout << i<<","<<j<< std::endl;
i++;
j--;
}
else if((A[i]+B[j])<K){
i++;
}
else{
j--;
}
}
return 0;
}

Solving problems recursively in C

Our professor gave us the following assignment:
A "correct" series is one in which the sum of its members equals to the index of its first member.
The program is supposed to find the length of the LONGEST "correct" series within a series of n numbers.
For example: if the input series would be arr[4]={1, 1, 0, 0}
the output (longest "correct" series) would be 3.
arr[0]=1. 0!=1 therefore the longest series here is 0.
arr[1]=1,and 1=1. but the following members also sum up to 1 as shown below:
1=arr[1]+arr[2]+arr[3] = 1+ 0 + 0, therefore the longest series here is 3.
The output in this example is 3.
This is what I have so far:
int solve(int arr[], int index, int length,int sum_so_far)
{
int maxwith,maxwithout;
if(index==length)
return 0;
maxwith = 1+ solve(arr,index+1,length,sum_so_far+arr[index]);
maxwithout = solve(arr,index+1,length,arr[index+1]);
if(sum_so_far+arr[index]==index)
if(maxwith>maxwithout)
return maxwith;
return maxwithout;
return 0;
}
int longestIndex(int arr[], int index,int length)
{
return solve(arr,0,length,0);
}
What am I doing wrong here?
We aren't supposed to us loops on this assignment.
Hmm, there are several problems with this program.
Most obvious, "return maxwithout; return 0;" should give a compile error: There's no way to get to that last return statement.
Second, you're recursing in to solve on the "maxwith" path until you reach the end of the array. Then you're going to recurse into maxwithout, hitting it for the first time with index=4. I don't think this is going to work.
Frankly, I don't think this problem really calls for recursion. THe most natural solution would be a nested loop:
for (int start=0;start<length;++start)
{
for (int end=start;end<length;++end)
{
// calculate the sum of arr[start]->arr[end] and compare to start
}
}
Or something to that effect.
Did the problem call for solving it with recursion, or was that just your first idea at a good solution?
Edit
Okay, so you have to use recursion. I guess the point of the lesson is to learn to use recursion, not necessarily to solve the problem in the most natural or efficient way. (Personally, I think the teacher should have come up with a problem where recursion was a natural solution, but I guess we're not here to critique the teacher today.)
I don't want to do your homework for you, but I'll give you a hint. You can use recursion to simulate a loop by putting the break condition at the beginning of the function and putting the recursive call at the end of the function with a +1 parameter. That is, instead of writing
for (int x=0;x<10;++x) { ... whatever ...}
you can write
void forx(int x)
{
if (x>=10)
return;
... whatever ...
forx(x+1);
}
So in this case I'd do something like:
void endloop(int start, int end)
{
if (end>=arrayLength)
return;
... work on running total ...
endloop(start, end+1);
}
void startloop(int start)
{
if (start>=arrayLength)
return;
endloop(start, start);
}
int main()
{
... setup ...
startloop(0);
... output ...
}
Parameter lists are not necessarily complete. As I say, I don't want to do your homework for you, just give you a hint to get started.
First, write a function that tests a series of given starting index and given length for the "sum of its members" condition. Then, write a second function which looks for the longest series within your array where only the starting index is given (looping over the sub-series length in decreasing order should do it); this function can call the first one. At last, write a third function looping over all starting indexes, calling function number two.
Oh wait, there is no recursion needed any more, so a lot of brain-twisting is gone ... :-)
It seems to me that the problem lies here:
if(sum_so_far+arr[index]==index)
You're comparing the sum so far with the current index, but you should be comparing it with the first index in the series. It seems to me that it would be better if you started with the last element of arr towards the first, instead of going in the natural order. That way you start summing elements up until the sum equals the current index.

Resources