How to determine why a piece of code produces an infinite loop? - c

This is my binary search function. I can't seem to find the error but every time I try to run the code it gives me a segmentation fault 11. I feel like my mistake has to do with my last else if statement.
void binary(struct list *A[], char search[15], int start, int
end) {
if(start <= end) {
int middle = (start + end)/2;
if(strcmp(search, A[middle]->name) == 0){
printf("found");
exit(0);
} else if (strcmp(search, A[middle]->name) > 0){
int start = middle + 1;
int end = end;
binary(A, search, start, end);
} else if (strcmp(search, A[middle]->name) < 0){
int start = start;
int end = middle - 1;
binary(A, search, start, end);
} else if (start == (end - 1)) {
printf("%s was not found in the list", search);
exit(0);
}
}
}

These statements
int end = end;
int start = start;
do not make sense because the variables are initialized by themselves while they have indeterminate values.
There is no need to declare local variables end and start. Use the parameters.
This statement
} else if (start == (end - 1)) {
printf("%s was not found in the list", search);
exit(0);
}
also does not make sense because initially the variables start and end satisfy the condition of enclosing if statement
if(start <= end) {
And at last it does not make sense to use standard function exit instead of the return statement..

First, as others already pointed out, the assignment like int end = end is asking for troubles. Do a simple test and print the start and end values at the beginning of the function to see what happens as your program works...
Next, you do not need recursion here! Shrinking the search area can be easily done in a simple loop:
void binary(struct list *A[], char search[15], int start, int end) {
while(start <= end) {
int middle = start + (end - start)/2;
int cmpresult = strcmp(search, A[middle]->name);
if (cmpresult > 0) {
start = middle + 1;
} else if (cmpresult < 0) {
end = middle - 1;
} else { // cmpresult == 0
printf("found at %d", middle);
return;
}
}
printf("%s was not found in the list", search);
}
Finally, please note the middle calculation – adding (start + end) is a common step to do that, however it may lead to error if the array is too long; specifically, if the array length exceeds a half of the maximum value representable by int type.

Related

Correct parenthesis

I came across this problem :
"It gives a string of round brackets. This string represents a parenthesis that is not necessarily correct. You have available the next move : you can change an open bracket '(' into a close brachet ')' or vice versa. You have to calculate the minimum number of moves needed to make the parenthesis to be correct."
e.g.
)())
answer : 1
First of all, I think that it would be useful to use parsing, but the program doesn't seem to work right.
void X() {
if(first=='(') {
firt=fgetc(fi);
X();
if(first!=')')
er++;
first=fgetc(fi);
}
else {
..
}
}
What would be an idea of beginning?
Thanks
I would like to propose an algorithm. First the pseudo code:
For each input character C:
If C is '(' then
increment counter
else if counter is 0 then // The closing paren has no matching opening
increment moves // so we "flip" it and counting as the opening
increment counter
else
decrement counter // This closing paren is balanced
end if
end For
// Now the counter is containing the number of unbalanced opening parentheses,
// so we add half of this number to moves, as half of them have to be balanced
moves = moves + counter / 2
return moves
Now in C:
#include <stdio.h>
#include <string.h>
int main(void) {
char input[] = "((((";
int len = strlen(input);
int i;
int moves = 0;
int count = 0;
for (i=0; i < len; i++)
{
if (input[i] == '(')
{
count ++;
}
else
{
if (count == 0)
{
count ++;
moves ++;
}
else
{
count --;
}
}
}
moves += count / 2;
printf("Moves: %d\n", moves);
return 0;
}
You are invited to test it with different inputs here, prove it's correctness or disprove with a counterexample input :)
Here's one way (in Pascal). Fixes the actual string and shows before and after.
function FixBrackets(s: string): Integer;
var
LeftToProcess, OpenCount: Integer;
I: Integer;
begin
writeln('in:', S);
Result := 0;
LeftToProcess := length(s);
OpenCount := 0;
for I := 1 to LeftToProcess do begin
case S[I] of
'(' :
if LeftToProcess <= OpenCount then begin
// we must close all
S[I] := ')';
inc(Result);
end else
inc(OpenCount);
')' :
if OpenCount = 0 then begin
// we have no open pars to close, so this has to be a new open
S[I] := '(';
inc(Result);
inc(OpenCount);
end else
dec(OpenCount);
end;
dec(LeftToProcess);
end;
writeln('out:', s);
end;
Here's an answer in C++:
template<class T>
int count_changes(T begin, T end) {
int offset = 0;
int changes = 0;
for (auto it = begin; it != end; ++it) {
if (*it == '(') ++offset;
else --offset;
if (offset < 0) {
offset = 1;
changes++;
}
}
return changes + ((offset + 1) / 2);
}
int main() {
std::string parens { "))(()" };
cout << parens << " : " << count_changes(parens.begin(), parens.end()) << endl;
}

