CS50 Pset 3 Finding the Needle - c

I realised that when I included the "else return false" in my bool search, it will never be able to "find the needle". Conversely, if I were to remove that part, the program works fine. It is able to find 2008 and not find 2013. Any idea why is this so?
/**
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
*/
#include <cs50.h>
#include "helpers.h"
/**
* Returns true if value is in array of n values, else false.
*/
//value = needle , values[] = haystack, n = size
bool search(int value, int values[], int n)
{
// TODO: implement a searching algorithm
if(n<0)
return false;
for(int i=0;i<n;i++)
{
if(value == values[i])
{
return true;
}
else
{
return false;
}
}
return false;
}
/**
* Sorts array of n values.
*/
void sort(int values[], int n)
{
// TODO: implement an O(n^2) sorting algorithm
return;
}

Look at the code carefully:
for(int i=0;i<n;i++)
{
if(value == values[i])
{
return true;
}
else
{
return false;
}
}
The loop body always returns from the function - thus it will only run once (assuming n > 0). This is the same as testing whether value is in the first position of the haystack.
If you take out the else branch, the code in the loop body only returns when the value is found. If it's not found, it will check the next element, and the next, etc., until either you find it or you run out of elements.

I think you should implement sort function first . the search will not work without sort . if you try the above code with needle say 1 and you but 1 in the beginning if haystack it will return true . but if you put 1 in the second of the haystack it will return false even you are looking for 1 .

Related

Linear search is not returning the right index

My linear search is always returning -1 and I don't know why. I tried figuring it out but without success. The search function goes everytime to the "else" branch and the "then" is never executed.
#include <stdio.h>
#include <stdlib.h>
#define size 50000
int search(int n,int s,int v[s])
{
int i;
for(i=0;i<s;++i)
{
if(v[i]==n)
return i;
else
return -1;
}
}
int main(void)
{
int valores[size];
//start the vector and put values in it.
for(int i=0;i<size;++i)
valores[i]=(i+1)*2;
//search the 50000 values
for(int i=1;i<=size +1;++i)
{
int p=search(2*i,size,valores);
if(p==-1)
printf("Not found %d\n",i);
else if(valores[p]!=2*i)
printf("Found %d in wrong index: %d\n",i,p);
}
return 0;
}
You are always leaving your search function after the first index, 0;
because at 0 it will either be identical and return i, or not and return -1.
I assume that it does return 0, instead of -1, if you give n as v[0].
Change that this way:
for(i=0;i<s;++i)
{
if(v[i]==n)
return i;
}
return -1;
You get the warning you mention in a comment ("control reaches end of non-void function") because there is no return at the very end of your function. It would of course be unreachable, but the warning could have been a hint for finding the problem.

Can't return the correct int in C

i'm using this function (quicksort algorithm) and im
trying to get the total relocations also. In order to collect as much statitics i can i have to execute the function many times using a for loop, so after the end of the algorithm i must make the static variable equal to zero after copying it to a non-static variable and return it. Instead i always get a 0 return.
Please help me to not get a 0 grade too :P Thanks
int quicksort(int left, int right, int *p)
{
static int staticrelocations=0;
int i,j,mid,x,temp,relocations;
if(left<right)
{
i=left;
j=right;
mid=(left+right)/2;
x=p[mid];
while(i<j)
{
while(p[i]<x)
i++;
while(p[j]>x)
j--;
if(i<j)
{
if(p[i]==p[j])
{
if(i<mid)
i++;
if(j>mid)
j--;
}
else
{
temp=p[i];
p[i]=p[j];
p[j]=temp;
staticrelocations++;
}
}
}
quicksort(left,j-1,p);
quicksort(j+1,right,p);
}
relocations=staticrelocations;
staticrelocations=0;
return relocations;
}
You recurse into quicksort(), and in the innermost invocation you set staticrelocations = 0 before returning its former value. However, in the outer quicksort(), you ignore the return value of the inner quicksort. The outer quicksort returns the zeroed staticrelocations. Instead, you should go like this:
int quicksort()
{
int relocs = 0;
/* function logic */
if (/*did a new relocation*/)
relocs++;
relocs += quicksort(); //inner quicksort recursively
return relocs;
}

Collatz chain recursive function C

I am trying to create some code that when given a starting number attempts to find the length of the corresponding collatz chain.
I was hoping to do this recursively and this is what I have so far :
#include stdio.h
int collatz(int number, int count)
{
if(number == 1)
{
return count;
}
if(number%2==0)
{
number = number/2;
collatz(number, count+1);
}
else
{
number = number*3+1;
collatz(number,count+1);
}
return 0;
}
int main(void)
{
int stored=0;
int temp;
for(int i = 1;i<10;i++)
{
temp = collatz(i,1);
if(temp>stored)
{
stored = temp;
}
}
printf("%i\n",stored);
}
The problem is of course that the function eventually reaches its endpoint, but then gets returned as the length of the chain and this becomes the new number..
How can I structure this program so that when the count reaches its endpoint I can take this value as the output of the very first call?
You need to return the result of the recursive call. Right now you're ignoring the value of the recursive call and returning 0. Each recursive call should look like this:
return collatz(number, count+1);

error: control may reach end of non-void function

