Calculating lowest subtotal of array in C - arrays

I want to search for the lowest subtotal of k values in an array z with n elements, filled by user input. This works fine with k==1 but I do not understand why my code does not work for k>1.
My program outputs the wrong index and subtotal.
The function is being called from main, after filling the array with n elements of int values in a loop until it's filled, asking for the desired length of k.
Please help me understand what I'm doing wrong
#include <stdio.h>
void lowest_subtotal(int z[], int n, int k){
int t[]={0};
int i = 0, position = 0, tempmin;
if(k==1){ //working 100%
while(i<n){
if(z[i]<tempmin){
tempmin=z[i];
position=i;
}
i++;
}
printf("Lowest subtotal on Index %d. (sum: %d.)", position, tempmin);
}
else{
//calculate subtotals
while(i<=n){
for(int j=0; j<k; j++){
if(z[i+j]<0){
t[i] -= z[j];
}
else{
t[i] += z[j];
}
}
i++;
}
//search for lowest subtotal
i = 0;
while(i<n-k+1){
if(t[i] < tempmin){
tempmin = t[i];
position=i;
}
i++;
}
//wrong result of index and sum?
printf("Lowest subtotal on Index %d. (sum: %d.)",position-k-1,tempmin);
}
}
int main(){
int n,k; //length of vector, length of subtotal
printf("n: ");
scanf("%d",&n);
int z[99] = { 0 }; //initialize array
printf("input elements:\n");
for(int i=0; i<n; i++){
scanf("%d",&z[i]);
}
printf("length of subtotal?: ");
scanf("%d",&k);
lowest_subtotal(z,n,k);
}