Binary Search...Is something wrong with this code

I have only included the function. I am trying to implement binary search but for some reason it is not working. What I am really trying to determine is whether the algorithm is correct. It appears fine to me....but may be I am wrong. I know that the algorithm has to be sorted first but that will be taken care of in another function. Is the algorithm wrong or right? For some unknown reason the programme hangs...I have taken care of all the headers etc....i am off target or what? Thanks. Function is in C.
bool search(int value, int values[], int n)
{
int i;
int begin = 0;
int end = n-1;
int middle = (begin + end)/2;
for ( i = 0; middle <=end; i++)
if (value == values[middle])
{
return true;
break;
}
else if (value > values[middle])
{
begin = values[middle +1];
}
else
{
end = values[middle -1];
}
return false;
}
You do not need the loop on i.
Your loop would be on begin and end, such as while( begin < end )
Depending on how values[middle] compare with values[begin] and values[end], you have to adjust begin (begin = middle + 1;) or end (end = middle - 1;). Beware of the boundary cases!
(begin + end) / 2 may caused integer overflow in C. Try to use begin + (end - begin) / 2 instead.
What is the algorithm you have in mind ? I would suggest to go through the algorithm first .
http://en.wikipedia.org/wiki/Binary_search
Your middle is calculating to the end. It should be middle = (end - begin) / 2

find an element in infinite sorted array

I got this as an interview question ...
infinite array which is sorted and from some position (we dont know the position) only special symbol '$' will be there we need to find an element in that array ...
i gave a solution like get the first occurrance of $ and then do binary search on the previous part from $
to find the first occurance of $ i gave solution like increment in window size if (i,2i)
the code i gave is
#include<stdio.h>
int first(int *arr,int start,int end,int index)
{
int mid=(start+end)/2;
if((mid==start||arr[mid-1] != '$') && arr[mid]=='$')
return mid;
if(arr[mid]=='$')
return first(arr,start,mid-1,index);
else
{
if(arr[end] =='$')
return first(arr,mid+1,end,index);
else
return first(arr,end+1,(1<<index),index+1);
}
}
int binsearch(int *arr,int end ,int n)
{
int low,high,mid;
high=end-1;
low=0;
while(low<= high)
{
mid=(low+high)/2;
if(n<arr[mid])
high=mid-1;
else if (n >arr[mid])
low=mid+1;
else
return mid;
}
return -1;
}
int main()
{
int arr[20]={1,2,3,4,5,6,7,8,9,10,'$','$','$','$','$','$','$','$','$','$'};
int i =first(arr,0,2,2);
printf("first occurance of $ is %d\n",i);
int n=20;//n is required element to be found
if(i==0||arr[i-1]<n)
printf(" element %d not found",n);
else{
int p=binsearch(arr,i,n);
if(p != -1)
printf("element %d is found at index %d",n,p);
else
printf(" element %d not found",n);
}
return 0;
}
Is there any better way to do the above problem ??
And also i wanted to know to find the first occurance of $ why should we move the window only in powers of 2 why not 3 like (i,3i)
Can someone pls through some light on the recurrance relation ..pls help..
Seems like a fine way to do it to me. As a small optimization, you can stop your first routine when you reach any number bigger than the one you're searching for (not just $).
Growing the window by powers of 2 means you'll find the end in log_2(n) iterations. Growing by factors of 3 means you'll find it in log_3(n) iterations, which is smaller. But not asymptotically smaller, as O(log_2(n)) == O(log_3(n)). And your binary search is going to take log_2(n) steps anyway, so making the first part faster is not going to help your big-O running time.
The efficient part of first function in iterative format would be
private int searchNum(int[] arr, int num, int start, int end) {
int index = 0;
boolean found = false;
for (int i = 0; i < arr.length; i = 1 << index) {
if (start + i < arr.length) {
if (arr[start] <= num && arr[start + i] >= num) {
found = true;
return bsearch(arr, num, start, start + i);
} else {
start = start + i;
}
} else {
return bsearch(arr, num, start, arr.length - 1);
}
}
return 0;
}
this wont return you first occurance but instead try to find number directly as in your case you are missing probability that number itself could be found even before finding the $ symbol. So worst case complexity is O(logn)..
and best case would be (1)
after that you pass this to
private int bsearch(int[] array, int search, int first, int last) {
int middle = (first + last) / 2;
while (first <= last) {
if (array[middle] < search)
first = middle + 1;
else if (array[middle] == search) {
System.out.println(search + " found at location "
+ (middle + 1) + ".");
return middle;
} else
last = middle - 1;
middle = (first + last) / 2;
}
if (first > last)
System.out.println(search + " is not present in the list.\n");
return -1;
}
calling function
if ((pos = searchNum(arr, num, 0, 2)) != -1) {
System.out.println("found # " + pos);
} else {
System.out.println("not found");
}
This is python solution.
arr = [3,5,7,9,10,90,100,130,140,160,170,171,172,173,174,175,176]
elm = 171
k = 0
while (True):
try:
i = (1 << k) - 1 # same as 2**k - 1 # eg 0,1,3,7,15
# print k
if(arr[i] == elm):
print "found at " + str(i)
exit()
elif( arr[i] > elm):
break
except Exception as e:
break
k = k+1
begin = 2**(k-1) # go back to previous power of 2
end = 2**k -1
# Binary search
while (begin <= end):
mid = begin + (end-begin)/2
try:
if(arr[mid] == elm):
print "found at " + str(mid)
exit()
elif(arr[mid] > elm):
end = mid-1
else:
begin = mid+1
except Exception as e:
# Exception can occur if you are trying to access min element and that is not available. hence set end to mid-1
end = mid-1
print "Element not found"

