I'm trying to create a programm to find all subsets whose elements sum to a specific target. My logic is : Let's say I have an array of 6 elements like this one
{3,2,4,1,1,9}.
To find a subset whose elements sum to the number 5, all I have to is get the first element and if its value is smaller than 5 then I move to the next elements of the array and I look for subsets whose elements sum to the difference : 5-value of the first element and so on.
Of course if the value of the element is greater than 5 then I move to the next element.
I've been trying to do this with a recursive function in which I will pass my array.
My problem is that I can't understand how to pass my array into my function and how am I supposed to move to the next element using my function again. To be my honest I did my research on this topic and I couldn't really find anything that helped me.
I use C and I declare my function like this void subset(int x[],int n); where n is the number of the elements of my array. I can't really understand the x[] part. My brother told me to do it like this but I can't really understand why.
So you're trying to pass your array into a function? An array has elements or members which will be referenced using the brackets "[ ]" for example in the array "int arry[6]={1,2,3,6,5};" the first element would be the number "1" which we can access using arry[0]
With all due respect it seems like you did not do your "honest research" in this area and I suggest you continue as arrays are an integral part of almost every language.
Below is some c code which should help you get started on your homework. int arry[] is a completely different type than lets say "int arry". The bracket part tells us that it is an array.
#include <stdio.h>
int main()
{
int arry[6]={1,2,3,6,5};
myFunction(arry,4);
return 0;
}
int myFunction(int myarr[], int x){
printf("the number %d element is %d",x+1,myarr[4]);
return 0;
}
Here's an elaborate solution. For the given data, it produces:
Data (6): 3 2 4 1 1 9
Found: 3 + 2 = 5
Found: 3 + 1 + 1 = 5
Found: 4 + 1 = 5
Found: 4 + 1 = 5
The key is to understand what data you need to solve the problem. You need to know:
The target sum
(The sum of the elements so far)
The number and list of unchecked elements
The number and list of elements already in the list
The 'sum so far' can be derived from the number and list of elements already in the list, but it is convenient to pass it too. That gives a 6-parameter recursive function. It is invoked with the desired target, 0 as the sum so far, the complete array of elements to search, and an empty list that is big enough to hold all the elements to be searched. This happens in main(). The function identifies whether it found any lists that added up to the target (returning 0 if not and 1 if it did), hence the test and report and the end of main().
In the function, check for various impossible conditions and bail out. If compiled with debug = 1 at the top, print data on entry to the function. Scan through the remaining unchecked elements, detecting when the element makes the sum equal to the target and reporting the list that does so (note it loses the original index information; you can add that, but it is an exercise for the reader). If the element is small enough to leave space for another, add the element to the found list and pass the rest of the array to a recursive call to the function. The other functions are trivial printing loops.
When target is set to 40 (instead of 5) it correctly reports no subsets are found adding up to 40.
There probably are easier ways to code it, but I'm pathologically opposed to unnecessary global variables (I regard debug as a way of conditionally compiling the code more than as a global variable). It would be possible to package up the argument list in a structure; I'm not sure it would help all that much, though. I could use bool instead of int (and false and true instead of 0 and 1) if I included <stdbool.h>. The code is unrepentantly C99 or C11; it won't compile as written under C89 (but it wouldn't be hard to make it work with C89).
Code:
#include <stdio.h>
static const int debug = 0;
static void found_one(int num, int *list)
{
printf("Found: ");
char const *pad = "";
int sum = 0;
for (int i = 0; i < num; i++)
{
printf("%s%d", pad, list[i]);
pad = " + ";
sum += list[i];
}
printf(" = %d\n", sum);
}
static void print_array(char const *tag, int num, int *arr)
{
printf("%s (%d):", tag, num);
for (int i = 0; i < num; i++)
printf(" %d", arr[i]);
putchar('\n');
}
static int find_subsets(int target, int sumsofar, int num_src, int *src,
int num_dst, int *dst)
{
if (sumsofar >= target)
return 0;
if (num_src <= 0)
return 0;
if (debug)
{
printf("-->> %s: sumsofar = %d, num_src = %d, num_dst = %d\n",
__func__, sumsofar, num_src, num_dst);
print_array("Source", num_src, src);
print_array("Dest'n", num_dst, dst);
}
int rc = 0;
int max = target - sumsofar;
for (int i = 0; i < num_src; i++)
{
if (src[i] == max)
{
dst[num_dst] = src[i];
found_one(num_dst + 1, dst);
rc = 1;
}
else if (src[i] < max)
{
dst[num_dst] = src[i];
if (find_subsets(target, sumsofar + src[i], num_src - (i + 1),
src + (i + 1), num_dst + 1, dst))
rc = 1;
}
}
if (debug)
printf("<<-- %s: %d\n", __func__, rc);
return rc;
}
int main(void)
{
int data[] = { 3, 2, 4, 1, 1, 9 };
enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };
int subset[NUM_DATA];
int target = 5;
print_array("Data", NUM_DATA, data);
if (find_subsets(target, 0, NUM_DATA, data, 0, subset) == 0)
printf("Did not find any subsets totalling %d\n", target);
return 0;
}
Related
You get an array a of integers. Need to return the largest value x in a so that -x is also in a. If there's no such value - return 0.
Example:
For [6,5,2,-1,-2,-5] the return value is 5 since -5 is in the array (the answer isn't 6 since -6 isn't in the array).
Edit: the input array isn't necessarily sorted.
Now, if I could use Java - I would solve it using HashSet which I'll add all array elements to in their absolute value, looping over the array and updating the maximum value if it's the largest I've seen so far and if I find the absolute value of it in the Hash. This will result in O(n) average time.
But on the interview I needed to solve it using C code, without creating any special data structures like HashSet.
The only idea I had was to sort the array, use two pointers (one for the start and one for the end) and move the pointers toward each other till I find the answer.
This wasn't good enough since it's O(nlogn).
Do you have an idea how can I solve it in C code in O(n), using built-in libraries only?
#include <stdio.h>
#include <stdlib.h>
int found = 0;
int n = 0;
int len = 6; // your array has 6 elements
for(int i = 0; i < len -1; i++) {
for(int j = i+1; j < len; j++) {
if(a[i] == -a[j] && (found = 0 || abs(a[i] > n)) n = abs(a[i]);
}
}
if(found) printf("Number is : %d\n", n);
else printf("Not found");
Ok, this is the real O(n) solution without libraries, but requires an ordered array. Just one loop, and moving the pointers initial and final.
#include <stdio.h>
int a[] = {6,5,2,-1,-2,-5};
int main(int argc, char** argv) {
int* left = a; // point to first
int* right = a + 5; // point to last
while(right > left) {
int result = *left + *right;
if(!result) {
printf("Number is %d\n", *left);
return 0;
}
if(result > 0) left++;
else right--;
}
printf("No result");
return 1;
}
this code is used to create an array filled with 10 random integers. It sorts the array and then inputs the array into a binary search function. I do not get the position of where my search key is positioned.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int binary_search(int array[], int search, int strt, int ending)
{
int middle;
middle = (strt + ending)/2;//splitting the array in half to compare the search key
if (search > array[middle]){binary_search(array, search, middle + 1, ending);}
else if(search == array[middle])
{
printf("Your search key is indicated in %d position the array Ferrari\n", middle + 1);
return middle;
}
else{binary_search(array, search, strt, middle -1);}
return -1;
}
int main()
{
srand(time(NULL));//random number seed generator
int Ferrari[10];
int size = 10;
int selection;
int temporary = 0;//I'm using this variable to store
//the value returned from linear_search()
int start = 0;
int end;
int i;
//this is to generate a random number between 0 and 101
for(int i=0; i<10; i++) {Ferrari[i] = rand() % 100 + 1;}
//printing the initial array
printf("\nThe array Ferrari consists of -> ");
for(int i=0; i<10; i++){printf("%d, ", Ferrari[i]);}
//--------------------------SORTING--------------------------------------------
for(int f = 0; f < (size - 1); f++)
{
for(int kk = 0; kk < (size - 1 - f); kk++)
{
if(Ferrari[kk] > Ferrari[kk +1])
{
int Te_mP;
Te_mP = Ferrari[kk + 1];
Ferrari[kk+1] = Ferrari[kk];
Ferrari[kk] = Te_mP;
}
}
}
//----------------------------------------------------------------------------
//printing the array after it has been sorted
printf("\n");
printf("\nThe sorted array Ferrari consists of -> ");
for(int i=0; i<10; i++){printf("%d, ", Ferrari[i]);}
start = 0;
end = i -1;
//this will be used to implement the searching algorithm
printf("\n\n");
printf("Please enter a number to test if it is included in the array or not\n");
scanf("%d", &selection);
temporary = binary_search(Ferrari, selection, start, end);
return 0;
}
I keep getting the answer that the search key is positioned in ``0 of array Ferrari. How do I resolve this?
Please let me know what I'm doing wrong over here. Much appreciated.
Look at this line
end = i - 1;
Where is i initialized?
In your loop you have
for(int i=0........
Note by giving int i=0 it means you are creating a new variable i within the for block. So this doesn't alter your original i variable declared at the top. Try using end = size - 1 or it's a best practice to define a constant for this purpose.
#define ARR_SIZE 10
in loop
for(i=0; i<ARR_SIZE;i++)
Then initialize end = ARR_SIZE -1;
And one more thing in your binary_search function is that you don't handle the case when the key is not present in the array.
Something like
if(end==start && array[end] != search)
return -1;
This checks when the search space has only one element and that is not your search element, it means it doesn't exist so we return -1.
Hope this helps
The problem is occurring because you are using uninitialised variable i here:
end = i -1;
Note that the scope of variable i declared in loop init clause is different from the scope of variable i declared in function block.
for(int i=0; i<10; i++){
^^^^^^^
// The scope of i declared in loop init clause is limited to the loop.
To fix the problem, you can use the i declared at function block scope as the loop variable, like this
for(i=0; i<10; i++){
Now, after the loop finishes, the variable i will hold its last value until it's value explicitly modify. But using i to identify the size of array down the code may cause several problems as it is not tightly coupled with the size of array and i may be get modified by other part of code. So, it is not the right idea to use i to identify the size of array.
Since, you are having a variable size which hold the size of array Ferrari, you can do:
end = size - 1;
No need to have another variable to keep the track of size of array. The problem with this is that you have to keep updating the size whenever you change the array size. An alternative of this would be to use a macro to define the array size.
The most appropriate way to set the end of array would be:
end = (sizeof(Ferrari) / sizeof(Ferrari[0])) - 1;
I'm trying to create a hash table. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 19
#define c1 3
#define c2 5
#define m 3000
int efort;
int h_table[N];
int h(int k, int i)
{
return (k + i*c1 + i*i*c2) % N;
}
void init()
{
for (int i = 0; i < N; i++)
h_table[i] = -1;
}
void insert(int k)
{
int position, i;
i = 0;
do
{
position = h(k, i);
printf("\n Position %d \n", position);
if (h_table[position] == -1)
{
h_table[position] = k;
printf("Inserted :elem %d at %d \n", h_table[position], position);
break;
}
else
{
i += 1;
}
} while (i != N);
}
void print(int n)
{
printf("\nTable content: \n");
for (int i = 0; i < n; i++)
{
printf("%d ", h_table[i]);
}
}
void test()
{
int a[100];
int b[100];
init();
memset(b, -1, 100);
srand(time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand() % (3000 + 1 - 2000) + 2000;
}
for (int i = 0; i < N ; i++)
{
insert(a[i]);
}
print(N);
}
int main()
{
test();
return 0;
}
Hash ("h") function and "insert" function are took from "Introduction to algorithms" book (Cormen).I don't know what is happening with the h function or insert function. Sometimes it fills completely my array, but sometimes it doesn't. That means it doesn't work good. What am I doing wrong?
In short, you are producing repeating values for position often enough to prevent h_table[] from being populated after only N attempts...
The pseudo-random number generator is not guaranteed to produce a set of unique numbers, nor is your h(...) function guaranteed to produce a mutually exclusive set of position values. It is likely that you are generating the same position enough times that you run out of loops before all 19 positions have been generated. The question how many times must h(...) be called on average before you are likely to get the value of an unused position? should be answered. This may help to direct you to the problem.
As an experiment, I increased the looping indexes from N to 100 in all but the h(...) function (so as not to overrun h_table[] ). And as expected the first 5 positions filled immediately. The next one filled after 3 more tries. The next one 10 tries later, and so on, until by the end of 100 tries, there were still some unwritten positions.
On the next run, all table positions were filled.
2 possible solutions:
1) Modify hash to improve probability of unique values.
2) Increase iterations to populate h_table
A good_hash_function() % N may repeat itself in N re-hashes. A good hash looks nearly random in its output even though it is deterministic. So in N tries it might not loop through all the array elements.
After failing to find a free array element after a number of tries, say N/3 tries, recommend a different approach. Just look for the next free element.
My problem has to do with passing an array of integers to a function by passing the array's address. The integer array functions properly outside the function, but not inside. Most of what I've written up is just to give some extra details that may or may not be useful. To get the real gist of the problem you can skip to TL;DR at the bottom.
There are two structs:
lineType is a struct consisting of two integer values (valid and tag)
typedef struct
{
int valid;
int tag;
} lineType;
setType is a struct consisting of a pointer to a grouping of lines and a pointer to a grouping of integers.
typedef struct
{
lineType * lines;
int * iruQueue;
}
I have a pointer to a grouping of setTypes called cache (for anyone familiar with computer systems, this object is used to represent a cache system. A cache has a number of sets, each with a number of lines containing a tag, a bit indicating whether or not the line holds valid information, and a byte offset for the actual information the line holds. None of this is really required for my main question, but I thought this might clarify what I am attempting to do).
So we have setType * cache.
I have created a function that will allocate the proper space for the cache called initCache. Again, not sure if this information is necessary, but I want to throw out all the detail I can.
setType * initCache(int NoSets, int NoLines)
int i, j;
setType * cache;
//allocates the appropriate space for the sets
cache = malloc(sizeof(setType) * NoSets);
for(i = 0; i < NoSets; i++)
{
//allocates the space for the lines and the integer array
cache[i].lines = malloc(sizeof(lineType) * NoLines);
cache[i].iruQueue = malloc(sizeof(int) * NoLines);
}
//initializes all valid bits to 0 and the iruQueue entries to -1
for(i = 0; i < NoSets; i++)
for(j = 0; j < NoLines; j++)
{
cache[i].lines[j].valid = 0;
cache[i].iruQueue[j] = -1;
}
return cache;
}
So that is essentially the cache constructor. No problems there. There's a ton more code that I've written, but it all functions correctly after thorough testing.
A little more background: the iruQueue integer array is used to keep track of the least recently accessed line of a set. Ex: I have four lines, the array is initialized as an int * that looks like (-1, -1, -1, -1). Line 0 is accessed. (0, -1, -1, -1). Line 1 is accessed. (0, 1, -1, -1). Line 2 is accessed (0, 1, 2, -1). Line 0 is accessed again. (1, 2, 0, -1)
Here's my problem: at some point I want to pass the integer array to a function that will modify it within the cache. I have two functions for this purpose, enqueue and dequeue. Here's the enqueue function.
void enqueue(int ** iruQueue, int noLines, int lineNo)
{
int cached = 0;
int i;
for(i = 0; i < noLines; i++) {
if(*iruQueue[i] == -1 && cached == 0) {
*iruQueue[i] = lineNo;
cached = 1;
}
}
}
In the above function, I pass a pointer to the specific iruQueue array I want to modify as well as the number of lines in a set and the number of the line just used. It searches through the iruQueue, finds the first index with a value of -1 (indicating that the index is unused) and replaces it with the line number. I pass a specific iruQueue to this function like this.
cache(&(cache[setIndex].iruQueue), noLines, lineNo);
So here's where I really have a problem. I noticed that that it would work on the first call of enqueue, but wouldn't work properly on subsequent enqueues/dequeues.
Printing the specific queue like this prior to enqueues/dequeues (with NoSets being the number of setTypes in the cache array and NoLines being the number of lines in the set array)
int i, j;
for(i = 0; i < NoSets; i++) {
for(j = 0; i < NoLines; j++)
printf("%d, ", cache[i].iruQueue[j])
}
yields the following: "-1, -1, -1, -1, " when there are four lines and 1 set. After one enqueue with a lineNo of 0, it yields "0, -1, -1, -1, ". Proper functioning ends there.
I was curious, so within my enqueue function I added some code to print the iruQueue array before and after modification.
void enqueue(int ** iruQueue, int noLines, int lineNo)
{
int cached = 0;
int i;
//checks the iruQueue array prior to modification
printf("Before: \n");
for(i = 0; i < noLines; i++) {
printf("%d : %d\n", i, iruQueue[i]);
}
for(i = 0; i < noLines; i++) {
if(*iruQueue[i] == -1 && cached == 0) {
*iruQueue[i] = lineNo;
cached = 1;
}
}
//checks the iruQueue array after modification
printf("After: \n");
for(i = 0; i < noLines; i++) {
printf("%d: %d\n", i, iruQueue[i]);
}
}
Here's what it prints when we start with the unmodified iruQueue array (meaning all values should be -1), the number of lines being 4, and the line number being 0.
Before:
0 : -1
1 : 0
2 : -1
3 : 0
After:
0 : 0
1 : 0
2 : -1
3 : 0
It appears as though the iruQueue being modified has changed in that there are zeroes between each proper value. If I changed the print function to print through noLines * 2, the pattern would continue as such. That's my problem. When the iruQueue isn't passed to the enqueue/dequeue functions and I print its contents the same exact way, it will print correctly with no extra indices containing zeroes. Why would passing it as such change it like that, and is there anything I can do to fix it?
TL;DR
I pass an integer array (int * iruQueue) to a function by passing the address of the int array to the function ( &(cashe[setIndex].iruQueue) ). Outside the function it operates as it should, but when passed to the function it creates extra indices with 0 values inbetween each of the correct indices. How do I correct this problem?
If any more code/clarification is needed I will happily provide it. Also, if I'm doing this whole thing wrong (writing up waaaaayyyyy too much or something) just let me know- while I read a lot of things on this website to help my issues, I don't really ever post here, so I just wanted to be as thorough as possible.
Thanks!
Actually, your double pointer isn't needed here and complicates matters. You dereference it when accessing, but don't when printing (which is wrong; I wonder why it doesn't crash or produce more "random" output…). Simply reduce it to a single pointer:
void enqueue(int * iruQueue, int noLines, int lineNo)
{
int cached = 0;
int i;
for(i = 0; i < noLines; i++) {
if(iruQueue[i] == -1 && cached == 0) {
iruQueue[i] = lineNo;
cached = 1;
}
}
}
void foo()
{
enqueue(cache[setIndex].iruQueue, noLines, lineNo);
}
I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.