It will be much easier for you if you split it into separate tasks (functions.
long long subtotal(int *arr, size_t size, size_t start, size_t k)
{
long long result = 0;
for(size_t index = 0; index < k; index ++)
{
result += arr[start + index];
}
return result;
}
long long smallestSubtotal(int *arr, size_t size, size_t k, size_t *startpos)
{
long long result = LLONG_MAX;
for(size_t start = 0; start < size - k; start++)
{
long long sum = subtotal(arr, size, start, k);
if(result > sum)
{
if(startpos) *startpos = start;
result = sum;
}
}
return result;
}
void lowest_subtotal(int z[], size_t n, size_t k)
{
size_t index;
long long subt;
subt = smallestSubtotal(z, n, k, &index);
printf("The smallest subtotal of length %zu is %lld at index %zu\n", k, subt, index);
}
int main(void)
{
int arr[SIZE];
srand(time(NULL));
for(size_t index = 0; index < SIZE; index++)
{
arr[index] = rand();
}
lowest_subtotal(arr, SIZE, 15);
}

As I understand from the OP code, the task is to find the starting index of k consecutive numbers in an array of n numbers such that the sum of the k numbers is minimal.
The case of k=1 need not be a special case. Besides, the idea of updating the sum of a "window" of k elements is good, but there are several errors in the implementation. A working version of lowest_subtotal() could be as follows:
#include<limits.h>
int lowest_subtotal(int z[], int n, int k)
{
if(k > n || k < 1)
{
return -1; // Error, k must be in the range from 1 to n
}
// Calculate sum in window at index 0
int sum = 0;
for(int i = 0; i < k; i++)
{
sum += z[i];
}
// Slide window and update sum
int index = 0;
int min_sum = sum;
for(int i = 1; i < n - k; i++)
{
sum += z[i+k-1] - z[i-1]; // Add incoming value and subtract the leaving value
if(sum < min_sum)
{
min_sum = sum;
index = i;
}
}
printf("Lowest subtotal at index %d (sum=%d)\n", index, min_sum);
return index;
}

Related

Swapping largest and smallest numbers in C

I want to write a program that reads 10 int values from the user and swaps the largest and smallest numbers on the first and second values, then the rest of the numbers should be in the order.
Please check the code and help me what the wrong is.
For instance:
1
9
4
5
6
7
8
2
4
5
New order should be 9 1 4 5 6 7 8 2 4 5
#include <stdio.h>
int main() {
int a[10],i,min,max=0,pos=0;
printf("Please enter 10 int values :\n");
do{
scanf("%d", &a[pos++]);
} while (pos<10);
for (i=0; i<10;i++) {
printf("%i\n",a[i]);
if (max<a[i])
{
max=a[i];
}
if (min>a[i])
{
min=a[i];
}
for (i=0;i<10;i++) {
if (a[i]==max)
a[i]=max;
if (a[i] == min) a[i] = min;
}
printf("The new order is : %d %d %d ", max, min, ...);
return 0;
}
EDIT:
It is the new form
#include <stdio.h>
int main() {
int a[10],i,pos,temp,min = 0,max = 0;
printf("Please enter 10 int values :\n");
do {
scanf("%d", &a[pos++]);
} while (pos < 10);
for ( =1; i<10;i++) {
if (a[i]>a[max])
{
max=i;
}
if (a[i]<a[min])
{
min=i;
}
}
temp=a[max];
a[max]=a[min];
a[min]=temp;
printf("%d %d",a[max],a[min]);
for (i=0;i<10;i++){
if ((i != min) && (i != max)) {
printf("%d ", a[i]);
}
}
printf("\n");
return 0;
}
As others have noted, your code does not properly identify the maximum and minimum values in the array because you are writing min and max back into the array instead of the other way around.
Since you want to swap these values, what you actually want are the indices of the min and max values of the array, and swap those.
It is best to break this code into functions instead of having everything in main. Here is a solution that will do what you want:
#include <stdio.h>
int indexofmax(int *data, int len)
{
int max = 0;
int i;
for(i = 0; i < len; i++)
{
if(data[i]>data[max]) max = i;
}
return max;
}
int indexofmin(int *data, int len)
{
int min = 0;
int i;
for(i = 0; i < len; i++)
{
if(data[i]<data[min]) min = i;
}
return min;
}
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
// user enters in 10 ints...
int max = indexofmax(a, 10);
int min = indexofmin(a, 10);
int i;
swap(&a[min], &a[max]);
for(i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
This initialization min=0,max=0 is not right.
Instead have min = INT_MAX and max = INT_MIN.
By setting min=0, you would never get the lowest number in the array if it is greater than 0.
Similarly by setting max=0, you would never get the greatest number in the array if it is lower than 0.
You are gaining nothing by this code:
for(i=0;i<10;i++)
{ if(a[i]==max) a[i]=max;
if(a[i]==min) a[i]=min; }
It is evident that this loop
for(i=0;i<10;i++)
{ if(a[i]==max) a[i]=max;
if(a[i]==min) a[i]=min; }
does not make sense.
Moreover variable min is not initialized while variable max is initialized incorrectly.
int a[10],i,min,max=0,pos=0;
For example the array can contain all negative elements. In this case you will get incorrect value of the maximum equal to 0.
And I do not see where the elements are moved to the right to place the maximum and the minimum to the first two positions of the array.
If I have understood correctly then what you need is something like the following. To move the elements you could use standard function memmove declared in header <string.h>. However it seems you are learning loops.
#include <stdio.h>
#define N 10
int main( void )
{
int a[N] = { 4, 5, 9, 6, 7, 1, 8, 2, 4, 5 };
for (size_t i = 0; i < N; i++) printf("%d ", a[i]);
printf("\n");
size_t min = 0;
size_t max = 0;
for (size_t i = 1; i < N; i++)
{
if (a[max] < a[i])
{
max = i;
}
else if (a[i] < a[min])
{
min = i;
}
}
if (max != min)
{
int min_value = a[min];
int max_value = a[max];
size_t j = N;
for (size_t i = N; i != 0; --i)
{
if (i - 1 != min && i - 1 != max)
{
if (i != j)
{
a[j - 1] = a[i - 1];
}
--j;
}
}
a[--j] = min_value;
a[--j] = max_value;
}
for (size_t i = 0; i < N; i++) printf("%d ", a[i]);
printf("\n");
}
The program output is
4 5 9 6 7 1 8 2 4 5
9 1 4 5 6 7 8 2 4 5
You're not actually altering the array.
In the second loop, you say "if the current element is the max, set it to the max". In other words, set it to its current value. Similarly for the min.
What you want is to swap those assignments.
if(a[i]==max) a[i]=min;
if(a[i]==min) a[i]=max;
Also, your initial values for min and max are no good. min is unitialized, so its initial value is undefined. You should initialize min to a very large value, and similarly max should be initialized to a very small (i.e. large negative) value.
A better way to do this would be to keep track of the index of the largest and smallest values. These you can initialize to 0. Then you can check a[i] > a[max] and a[i] < a[min]. Then you print the values at indexes min and max, then loop through the list and print the others.
int i, temp, min=0, max=0;
for (i=1; i<10; i++) {
if (a[i] > a[max]) max = i;
if (a[i] < a[min]) min = i;
}
printf("%d %d ", a[max], a[min]);
for (i=0; i<10; i++) {
if ((i != min) && (i != max)) {
printf("%d ", a[i]);
}
}
printf("\n");
Just keep it nice and simple, like this:
#include <stdio.h>
#include <stdlib.h>
#define MAXNUM 10
int find_biggest(int A[], size_t n);
int find_smallest(int A[], size_t n);
void print_array(int A[], size_t n);
void int_swap(int *a, int *b);
int
main(void) {
int array[MAXNUM], i, smallest, biggest;
printf("Please enter 10 int values:\n");
for (i = 0; i < MAXNUM; i++) {
if (scanf("%d", &array[i]) != 1) {
printf("invalid input\n");
exit(EXIT_FAILURE);
}
}
printf("Before: ");
print_array(array, MAXNUM);
smallest = find_smallest(array, MAXNUM);
biggest = find_biggest(array, MAXNUM);
int_swap(&array[smallest], &array[biggest]);
printf("After: ");
print_array(array, MAXNUM);
return 0;
}
int
find_biggest(int A[], size_t n) {
int biggest, i, idx_loc;
biggest = A[0];
idx_loc = 0;
for (i = 1; i < n; i++) {
if (A[i] > biggest) {
biggest = A[i];
idx_loc = i;
}
}
return idx_loc;
}
int
find_smallest(int A[], size_t n) {
int smallest, i, idx_loc;
smallest = A[0];
idx_loc = 0;
for (i = 1; i < n; i++) {
if (A[i] < smallest) {
smallest = A[i];
idx_loc = i;
}
}
return idx_loc;
}
void
print_array(int A[], size_t n) {
int i;
for (i = 0; i < n; i++) {
printf("%d ", A[i]);
}
printf("\n");
}
void
int_swap(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}

Copying elements from an array to another one and counting the number of a character in C

I'm new to C, so I apologize for asking silly questions.
I need to copy certain elements from an array to another one, but I can't make it work and get random numbers instead. In this case I need all the elements after the smallest one from the first array to be copied to the second one.
The other thing I can't figure out is a function that counts how many times a certain symbol is used. I need to find the number of times I've used the biggest odd digit in an array.
Here's the code, I've made so far. I hope you understand most of it:
#include <stdio.h>
#define DIM 100
int enter (int x[]);
int min (int x[], int y[], int n);
int sort (int x[], int n);
void print (int x[], int n);
//=============================================
int main () {
int a[DIM], b[DIM], n, i;
n = enter (a);
printf("The smallest element in the first array: %d.\n The smallest element in the second array: %d.\n", min (a, b, n));
printf("%d\n", sort (b, n));
for (i = 0; i < n; i++)
printf ("%d ", b[i]);
printf ("\n");
system("pause");
return 0;
}
//===========================================================
int enter (int x[]) {
int i, n;
do {
printf ("Enter number of elements in array: ");
scanf ("%d", &n);
}
while (n < 1 || n > DIM);
printf ("Enter %d elements:\n", n);
for (i = 0; i < n; i++)
scanf ("%d", &x[i]);
return x[i], n;
}
int min (int x[], int y[], int n) {
int minimum, i, j=0, p;
minimum = x[0];
for ( i = 1 ; i < n ; i++ ) {
if ( x[i] < minimum ) {
minimum = x[i];
p = i+1;
}
}
for (i = p+1; i<n; i++ && j++) {
x[i] = y[j];
}
return minimum;
}
int sort (int x[], int n) {
int i, j, a;
for (i = 0; i < n; ++i) {
for (j = i + 1; j < n; ++j) {
if (x[i] > x[j]){
a = x[i];
x[i] = x[j];
x[j] = a;
}
}
}
printf("Elements from array in ascending order: \n");
for (i = 0; i < n; ++i)
printf("%d\n", x[i]);
return x[i];
}
I need to find the number of times I've used the biggest odd digit in
an array.
Fist sort your array start at the end and find the biggest odd number. You can find a odd number by number%2==1. Finally count equal numbers:
// sort the array
sort(b, n); // sort function from your questions code
// find the biggest odd number
int i = n-1;
while ( i >= 0 && b[i]%2 == 0 )
{
i --;
}
// count the biggest odd number
count = 0;
int j = i;
while ( j >= 0 && b[i]==b[j] ) // note first time i==j !
{
count ++;
j --;
}
If you don't want to sort your array use this:
// find the biggest odd number
int oddInx = -1;
for ( int i = 0; i < n; i++ )
{
if ( b[i]%2 == 1 && ( oddInx < 0 || b[i] > b[oddInx] ) )
oddInx = i;
}
// count the biggest odd number
count = 0;
if ( oddInx >= 0 )
{
for ( int i = 0; i < n; i++ )
{
if ( b[i] == b[oddInx] )
count ++;
}
}

Having trouble with the function in C

I wrote this program to calculate the scalar product and find out the smallest as well as the biggest number (+ there position) of the vector v. Everything works fine except for the lowest_number function. It find the lowest number inside the vector v and the position as well,but when the position is at v[0] ----> at 1 it displays a really long number. I am not sure why this happens. PLease help thank you very much
int scalar_produc(int *v,int *w,int n)
{
int i = 0;
int sp;
int sp2 = 0;
for(i= 0; i < n; i++)
{
sp = v[i] * w[i];
sp2 = sp2 + sp;
}
return sp2;
}
int lowest_number(int *v,int n)
{
int i = 0;
int low = v[i];
int position;
for(i = 0; i < n; i++)
{
if(v[i] < low)
{
low = v[i];
position = i;
}
}
printf("The lowest number is: %d \n", low);
printf("The position of it: %d \n",position+1);
}
int biggest_number(int *v, int n)
{
int i = 0;
int position;
int biggest = v[i];
for(i = 0; i < n; i++)
{
if(v[i] > biggest)
{
biggest = v[i];
position = i;
}
}
printf("The biggest number of the vector 'v' is: %d \n",biggest);
printf("The position of the biggest number: %d \n", position+1);
}
int main()
{
int n,i;
int *v,*w;
printf("Enter the number of vectors you would like to enter: \n");
scanf("%d",&n);
v = (int*) malloc(sizeof(int) *n);
w = (int*) malloc(sizeof(int) *n);
printf("Enter the vectors: \n");
for(i = 0; i < n ;i++)
{
printf("v[%d]: \n",i+1);
scanf("%d",&v[i]);
printf("w[%d]: \n",i+1);
scanf("%d",&w[i]);
}
printf("The scalar product: %d \n",scalar_produc(v,w,n));
lowest_number(v,n);
biggest_number(v,n);
free(v);
free(w);
return 0;
}
You don't initialize position. So if the smallest value is the first value, the value of position is undefined.
Initialize it to 0 and it should work.
int i = 0;
int low = v[i];
int position = 0;

Sorting array based on index of minimum value?

I'm currently trying to learn C, and the exercise I found online has me creating a function that returns the index of the smallest value in an array. This is my function:
int return_index_of_minimum(int A[10], int i, int j){
int minimum_value = A[i];
int index_to_return = 0;
for (int index = i; index < j; index++){
if (A[index] < minimum_value){
minimum_value = A[index];
index_to_return = index;
}
}
return index_to_return;
}
i and j are the lower and upper bound numbers the function should look in. For example, if i is 4 and j is 8, that means the function will return the index of the smallest value between indices 4 and 8.
Here is my main function:
#include <stdio.h>
int main(){
int numbers[10];
int user_input = 0;
for (int i = 0; i < 10; i++){
printf("Please enter a number: ");
scanf_s("%d", &user_input);
numbers[i] = user_input;
}
for (int i = 0; i < 10; i++){
int index_of_min_value = return_index_of_minimum(numbers, i, 10);
int old_num = numbers[index_of_min_value];
int new_num = numbers[i];
numbers[index_of_min_value] = new_num;
new_array[i] = old_num;
}
for (int i = 0; i < 10; i++){
printf("%d\n", new_array[i]);
}
}
The user would first enter a bunch of numbers and that would populate the array with the user's values. The idea is to use return_index_of_minimum to return the index of the smallest item in an array, and then set that equal to numbers[0] with a for loop, and then numbers[1], and then so on. old_num is the lowest number in the array, at its previous index. Here, I'm trying to swap that minimum value with whatever is at numbers[i] However, when I'm done sorting through the entire array, and am printing it out, I see that 10 (when the user enters 1-10 randomly for values) is at index 0, and then the rest of the numbers are in order. Does anybody see what is wrong here?
Here is a fix:
int return_index_of_minimum(int A[10], int i, int j){
int minimum_value = A[i];
int index_to_return = i;
...
}
Unfortunately this code doesn't have protection of invalid arguments, but otherwise this is an answer you've been looking for.
The reason is in call index_of_minimum(a, 9, 10): the loop performs only one iteration for index = 9, and because the minimum value is already initialized to value a[9], the index_to_return is not updated due to condition check.
This is a different approach that doesn't have same issue:
int return_index_of_minimum(int A[10], int i, int j){
/* assuming i < j */
int minimum_value = A[i];
int index_to_return = i; /* First element is a candidate */
for (int index = i + 1; index < j; index++){
/* Iterate from second element */
if (A[index] < minimum_value){
minimum_value = A[index];
index_to_return = index;
}
}
return index_to_return;
}
I believe there is an error in your return_index_of_minimum function.
int index_to_return = 0;
The problem lies I think here as the value of index_to_return will stay 0 if you call return_index_of_minimum(numbers, 5, 10); and that numbers[5] if the actual minimum.
However why not use a simple bubble-sort like the one implemented here
/*
* C program to sort N numbers in ascending order using Bubble sort
* and print both the given and the sorted array
*/
#include <stdio.h>
#define MAXSIZE 10
int main(void)
{
int array[MAXSIZE];
int i, j, num, temp;
printf("Enter the value of num \n");
scanf("%d", &num);
printf("Enter the elements one by one \n");
for (i = 0; i < num; i++)
{
scanf("%d", &array[i]);
}
printf("Input array is \n");
for (i = 0; i < num; i++)
{
printf("%d\n", array[i]);
}
/* Bubble sorting begins */
for (i = 0; i < num; i++)
{
for (j = 0; j < (num - i - 1); j++)
{
if (array[j] > array[j + 1])
{
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
printf("Sorted array is...\n");
for (i = 0; i < num; i++)
{
printf("%d\n", array[i]);
}
}

Mergesort of dynamic array of doubles using malloc, memory prob

Hey everyone so my MergeSort algorithm isn't perfect, it's actually the same one that was posted here in a similar question, but that's not even the real problem.
Basically the user inputs an array size, and lower & upper bounds on a range of values to be put into an array of doubles to be mergeSorted.
I can print out the array just fine but after MergeSort it returns whack negative values that I assume are addresses.
I know this has something to do with memory but I have no idea why it's messing up because I believe I allocated memory and cleared it correctly. Here is my code, any insight will be much appreciated especially before 12:00 tonight ;).
Here is main.c, mergesort.c, and mergesort.h. I am also using a makefile but I don't think that is necessary to share.
Main.c:
#include <stdlib.h>
#include <stdio.h>
#include "mergesort.h"
int lower = 0;
int upper = 0;
int n = 0;
int main(int argc,char* argv[]) {
int i = 0; // loop values
int j = 0;
int r = 0; // random number
/*int n = 0; // size of array
int lower = 0; // lower bound on values in array
int upper = 0; // upper ...*/
double *t; //array of doubles
printf("Size of array?\n");
scanf("%d", &n);
printf("Lower Bound?\n");
scanf("%d", &lower);
//globLower = lower;
printf("Upper Bound?\n");
scanf("%d", &upper);
//globUpper = upper;
t = malloc(n * sizeof *t); // allocates n slots of memory
printf("Unsorted Array:\n");
for(i=0; i<n; i++) {
r = lower + arc4random() % (upper - lower);
//printf("%d\n", r);
t[i] = r; // fills array with random values in range
printf("%g\n", t[i]);
}
printf("Before Merge Sort\n");
mergeSort(t,n); // This is supposed to sort the array...
printf("After Merge Sort\n");
i = 0; //reset
// printf("%g\n", t[0]);
printf("%g\n", t[1]);
printf("%g\n", t[2]);
free(t); // Need to free the memory allocated since is stored in the heap
return 0;
}
mergesort.c:
#include <stdlib.h>
#include <stdio.h>
#include "mergesort.h"
void mergeSort(double* t, int n) {
printf("Size: %d\n", n);
printf("Lower: %d\n", lower); // tests
printf("Upper: %d\n", upper);
printf("t[2]: %g\n", t[2]);
int beg = 0;
int end = n-1;
mergeSortHelp(t, beg, end);
}
void mergeSortHelp(double* t, int beg, int end) {
int mid = (end + beg) / 2;
if(beg < end) {
mergeSortHelp(t, beg, mid);
mergeSortHelp(t, mid+1, end);
merge(t, beg, mid, end);
}
}
void merge(double* t, int beg, int mid, int end) {
int sizeLeft = mid - beg + 1;
int sizeRight = end - mid;
double *left = malloc((sizeLeft)*sizeof(double));
double *right = malloc((sizeRight)*sizeof(double));
int i,j,k;
for(i = 0; i < sizeLeft; i++) {
left[i] = t[beg+i];
}
for(j = 0; j < sizeRight; j++) {
right[i] = t[beg+j];
}
i = 0;
j = 0;
for(k = beg; k <= end; k++) {
t[k] = (left[i] <= right[j]) ? left[i++] : right[j++];
}
free(left);
free(right);
return;
}
and the header mergesort.h
extern int lower;
extern int upper;
extern int n;
Thanks!
It looks like you may have two bugs here:
for(j = 0; j < sizeRight; j++) {
right[i] = t[beg+j];
This should probably be:
for(j = 0; j < sizeRight; j++) {
right[j] = t[med+j];
^^^ ^^^

Resources