Recursively add sequence of numbers

Hey im trying to refresh my mind with a bit of recursion.
I want to add all numbers from 'start' to 'end' inclusive.
I.e if start was 1, and end was 5. Then the answer would be 1+2+3+4+5 = 15
So far I've got this
int calc(int start, int end){
if(start > end)
return total;
else{
total = total + start;
return sum1(start++, end);
}
}
Its not working (i get seg fault). What am i doing wrong?
EDIT: Sorry i am using the same variables in my actual code, when i wrote this i ended up reffering to them as start/end and forgot to change all the code.
What are from and to variables inside your function? Maybe you use some globals instead of using start and end and that's why you have the problem? Also why are you using sum1 inside the calc function instead of calc?
Try this instead:
int calc(int start, int end){
if(start > end)
return 0;
else
return start + calc(start + 1, end);
}
For starters, you aren't using your function parameters (start, end), you are using (from, to) instead. I assume from and to are either global variables or your code wouldn't compile. Furthermore, where is total declared?
This should work better:
int calc(int start, int end){
if(start > end)
return 0;
else{
return start + calc(start+1, end);
}
}
By the way, here's a more efficient solution:
int calc(int from, int to)
{
if (from == 0)
return to * (to+1) / 2;
else
return calc(0, to) - calc(0, from);
}
It's even recursive! Well, until you simplify it further to
int calc(int from, int to)
{
return ( to * (to+1) - from * (from+1) ) / 2;
}
That's because f(n) = n+...+3+2+1 = n(n+1)/2
This works fine for.
int calc(int from, int to)
{
if (from >= to) return to;
return from + calc(from + 1, to);
}

Simplify/Neatify this two-way loop?

