I'm trying to implement a binary search in a slightly non-traditional way by using only 3 arguments int value (what I'm looking for), int values[] (the array), int n (the size of the array). The code below finds the number 2 and recognizes that 13 is not there, but cannot find numbers like 6 or 7. I think the problem is in the final recursive call. It could be a pointer issue. I'm certain the rest of the code works fine. Any thoughts on where I might be going wrong would be appreciated.
#include <stdio.h>
#include <stdbool.h>
bool search(int value, int values[], int n);
int main(void)
{
int value = 6;
int values[] = {1, 2, 3, 4, 5, 6, 7};
int n = 7;
bool x = search(value, values, n);
if (x == true)
printf("found\n");
else
printf("not found\n");
}
bool search(int value, int values[], int n)
{
int midpoint = n/2;
if (n/2 <= 0)
{
return false;
}
if (value == values[midpoint])
{
return true;
}
if (value < values[midpoint])
{
return search(value, values, n/2);
}
else if (value > values[midpoint])
{
return search(value, values, n/2);
}
return false;
}
Yes, the problem is that when you call search with the upper half of the array, you should pass it with the offset like
return search(value, values + (n + 1) / 2, n / 2);
Note that I also skipped the middle element that you have already compared for the cases when n is odd. You can of course optimize the recursive calls, always taking care that also the length is calculated correctly.
Related
The following is an implementation of the problem from spoj:- http://www.spoj.com/problems/COINS/
#include <stdio.h>
#define ll long long
ll arr[100000];
ll max(ll n)
{
if(n < 49999)// Doubt
{
if(!arr[n])
return arr[n] = max(n/2) + max(n/3) + max(n/4);
else
return arr[n];
}
else
return max(n/2) + max(n/4) + max(n/3);
}
int main()
{
ll n, c = 0, i;
for(i = 0; i < 12; i++) // Also why 12 when the input can be <12
{
arr[i] = i;
}
while(scanf("%lld", &n) != EOF)
{
printf("%lld\n", max(n));
}
return 0;
}
Why does the if condition contain n<49999?
without having examined each possibility, other than the first 20+ values and the max and min values:
MY expectation is
the first 12 entries in the arr[] are pre-calculated to help reduce the depth of a recursion however the dollar value is not the same as the calculated value for those first 12 entries.
for coin values <= 49999, check to see if value already calculated, if not then break the coin into the /2 /3 /4 values and recurse each of those resulting values.
This limit value (49999) could be extended to 100000 as that is the available size of the arr[] array.
the presetting and the saving into the arr[] array are to help reduce execution time taken and the depth of the recursion.
the use of the array is so any previously calculated values (in the posted code, up to 49999) can be immediately returned by the max() function, without further recursion.
I would modify the code slightly for better documentation and robustness and faster execution as follows:
#include <stdio.h>
#include <stdint.h>
#define MAX_ARRAY_LEN (100000)
uint32_t arr[ MAX_ARRAY_LEN ] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
uint32_t max(uint32_t n)
{
if(n < MAX_ARRAY_LEN)
{ // value of 'n' within the range of the learning array arr[]
if(!arr[n] && n)
{ // then learning array arr[] not yet set
return arr[n] = max(n/2) + max(n/3) + max(n/4);
}
else
{ // else learning array arr[] already set for 'this' value of 'n'
return arr[n];
}
}
else
{ // value of 'n' is greater than the learning array arr[]
return max(n/2) + max(n/4) + max(n/3);
}
} // end function: max
int main( void )
{
uint32_t n;
int status;
while( (status = scanf("%u", &n)) == 1 && EOF != status)
{
if( 1000000000 >= n)
{
printf("%u\n", max(n) );
}
else
{
printf(" invalid value entered, must be in the range 0...1 000 000 000\n");
} // end if
} // end while
return 0;
} // end function: main
As far I understand that,
The person who write the code, somehow he found out that (manually) if
the coin less than 12 then result will be itself. so that he use 12.
(check the explanation of the input coin = 2)
And about the recursion function
as we know we can't declare array with 1,000,000,000 size so he try to
use some other value (49999 here) in which size he can create array
and later take the result for the coin in array like arr[12] = 13
(where 12 is coin and 13 is the result) so that he can get the result
without generate for the value by using that array with arr[12] (only)
for coin 12.
Hope you understand.
I have been cracking my head at achieving something very simple in C in order to make my one of the programs (not written by me) in our computational physics project more dynamic:
comparing two different arrays element by element in an if conditional.
#include <math.h>
#include <stdio.h>
#include "header.h"
const int nParam = 10;
double a[nParam], a_tmp[nParam];
double values[10000];
double FitParam(double x){
int xindex;
double value;
xindex=(int) x;
if (a_tmp[1]==a[1] && a_tmp[2]==a[2] && a_tmp[3]==a[3] && a_tmp[4]==a[4]){
value=values[xindex];
return(value);
}
// code continues... (very long subroutine and there is recursion for
// the subroutine so this if statement above is very important).
The array a[ ] has a varying number of significant elements every time we run our program; for example, right now, we are using this subroutine for only elements [1] through [4]. However, in other cases, we will want to have fewer or more elements, say, up to 3 elements or up to 5 elements, respectively.
So essentially, I want to be able to rewrite the if statement above so that it is dynamic... in other words, if there are N elements considered, then it will do:
if (a_tmp[1]==a[1] && ... && a_tmp[N]==a[N]){}
So this if conditional should vary whenever our number N of elements of interest is changed (N is defined as a #define in the header of this file, which I just named header.h).
I would greatly appreciate your support on this task. Thank you.
Your best bet is to rewrite it as a function that returns true or false (1 or 0):
int compareArrays(double a[], double b[], int n) {
int ii;
for(ii = 1; ii <= n; ii++) {
if (a[ii] != b[ii]) return 0;
// better:
// if(fabs(a[ii]-b[ii]) < 1e-10 * (fabs(a[ii]) + fabs(b[ii]))) {
// with the appropriate tolerance
}
return 1;
}
Note that it is usually bad practice to compare doubles for equality - you are better off comparing their difference, and making sure the absolute value is less than some tolerance.
Also note you are comparing elements 1 through n - C arrays start at 0 though.
You would use the above with
if (compareArrays(a, a_tmp, N)) {
where the value N is #define'd per your question.
If you want to be "clever" and avoid a loop, you can write the following - it will stop ("short-circuiting") as soon as you reach the right number of comparisons. It is still a Bad Idea to compare doubles for equality but I will leave that for another time (see comment in code above for a solution).
if(a[1]==a_temp[1] && (2 > N || (a[2]==a_temp[2] && (3 > N || (a[3]==a_temp[3]))))) {
This makes the "and the rest" true as soon as you have compared the right number of terms - so it will stop evaluating terms (as you need). I am not convinced this is either faster, or better code - but it is "dynamic"... You can obviously make this expression as long as you would like; I just wrote the first three terms so you get the idea. I DO NOT RECOMMEND IT.
As for the comparison of doubles, you might consider replacing
if(a == b)
with
if(closeEnough(a, b))
where you define the macro
#define closeEnough(a, b) (fabs((a)-(b)) < 1e-10 * (fabs(a) + fabs(b)))? 1 : 0
This will make sure that your doubles don't have to be "exactly equal" - depending on how you arrived at them, they will almost never be, and the relative tolerance of 1 part in 10^10 is usually plenty for most practical comparisons.
If it must be at compile time, there is nothing in the standard that provides for a repeating macro like that. As in another (question), for bounded N, you can prepare N macros that expand to your desired comparison.
While yet another alternative is memcmp
memcmp( data, data2, array_len_in_bytes );
reference
An implementation might be to loop over all the elements and set a flag when a difference is detected
int i, N;
int is_equal = 1;
for (i=1; i<N; ++i) {
if (a[i] != a_tmp[i]) {
is_equal = 0;
break;
}
}
if (is_equal)
printf("Arrays are equal");
A simple implementation is a linear comparison between both arrays, it just iterate over the array length and check if (a[i] != b[i]), if so return false & break out of the iteration.
See the example below:
#include <stdio.h>
int compareArrays(int a[], int b[], int n)
{
for (int i=0; i<n; ++i)
{
if (a[i] != b[i])
{
return -1;
}
}
return 0;
}
int main()
{
int arr1[4] = {3, 4, 5, 7};
int arr2[4] = {3, 4, 5, 7};
int arr3[4] = {1, 5, 3, 7};
int arr4[4] = {3, 4, 5, 19};
printf("Should be True %d\n", compareArrays(arr1, arr2, 4));
printf("Should be False %d\n", compareArrays(arr3, arr4, 4));
return 0;
}
You should get:
Should be True 0
Should be False -1
Run it online this example: https://repl.it/#abranhe/compare-arrays-in-c
This one, lets you compare two arrays of any type and will return the index of the first unequal elements found. If the arrays are identical the returned value will be the number of elements in the array.
int compareArrays(void* arrayA, void* arrayB, uint numElements, uint elementSizeBytes) {
//returns -1 on error, numElememts if the arrays are equal or the index
//of the first unequal elements
uint i;
uint8_t* byteArrayA;
uint8_t* byteArrayB;
if(elementSizeBytes < 1) {
return -1;
}
if(numElements < 1) {
return -1;
}
byteArrayA = (uint8_t*) arrayA;
byteArrayB = (uint8_t*) arrayB;
for(i = 0; i < (numElements*elementSizeBytes); i++) {
if(byteArrayA[i] != byteArrayB[i]) {
break;
}
}
return i / elementSizeBytes;
}
An example call:
uint16_t test1[6] = {12, 15, 24, 86, 92, 15};
uint16_t test2[6] = {12, 15, 24, 86, 93, 15};
int retVal = compareArrays(test1, test2, 6, 2);
Today i came across same kind of problem statement,i googled for solution for an hour and end up with no solution,the above all approaches are not correct solutions for the stated problem
The Better way to resolve above Problem is
Sort the two arrays either in ascending or descending order, Then compare both the arrays.
#include<stdio.h>
void sort_it(int a[], int size)
{
int i,j,temp=0;
for(i=0;i<size;++i)
{
for(j=i+1;j<size;++j)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
};
int compare(int size,int a[],int b[])
{
int i,j,is_equal;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)`enter code here`
{
if(a[i]!=b[j])
{
is_equal=0;
}
else
is_equal=1;
}
}
return is_equal;
};
int main()
{
int size=4,i,is_equal;
int a[]={1,2,5,4};
int b[]={1,7,4,2};
sort_it(a,size);
sort_it(b,size);
is_equal=compare(4,a,b);
if(is_equal)
printf("arrays are equal\n");
else
printf("arrays are not equal\n");
return (0);
}
i would like to ask about the array recursion in C, Let say i have an array in float
float arr[] = {12.5, 5.5, 6.0, 18.0};
i want to count the number which is greater than 10, so the result should be 2. However, below is what i did
int cntArray(float arr[], int size)
{
int number = 0;
if((cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
int main()
{
float arr[] = {12.5, 5.5, 6.0, 18.0};
int result;
result = cntArray(arr, 4);
printf("The result is : %d", result);
}
But it returns 0 as result, any solutions for it? Thanks
Another example:
int cntArray(float arr[], int size) {
if (!size) return 0;
return (arr[0] > 10.0 ? 1 : 0) + cntArray(&arr[1], size - 1);
}
Edit #1 (in reply to comment):
This simply evaluate through a ternary operator (?:) if the first index of arr[] is greater than 10.0. If true, 1 will be the lvalue, otherwise will be 0. The lvalue of cntArray(&arr[1], size - 1) (which will process the next element on the array after decrementing size and if size is different than 0, which in this case will immediately return 0) will be added to the lvalue of the ternary operator. Applying this recurring logic, the aftermath will be the number of elements in the array that are greater than 10.0.
Your cntArray() function lacks a recursion base case, and also seems to hardcode the wrong value (5 instead of 10).
It should be something like:
int cntArray(const float *arr, size_t size)
{
if(size > 0)
{
/* Count the first element, then recurse. */
const int count = arr[0] >= 10.f;
return count + cntArray(arr + 1, size -1);
}
return 0;
}
Your logic is severely flawed: You don't actually check if a value in the array is larger than 10. you also always return number which will always be zero meaning the condition will always be false.
int cntArray(float arr[], int size){
int number = 0;
if((number = cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
You maybe want to change 5 to 10.
int cntArray(float arr[], int size) {
int number = 0;
if (size > 0) number = cntArray(&arr[1], size - 1);
if (arr[0] > 10) number += 1;
return number;
}
I'm not sure what does this portion of your code does.
if((cntArray(&arr[1], size - 1))>=5)
number++;
I would something like this instead:
int cntArray(float arr[], int index, int size){
if (index == size) return 0; // base case
int rest = cntArray(arr, index + 1, size); // how many elements are greater
// then 10 in rest of the array
if (arr[index] > 10)
return rest + 1;
else
return rest;
}
And call it in the main like this:
cntArray(arr, 0, 4);
`/* finding the minimum number of a array */
#include<stdio.h>
int minimum(int n, int a[n], int x);
int main(void)
{
int a[5] = { 5, 4, 3, 4, 5 };
printf("%d \n", minimum(4, a, 0));
return 0;
}
int minimum(int n, int a[n], int x)
{
int minima;
if (x >= n)
return a[x];
else
minima = minimum(n, a, x + 1);
if (a[x] > minima)
return minima;
}
`
Hey I read few recursion sources in stackoverflaw. Also found same kind problem using JAVA. Can you please explain me how this code works.Or is this a good coding. I make it my self to learn recursion and it is working.Please explain.
There are two problems in your code:
The termination happens too late: you return a[x] when x==n - that's one element past the end.
There is a missing return when a[x] > minima is false: your function ends without returning a[x].
To fix these two problems, change the check of the termination condition, and add the missing return:
if(x >= n-1) return a[n-1];
// You do not need an else after a return
minima = minimum(n,a,x+1);
if (a[x] > minima) return minima;
return a[x];
Note that you can save one parameter by starting the search at the end of the array and going backward until you reach index zero.
I'm trying to make a divide and conquer version of binary search, but one that divides the array to two subarrays and search similar to merging in merge sort, the reason I want to do that becuase I want to use it in cilk, but I have to make it that way.
Here is the code I wrote, which seems to have something wrong with it as its returning -1 to valid key values.
#include <stdio.h>
#include "BinarySearch.h"
int main () {
int a[] = {0,1,2,3,4,5,6,7,8,9};
int index = binarySearch(a, 0, 9, 7);
printf("%i", index);
return 0;
}
int binarySearch (int* A, int first, int last, int key) {
if (last < first)
return -1;
else {
int mid = (last + first) / 2;
if (A[mid] == key)
return mid;
int x, y;
x = binarySearch(A, first, mid - 1, key);
y = binarySearch(A, mid + 1, last, key);
if (x == -1 && y == -1)
return -1;
else if (x == -1 && y != -1)
return y;
else
return x;
}
}
It's simple, 99 doesn't exist in your array. The result is correct. You probably just messed up the parameters - the first one is the array, the next two represent the range of the search, the fourth one is what you're looking for. A correct call would be:
int index = binarySearch(A, 0, 10, 4);
Also, this
int* A = &a[0];
is useless, you can simply use a as arrays decay to pointers:
int index = binarySearch(a, 0, 7, 99); // a instead of A
Also - a binary search takes into account the fact that the array is sorted. If your key is lower than the middle value, why bother searching to the right - it's guaranteed you won't find it there.
What you're doing is O(n), as opposed to a O(log(n)) binary search solution.
For any one still looking for solutions, I found this made by ankzcode.
It finds the minimum value in an array without linear search, using divide and conquer.
#include <stdio.h>
int findMin(int a[], int l,int h)
{
int pivot = (l + h) / 2;
int minl=-1, minh = -1;
if ( (pivot - l ) > 1)
{
minl = findMin(a, l, pivot);
}
else
{
minl = (a[l] > a[pivot])?a[pivot]:a[l];
}
if ( (h - pivot ) > 1)
{
minh = findMin(a, pivot, h);
}
else
{
minh = (a[l] > a[pivot])?a[pivot]:a[l];
}
return (minl>minh)?minh:minl;
}
int main()
{
int a[]={5,2,9,10,3};
printf("%d\n",findMin(a, 0, 5));
return 0;
}
you gave the key 99,which is not in array,So its obvious the code return -1.