This error appeared to me when i was trying to compile a c file which contains a declaration of a linear search function
bool search(int value, int values[], int n)
{
// TODO: implement a searching algorithm
for(int d = 0;d<n;d++){
if(n<0){
return false;
}
else if(values[d]==value){
return true;
}
else{
return false;
}
}
}
What is wrong with my code? Please help.
Some problems with the code:
The method have a path that don't return anything, as commented, when parameter n = negative number or 0
The for-loop don't do anything, will only execute one time and exit for one of the conditions. It would only work correctly when the first element is the element searched, in any other case only check the first element and return (without correct info of present or not). Test with array int values[] = { 1, 2, 3, 4, 5 }; and search 3, your code would not found this value.
If you're searching for a specific value the code is:
bool search(int value, int values[], int n) {
for (int d = 0; d < n; d++) {
if (values[d] == value) {
return true;
}
}
return false;
}
The problem is the argument n passed to the function is n <= 0. The loop never executes and the function finishes without returning any value.
To fix it put the if(n <= 0) statement before the for loop.
If the 'for' loop doesn't get to do any iterations you won't be able to return anything from the function. Maybe add an edge case like
if(n <=0 )
return false;
before the loop.
d is incremented in the for loop until it equals the value of n. At that point, the code beyond the for loop is executed.
Being that there are no instructions beyond the for loop, the function returns to the caller. The error occurs due to there being no (boolean) value returned from the function in this case.
The error can be avoided by following Rule #1 of the Mahonri List Of Rules For Writing Maintainable C Code. Example:
bool search(int value, int values[], int n)
{
bool rCode=false;
// TODO: implement a searching algorithm
for(int d = 0;d<n;d++)
{
if(n<0)
{
goto CLEANUP;
}
else if(values[d]==value)
{
rCode=true;
goto CLEANUP;
}
else
{
goto CLEANUP;
}
}
CLEANUP:
return(rCode);
}

Check if Number Exists in array which first increases then decreases then increases

Given an array first increasing then decreases at a point and again increases?
find a given number N exists in array or not.
Example 1:
Array = 7,8,3,4,5,6
number = 7
answer should be true.
Example 2:
Array = 3,4,6,7,8,5,9,10,11
number = 10
answer should be true.
All numbers are unique.
can be done with linear search in O(N),
Can we do that lesser than that. (more efficient)
In general, no. Suppose we have the following, in Python:
l = range(n)
and we randomly stick a -1 in there:
if random.random() < 0.5:
l[random.randrange(len(l))] = -1
The only way to tell if there's a -1 in the list is to look through every element until you find it or don't. The structure of the list ends up not helping at all.
a linear search is as good as you will get for a non-linear array
Optimized Algorithm : -
Use binary search for key on array if found then return true.
If not found use linear search
Time Complexity : -
Unsuccessful search : Here we would do both linear search and binary search hence O(N) for large inputs
Successful search : Here is where our optimization work to some extent. There is on average 1/2 chance that you end up searching in right part of array in binary search . Hence atleast 2 times faster search on average.
Java Code for optimized algorithm with results :-
public class UniqueSearch {
static int linearCount = 0;
public static boolean binSearch(int[] arr,int key,int high,int low) {
while(high>=low) {
int mid = (low+high)/2;
if(arr[mid]==key)
return(true);
if(arr[mid]<key) {
low = mid+1;
}
else {
high = mid-1;
}
}
return(false);
}
public static boolean linearSearch(int arr[],int key) {
//System.out.println("linearSearch");
linearCount++;
for(int i=0;i<arr.length;i++) {
if(key==arr[i]) {
return(true);
}
}
return(false);
}
public static boolean optSearch2(int arr[],int key) {
boolean flag = binSearch(arr, key, arr.length-1,0);
if(!flag) {
return(linearSearch(arr, key));
}
return(flag);
}
public static void main(String[] args) {
int n = 100000;
int[] arr = new int[n];
int error = 0;
Random r = new Random();
long start = System.currentTimeMillis();
int totalCount = 0;
for(int i=0;i<1000;i++) {
error = r.nextInt(arr.length-1);
for(int k=0;k<error;k++) {
arr[k] = 2*k+1;
}
for(int k=error;k<arr.length;k++) {
arr[k] = 2*(k-error);
}
for(int j=0;j<1000;j++) {
int x = r.nextInt(arr.length);
totalCount++;
boolean flag = optSearch2(arr,arr[x]);
if(!flag) {
System.out.println("error");
}
}
}
System.out.println("linearSearch Percentage: "+linearCount*100/totalCount);
System.out.println(System.currentTimeMillis()-start);
}
}
Results :
Run the code and wait for 6-7 secs and you will see that for random successfull search on random array of the special kind as your problem requires linear search about 30% times and rest can be done using binary search in O(logn)
Can be done in O(logN) time complexity
Find maximum element in array (call this pivot). Here's the pseudo code
public static int getMax(int start, int end){
if(start==end)
return start;
if(start>end)
return -1;
int mid = start + (end-start)/2;
// check if maxima
if(arr[mid-1]<arr[mid] && arr[mid]>arr[mid+1])
return mid;
// check slope
if(arr[mid-1]<arr[mid] && arr[mid]<arr[mid+1]){
//increasing slope
return getMax(mid+1, end);
}
if(arr[mid-1]>arr[mid] && arr[mid]>arr[mid+1]){
return getMax(start, mid-1);
}
return -1;
}
Partition array on pivot element and run two binomial searches for left(increasing) and right(decreasing)
findElem(int key, int pivot){
int index = binSearchInc(start, pivot-1);
if(index>=0)
return index;
else
return binSearchDec(pivot+1, end);
}
Both steps take O(logN) time for execution.

Resources