I've got my wires crossed somewhere (or I had not enough sleep). I need a two-way loop, and my current code is just plain ugly.
Problem: I am running along a linear datastructre using an index. I have an starting index, lets say 120. I want to run alternating into both directions.
Example:
120,121,119,122,118,123,117,...
I have a stopping criterion which needs to be met for each direction separately. If it is met for one direction, I only want to run into the other direction, if both are met I need to exit the loop. In addition I need to stop if the next index is invalid (end of data structure, say smaller than 0 or bigger than 200).
Example: Stopping execution at 116 backwards and 130 forward:
120,121,119,122,118,123,117,124,116,(break),125,126,127,128,129,130.
Running into one direction first, then the other one is unfortunately not an option.
My current code is plain ugly. It is a lot of lines without containing any "productive" code. Only iteration logic:
int start_idx = 120;
int forward_idx = start_idx;
int backward_idx = start_idx;
bool next_step_forward = true; //should next step be forward or backward?
int cur_idx;
while(backward_idx >= 0 || forward_idx >= 0)
{
if(next_step_forward //if we should step forward
&& forward_idx >= 0) //and we still can step forward
{
cur_idx = ++forward_idx;
if(forward_idx >= 200) //200 is fictive "max index"
{
next_step_forward = false;
forward_idx = -1; //end of data reached, no more stepping forward
continue;
}
if(backward_idx >= 0)
{
next_step_forward = false;
}
}
else if(!next_step_forward
&& backward_idx >= 0)
{
cur_idx = --backward_idx;
if(backward_idx < 0) //beginning of data reached, no more stepping backward
{
next_step_forward = true;
continue;
}
if(forward_idx >= 0)
{
next_step_forward = true;
}
}
else
{
next_step_forward = !next_step_forward; //ever hit?, just security case
continue;
}
//loop body
//do something with cur_idx here
if(stoppingCriterionMet())
{
if(cur_idx > start_idx)
{ //this was a forward step, stop forward stepping
forward_idx = -1;
}
else
{ //this was backward step, stop backward stepping
backward_idx = -1;
}
}
}
Am I missing anything? Any hints appreciated. Thanks.
Edit 1: There are lots of very nice answers, which put "do something with cur_idx" into a separate function. While this is a perfect idea for the way my question was asked, I prefer putting the iterating code somewhere else and leave the productive code there. I have a long algorithm and want to split it up after it is finished to minimize rearangement work.
How about this?
void do_loop(SomeType *arr, int start, int low, int high, int arr_max)
{
int downwardIndex, upwardIndex;
downwardIndex = upwardIndex = start;
while (downwardIndex > 0 && upwardIndex < arr_max) {
if (downwardIndex < low && upwardIndex > high) {
break;
}
if (downwardIndex > low) {
processElement(arr[downwardIndex]);
downwardIndex--;
}
if (upwardIndex < high) {
processElement(arr[upwardIndex]);
upwardIndex++;
}
}
}
It so happened that I coded almost this problem today. And I used a C# iterator function to do it. But I think you want a more generic solution.
If you use a language where you can build your own iterators (C++,Java,C#), it's easy. You just make a custom iterator that initially spits out numbers starting from the center. Then you give the iterator an extra function to tell it to stop running in the current direction.
If you're doing something like this in C (it looks C to me), you can mimic this with a struct containing the iterator state, and functions that you call to step it forward or stop it.
First pass at hacking this (assuming C - adaptations needed for other languages, but the concepts are basically language neutral):
void pass1(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
while (lo_x >= lo_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
}
while (hi_x <= hi_limit)
{
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
}
It is not clear what should happen if the starting position matches the stop criterion. Should the search stop altogether, or should it continue upwards, or downwards, or both ways. I chose 'stop altogether', but a case could be made for any of the options listed. In the case of 'both', you would not even bother to run the stop criterion check.
I also chose to do the lower before the upper direction; it is clearly trivially reversed. The order of the final two loops doesn't matter because if both directions terminate in the same iteration, neither trailing loop is executed; if only one direction is terminated, the corresponding loop won't execute at all - only the other will.
Since there is still repeated code in there:
void pass2(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process_lo(&lo_x, lo_limit);
Process_hi(&hi_x, hi_limit);
}
while (lo_x >= lo_limit)
Process_lo(&lo_x, lo_limit);
while (hi_x <= hi_limit)
Process_hi(&hi_x, hi_limit);
}
void Process_lo(int *lo_x, int lo_limit)
{
Process(*lo_x);
if (StopCriterion(*lo_x))
*lo_x = lo_limit - 1;
else
*lo_x--;
}
void Process_hi(int *hi_x, int hi_limit)
{
Process(*hi_x);
if (StopCriterion(*hi_x))
*hi_x = hi_limit + 1;
else
*hi_x++;
}
Visibility controls (static functions) etc left out as details of the implementation language.
This is how I'd approach it in C#:
const int UPPER_BOUND = 200;
const int LOWER_BOUND = 0;
const int START = 120;
bool foundlower = false, foundupper = false;
int upper, lower;
upper = lower = START;
while (!foundlower || !foundupper) {
if (!foundlower) {
if (--lower <= LOWER_BOUND) foundlower = true;
if (stoppingCriterionMet(lower)) foundlower = true;
}
if (!foundupper) {
if (++upper >= UPPER_BOUND) foundupper = true;
if (stoppingCriterionMet(upper)) foundupper = true;
}
}

Resources