I'm stuck trying to implement pseudocode from an algorithm book. My code compiles and prints out the correct answer, except some of the information I want to print out is not displaying correctly. Here's what the console output looks like:
Correct Solution Tested:
max_left= 7
max_right= 10
sum= 43
Failing Outputs:
curr_cross_low = 17; curr_cross_high = -1; curr_cross_sum = 38
curr_cross_low = -1; curr_cross_high = -1; curr_cross_sum = 18
curr_cross_low = 32766; curr_cross_high = -272632720; curr_cross_sum = 43
max_left_full= 32766
max_right_full= -272632512
sum_full= 43
Program ended with exit code: 0
The first three values printed are the correct results arrived by brute implementation of one part of the algorithm. In the code, this is the function "findMaxCrossingSubarray" all by itself. The second part printed out is when I execute the full algorithm "findMaximumSubarray". I believe it should be printing out results that show approaching the solution. The final answer given by the variable "sum_full" appears to be correct since it matches the brute force solution which the book says is the correct answer.
I've been trying to find how I can print the correct max_left_full and max_right_full values and not what I believe is the memory address. I'm at a point where if I change a pointer in one place it makes the solution incorrect or print out a memory address as well.
Is there a simple way to find where I may be dropping the ball?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//returns a pointer to a value equal to the set of changes
int * returnPriceChanges(int sz, int A[]){
int MAX_SIZE = 256;
static int* C;
C = malloc(MAX_SIZE *sizeof(int));
int i;
for(i=0;i<sz-1;i++){
C[i]=A[i+1]-A[i];
}
return C;
}
int findMaxCrossingSubarray(int A[], int low, int mid, int high, int* max_left, int* max_right){
double left_sum = -INFINITY;
int sum = 0;
for(int i=mid;i>=low;i--){
sum=sum+A[i];
if(sum > left_sum){
left_sum = sum;
*max_left = i;
}
}
double right_sum = -INFINITY;
sum = 0;
for(int j=mid+1; j<=high;j++){
sum=sum+A[j];
if(sum > right_sum){
right_sum = sum;
*max_right = j;
}
}
return (*max_left, *max_right, left_sum+right_sum);
}
int findMaximumSubarray(int A[], int low, int high){
int curr_left_low, curr_left_high, curr_left_sum;
int curr_right_low, curr_right_high, curr_right_sum;
int curr_cross_low, curr_cross_high, curr_cross_sum;
int mid = 0;
int* temp_max_left, temp_max_right;
if(high==low){
return(low, high, A[low]);
}
else{
mid =floor((high+low)/2);
curr_left_low, curr_left_high, curr_left_sum = findMaximumSubarray(A, low, mid);
curr_right_low, curr_right_high, curr_right_sum = findMaximumSubarray(A, mid+1,high);
curr_cross_low, curr_cross_high, curr_cross_sum = findMaxCrossingSubarray(A, low, mid, high, &temp_max_left, &temp_max_right);
if(curr_left_sum>=curr_right_sum && curr_left_sum>=curr_cross_sum){
return (curr_left_low, curr_left_high, curr_left_sum);
}
else if(curr_right_sum>= curr_left_sum && curr_right_sum>=curr_cross_sum){
return (curr_right_low, curr_right_high, curr_right_sum);
}
else{
printf("curr_cross_low = %d; curr_cross_high = %d; curr_cross_sum = %d\n", curr_cross_low, curr_cross_high, curr_cross_sum);
return (curr_cross_low, curr_cross_high, curr_cross_sum);
}
}
}
int main(){
int prices[] = {100,113,110,85,105,102,86,63,81,101,94,106,101,79,94,90,97};
int szPrices = sizeof(prices)/sizeof(prices[0]);
int changes[szPrices-1];
int *P;
P = returnPriceChanges(szPrices,prices);
//set C = to list of changes
for(int i=0; i<szPrices-1; i++){
changes[i]=*(P+i);
}
int max_left, max_right, sum;
max_left, &max_right, sum = findMaxCrossingSubarray(changes, 0, 8, 16, &max_left, &max_right);
printf("\nCorrect Solution Tested: \nmax_left= %d \nmax_right= %d \nsum= %d\n\n", max_left, max_right, sum);
printf("\nFailing Outputs:\n");
int max_left_full, max_right_full, sum_full;
max_left_full, &max_right_full, sum_full = findMaximumSubarray(changes, 0, 16);
printf("\nmax_left_full= %d \nmax_right_full= %d\nsum_full= %d\n\n", max_left_full, max_right_full, sum_full);
return 0;
}
You cannot return tuples from functions in C. When you separate values using a comma in C, the whole expression simply evaluates to the last member.
So when you write:
a, b, c = some_function();
It really means:
/* do nothing */, /* do nothing */, c = some_function();
If you want to return a composite data structure, use a struct, i.e.
struct subarray
{
int low;
int high;
int sum;
};
void findMaximumSubarray(int A[], int low, int high, struct subarray * result);
If the struct is small and you are using a modern compiler, and not running on an embedded system, then you can also return the struct by value:
struct subarray findMaximumSubarray(int A[], int low, int high);
The latter syntax simplifies usage, but it can become an issue if you start returning huge structs this way.
Related
Question: Given two arrays of integers A[] and B[] of size N and M, the task is to check if a pair of values (one value from each array) exists such that swapping the elements of the pair will make the sum of two arrays equal.
My approach:
find sum of both arrays.
Identify array with larger sum(denote with A[]).
Sort A.
For all values in B binary search (sum(A)-sum(B)/2 + B[i]) in A, if found return true.
Return false.
code:
int sum(int a[], int n){
int s=0;
for(int i=0; i<n; i++){
s+= a[i];
}
return s;
}
int findSwapValues(int A[], int n, int B[], int m)
{
// Your code goes here
int a = sum(A, n);
int b = sum(B,m);
int t;
int *temp;
if(a<b){
temp = A;
A = B;
B = temp;
t = n;
n = m;
m = t;
t = a;
a = b;
b = t;
}
sort(A, A+n);
for(int i=0; i<m; i++){
if(binary_search(A,A+n,(a-b)/2+B[i])){
return 1;
}
}
return -1;
}
Doubt: My algorithm is failing for some test cases(not TLE). As the test cases are very large, it's difficult to reason out the problem in the algorithm. I searched online and understood other approaches. My only curiosity is why its incorrect?
I think the error in your code is that you find B[i] + (a-b)/2.
The problem with this is that if (a-b) is an odd value, division by 2 will round it down to the nearest integer and you end up finding the wrong value.
What you can instead do is check if the difference is odd before even swapping the arrays, and if it is true, straight-away return -1 because if the difference is odd, no such pair can ever exist.
I hope I cleared your doubt :).
im learning C and i am a bit confused with array handling.
I have a task that asks me to sum up 2 arrays of non negative integers.
example array 1 = {1,2,3} , array 2 = {4,5,6} -> 123+456 = 579
I searched a bit for a solution on how to convert those arrays of integers to an integer, but didnt really get helpful information.
I ended up with a code:
#include <stdio.h>
int sum(int A[],int B[], int n){
int i,j,t,k;
for(i=0;i<n;i++){
t= t+A[i];
}
for(j=0;j<n;j++){
k= k+B[j];
}
return t+k;
}
int main()
{
int n = 3;
int a[n] = {1,2,3};
int b[n] = {4,5,6};
printf("%d",sum(a,b,n));
return 0;
}
But my result is 1225283 which of course is wrong.
I found a solution where people write something like "t= 10* t+A[i]" , i dont get where that "10* " comes from, but i tested it and then "t" gets "123" but if i try the same for "k" it doesnt work, returning "k" doesnt give me "456". I am a bit confused, whats the proper way of handling this problem?
Thanks for any help.
You're basically adding digits 1+2+3 instead of creating the number 123. Your code also has various other flaws, like uninitialized variables. Here is a working example:
int array2int(int A[], int n) {
int ret = 0;
for(int i=0, k=1; i<n; i++){
ret = ret + k * A[i];
k *= 10;
}
return ret;
}
int sum(int A[],int B[], int n){
return array2int(A, n) + array2int(B, n);
}
First of all, in sum function, you haven't initialized neighter t nor k but you keep summing them and use later, so every time your code is executed, you chould get different result.
On the other hand, in something like "t= 10 t+A[i]", 10 comes from basic math, where a number could be resolved as a10^0 + b10^1 +c*10^2 + .... + m * 10^n. As a result, starting from least significant digit, everytime you try to add new digit (from least to most significant), you need your multipliciant to be 10 times greater.
int sum(int A[],int B[], int n){
int i,j,t=0,k=0,ten=1;
for(i=n-1;i>=0;i--){
t += ten*A[i];
ten *= 10;
}
ten = 1; /* initialize again*/
for(j=n-1;j>=0;j--){
k += ten*B[j];
ten *= 10;
}
return t+k;
}
Something like that should work.
I'm trying to write a recursive function to find duplicates in an array of integers. For example if the array is: {4, 1, 4, 3, 2, 3} it should returns 2.
I tried a mergesort-like approach but without success. Someone can help?
My try (works only with ordered arrays):
int count(int arr[], int bot, int top){
if(bot==top) return 0;
else{
int med = (bot+top)/2;
int n = count(arr, bot, med) + count(arr, med+1, top);
if(arr[med]==arr[med+1]) n++;
return n;
}
}
You are just checking if arr[med]==arr[med+1] which will have a problem when you have a case like 111 then the count will become two but the count should actually be one. So add an extra flag to check if the same element is repeated or not.
Sort the array. May be you can use merge sort or something to do that and then something like this should work!
#include <stdio.h>
int main(void) {
// your code goes here
int a[16] = {1,1,1,1,1,1,1,1,1,1,1,2,2,3,3,5};
int out = count(a,0,15);
printf("%d\n",out);
return 0;
}
int count(int arr[], int bot, int top){
int flag = 0;
if(bot==top) return 0;
else{
int med = (bot+top)/2;
int n = count(arr, bot, med) + count(arr, med+1, top);
if(arr[med]==arr[med+1])
{
flag = arr[med-1];
if(flag != arr[med])
n++;
}
return n;
}
}
Given a value N, if we want to make change for N cents, and we have infinite supply of each of S = { S1, S2, .. , Sm} valued coins, how many ways can we make the change? The order of coins doesn’t matter.
I have written below code but it is always returning one less than the actual answer. I want to know if this is the right way of coding up the solution?
#include <stdio.h>
int ways=0;
int remember[100] = {0};
void foo(int coin_denomination[], int size, int sum)
{
int i;
printf("%d\n", sum);
if (sum==0) {
ways++;
return;
}
if (remember[sum]==1)
return;
remember[sum] = 1;
if (sum < 0)
return;
for(i=0;i<size;i++)
foo(coin_denomination, size, sum-coin_denomination[i]);
}
int main()
{
int coin_denomination[] = {1, 2, 3};
int sum = 5;
foo(coin_denomination, sizeof(coin_denomination)/sizeof(coin_denomination[0]), sum);
printf("%d\n", ways);
return 0;
}
You need some change to foo method. Your problem is that with the variable remember you are not counting some solutions. The goal of variable remember is not correct, you are using for not processing the same coin collection multiple times but you are saving only the sum of the coin collection and the sum could be obtained with multiple coin collections (ex: 1 1 1 have same sum that 1 2 when you select the second, remember[3] would be 1 and not be passing this point, missing solution 1 2 2)
Other way of not repeating coin collection is needed, in this case, adding a parameter that represent the index of coin_denomination that is processing and only allow processing of coin after, the problem is solve.
Code (Tested with GCC 4.9.0):
#include <stdio.h>
int ways=0;
void foo(int coin_denomination[], int size, int sum, int coin_idx = 0)
{
if (sum < 0)
return;
int i;
printf("%d\n", sum);
if (sum==0) {
ways++;
return;
}
for(i=coin_idx;i<size;i++)
foo(coin_denomination, size, sum-coin_denomination[i], i);
}
int main()
{
int coin_denomination[] = {1, 2, 3};
int sum = 5;
foo(coin_denomination, sizeof(coin_denomination)/sizeof(coin_denomination[0]), sum);
printf("%d\n", ways);
return 0;
}
What should i do to remove a value from min heap when the left and right child are equal and smaller than their parent. For example i have a value 0 on the root of my min heap and want to remove it. I'll swap 0 with the last element of my vector(value=12), after that, i need to run the function that turns the vector into a min-heap again(min-heapfy), but in my example i exchanged 0 with 12, and now 12 is on the root and 0 will be soon returned. I have to swap 12 with the left child(1) or right child(1), how can i know which of this number 1 entered in the vector first?
#include <stdio.h>
#include <stdlib.h>
int left(int i){
return 2*i;
}
int right(int i){
return 2*i +1;
}
void swap_pos(int *vi, int *vm){
int aux;
aux = *vi;
*vi = *vm;
*vm = aux;
}
void heapify(int *v, int i,int heap_size){
int l,r,menor_ind = i;
l = left(i);
r = right(i);
if(l<=heap_size && v[l]<v[i]) menor_ind = l;
if(r<=heap_size && v[r]<v[menor_ind]) menor_ind = r;
if(menor_ind!= i){
swap_pos(&v[i],&v[menor_ind]);
heapify(v,menor_ind,heap_size);
}
}
void build_min_heap(int v[],int heap_size){
int i;
for(i=heap_size/2; i>=1; i--){
heapify(v,i,heap_size);
}
}
int extract(int *v, int *heap_size){
int ret = v[1];
if(*heap_size==0) return -1;// erro
swap_pos(&v[*heap_size],&v[1]); // swap root with the last element
(*heap_size)--;
heapify(v,1,*heap_size);
return ret;
}
void heap_sort(int *v, int *heap_size){
while(*heap_size>=2){
swap_pos(&v[1],&v[*heap_size]);
(*heap_size)--;
heapify(v,1,*heap_size);
}
}
int main(void){
int heap_size = 9;
int i, v[] = {-1,6,12,3,1,5,0,1,9,7};
build_min_heap(v,heap_size);
printf("%d\n",extract(v,&heap_size));
//heap_sort(v,&heap_size);
for(i=1; i<=heap_size; i++){
printf("%d ",v[i]);
}
return 0;
}
As far as the heap goes, 1 and 1 are equal. (Indeed, that is generally true.) So it doesn't matter which 1 becomes the new root. The 12 will percolate up the heap until it finds some place to rest, possibly at the fringe but not necessarily. There's nothing which requires it to get back to where it came from, and it's very likely that it won't.
Why do you think the code you present isn't correct?