Finding a maximum sum contiguous sub array - c

I am writing a code to find the maximum sum contiguous sub array in C. The logic seems fine according to me, but still the output is not correct. Please look into the code. The algorithm divides a bigger array into 2 sub-arrays. It then checks for maximum sum sub-array by examining the left array , right array and also the array containing the midpoint (It will check right and left from the midpoint and then return the maximum sum sub-array containing the midpoint).
int* cross_max(int arr[], int low, int mid, int high)
{
int left_max, left_sum = -2000;
int sum = 0;
int i;
for(i=mid; i>=low;i--)
{
sum = sum + arr[i];
if(sum > left_sum)
{
left_sum = sum;
left_max = i;
}
}
int right_max, right_sum = -2000;
for(i=mid+1; i<=high;i++)
{
sum = sum + arr[i];
if(sum > right_sum)
{
right_sum = sum;
right_max = i;
}
}
// 0 - sum
// indices - 1,2
int temp_arr[3] = {0,0,0};
temp_arr[0] = left_sum + right_sum;
temp_arr[1] = left_max;
temp_arr[2] = right_max;
int *p = temp_arr;
printf("\n Maximum sum = %d\n",*p);
printf("\n low = %d\n",*(p+1));
printf("\n high = %d\n",*(p+2));
return p;
}
int* find_max(int arr[], int low, int high)
{
int temp_arr[3] = {0,0,0};
if(low == high)
{
temp_arr[0] = arr[low];
temp_arr[1] = low;
temp_arr[2] = low;
int *q = temp_arr;
return q;
}
int mid = (low + high)/2;
int* a1 = find_max(arr,low,mid);
int* a2 = find_max(arr,mid+1,high);
int* a3 = cross_max(arr,low,mid,high);
if (*a1 > *a2 && *a1 > *a3)
return a1;
else if (*a2 > *a1 && *a2 > *a3)
return a2;
else
return a3;
}
int main()
{
int arr[8] = {1,1,2,-2,3,3,4,-4};
int *point = find_max(arr,0,7);
printf("\n Maximum sum = %d\n",*point);
printf("\n low = %d\n",*(point+1));
printf("\n high = %d\n",*(point+2));
return 0;
}

Slightly off-topic, but this problem is well-known for the best way to solve it (in linear time). You can completely derive the code from the specification.
First, define the problem formally:
Given: integer array A[0, N)
Required:
max(0 <= p <= q <= N : sum(p, q))
where sum(p, q) = sum(p <= i < q : A[i])
Approach:
Let X(n) = max(0 <= p <= q <= n : sum(p, q)), then we need to find X(N). We do this by induction:
X(0) = max(0 <= p <= q <= 0 : sum(p, q))
= sum(0, 0)
= sum(0 <= i < 0 : A[i])
= 0
and
X(n+1) = max(0 <= p <= q <= n+1 : sum(p, q))
= max(max(0 <= p <= q <= n : sum(p, q)), max(0 <= p <= n+1 : sum(p, n+1)))
= max(X(n), Y(n+1))
where Y(n) = max(0 <= p <= n : sum(p, n)). We now also determine Y(n) by induction:
Y(0) = max(0 <= p <= 0 : sum(p, 0))
= sum(0, 0)
= 0
and
Y(n+1) = max(0 <= p <= n+1 : sum(p, n+1))
= max(max(0 <= p <= n : sum(p, n+1)), sum(n+1, n+1)))
= max(max(0 <= p <= n : sum(p, n)) + A[n], 0)
= max(Y(n) + A[n], 0)
Code:
Using the analysis above, the code is trivial.
int arr[8] = {1,1,2,-2,3,3,4,-4};
int N = 8;
int x = 0;
int y = 0;
for (int n = 0; n < N; n++) {
y = max(y + arr[n], 0);
x = max(x, y);
}
printf("Maximum sum = %d\n", x);
with
int max(int a, int b) {
if (a > b)
return a;
else
return b;
}

There are a couple of problems with undefined behavior in your code:
The first is that you pass 9 as high which will be used to index the tenth element of an eight-element array. It will be the tenth because in cross_max you loop while i <= high, so you will index arr[9]. Remember that array indexes are from zero to the size minus one (so you can index from 0 to 7 for your array). The indexes out of bounds will contain undefined (i.e. random) values.
The second problem is that you are returning pointers to a local variable from cross_max. This will lead to undefined behavior when you use that returned pointer. Local variables are only valid inside the scope they were declared, and when the function returns the memory area used by the local variables will be reclaimed and used for the next function.

this is helper to get the max value.
int maxcmp(int a, int b) {
return a >= b ? a : b;
}
The idea is as you iterate over the nums, you add them together. If your cur_sum is less than 0 up to that point, you eliminate all the numbers so far. Because adding negative value after that point is not going to increase the total sum for the rest of nums.
int maxSubArray(int* nums, int numsSize){
int maxSoFar = nums[0],
cur_sum = 0;
for(int i = 0; i < numsSize; i++) {
if (cur_sum<0){
cur_sum=0;
}
cur_sum=cur_sum+nums[i];
maxSoFar=maxcmp(maxSoFar,cur_sum);
}
return maxSoFar;
}`enter code here`

The algorithm is not very efficient. The time complexity is o(n^2). Here is a dynamic programming algorithm, which is o(n).
/*************************************************************************
> File Name: subarray.cpp
> Author: luliang
> Mail: lulyon#126.com
> Created Time: 2013/09/10 Tuesday 15:49:23
************************************************************************/
#include <stdio.h>
typedef struct {
int low;
int high;
int sum;
}DPInfoType;
int main()
{
int arr[8] = {1,1,2,-2,3,3,4,-4};
const int n = sizeof(arr) / sizeof(arr[0]);
DPInfoType dp[n];
dp[0].low = 0;
dp[0].high = 0;
dp[0].sum = arr[0];
for(int i = 1; i < n; ++i) {
if(dp[i - 1].sum > 0) {
dp[i].low = dp[i - 1].low;
dp[i].high = i;
dp[i].sum = dp[i - 1].sum + arr[i];
}
else {
dp[i].low = i;
dp[i].high = i;
dp[i].sum = arr[i];
}
}
int max_index = 0;
for(int i = 1; i < n; ++i) {
if(dp[max_index].sum < dp[i].sum) max_index = i;
}
printf("\n Maximum sum = %d\n", dp[max_index].sum);
printf("\n low = %d\n", dp[max_index].low);
printf("\n high = %d\n", dp[max_index].high);
return 0;
}

As already mentioned use of pointers is inappropriate in your code.
This code worked for me.
#include <stdio.h>
#define INF 1000000
int max (int a, int b)
{
if (a < b)
return b;
return a;
}
int findMaxCrossingSubarray (int arr[], int low, int mid, int high, int *start, int *end)
{
int i, left, right;
int max_left, max_right;
int left_sum = -INF;
int sum = 0;
for (i = mid; i >= 0; i--) {
sum += arr[i];
if (sum > left_sum) {
left_sum = sum;
max_left = i;
}
}
int right_sum = -INF;
sum = 0;
for (i = mid + 1; i <= high; i++) {
sum += arr[i];
if (sum > right_sum) {
right_sum = sum;
max_right = i;
}
}
*start = max_left;
*end = max_right;
return left_sum + right_sum;
}
int findMaxSubarray (int arr[], int low, int high, int *start, int *end)
{
if (low == high)
return arr[low];
int mid = (high - low)/2 + low;
int start1, start2, start3;
int end1, end2, end3;
// initialization of start and end for terminal cases.
start1 = start3 = low;
start2 = mid + 1;
end1 = mid;
end2 = end3 = high;
int sum1 = findMaxSubarray(arr, low, mid, &start1, &end1);
int sum2 = findMaxSubarray(arr, mid + 1, high, &start2, &end2);
int sum3 = findMaxCrossingSubarray(arr, low, mid, high, &start3, &end3);
int res = max(max(sum1, sum2), sum3);
if (res == sum1) {
*start = start1;
*end = end1;
}
if (res == sum2) {
*start = start2;
*end = end2;
}
if (res == sum3) {
*start = start3;
*end = end3;
}
return res;
}
int main(int argc, char const *argv[])
{
int size, i, item, result;
printf("Enter the size of array: ");
scanf("%d",&size);
int arr[size];
printf("Enter the array:\n");
for (i = 0; i < size; ++i) {
scanf("%d",&item);
arr[i] = item;
}
int start = 0, end = size-1;
result = findMaxSubarray(arr, 0, size-1, &start, &end);
printf("Result: %d, start: %d and end: %d.\n", result, start, end);
return 0;
}

Related

how to find the position of newArr[i] in Arr[] and implement this position in newArr[] - without duplicates

I hope i made my self clear enough in the title but if not i am here to explain my self
i got an array from an input ( like Arr = {, ).
we can use only 1 additional array (1 original 1 additional)
this is what i made so far :
I made a new array named newArr and assigned it all the values Arr contains.
i sorted it (because its requires time complexity of nlogn)
and then moved duplicates to the end.
now what i can't figure out :
now i need to move the original digits to their place according to the main
(all the values in the arrays are positive and they can be bigger then
n-which is the size of the array and ofc they can be also smaller then n)
i also need to return the number of original digits in the array
the original number should stay in the same position and the duplicates in the end of the array their order doesn't matter.
from here we can't use another additional array only the current arrays that we have ( which are 2)
i have been thinking about doing some kind of binary search but all of them went wrong.(like bin_search_first) and original binary and still couldn't manage it.
can some one give me an hint?
here is the code at where i am
#define _CRT_SECURE_NO_WARNINGS
/*Libraries*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int* input_array(int);
int moveDuplicatesV2(int*, int);
void merge(int* a, int p, int q, int r);
void merge_sort(int* a, int first, int last);
void swap(int* v, int* u);
int bin_search_first(int , int* , int );
int main()
{
int arr[10] = { };
int n = 12;
int k = 0;
int first = 0;
int last = n - 1;
int mid = (first + last) / 2;
int l = n - 1;
int* D = arr + 1;
int j = 0;
size_t dupes_found = 0;
int* newArr = (int*)malloc(12 * sizeof(int));
assert(newArr);
for (int i = 0; i < n; i++)
{
newArr[i] = arr[i];
}
merge_sort(newArr, first, last);
for (size_t i = 0; i < n - 1 - dupes_found;)
{
if (newArr[i] == newArr[i + 1])
{
dupes_found++;
int temp = newArr[i];
memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
newArr[n - 1] = temp;
}
else {
i++;
}
}
j = 0;
int key = 0;
first = 0;
for (int i = 0; i < n - dupes_found; i++)
{
key = newArr[i];
first = bin_search_first(key, arr,n);
swap(&newArr[i], &newArr[first]);
newArr[first] = newArr[i];
}
for (int i = 0; i < n; i++)
{
arr[i] = newArr[i];
}
for (int i = 0; i < n; i++)
{
printf("%d", arr[i]);
}
return n - dupes_found;
}
void merge(int* a, int p, int q, int r)
{
int i = p, j = q + 1, k = 0;
int* temp = (int*)malloc((r - p + 1) * sizeof(int));
assert(temp);
while ((i <= q) && (j <= r))
if (a[i] < a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
while (j <= r)
temp[k++] = a[j++];
while (i <= q)
temp[k++] = a[i++];
/* copy temp[] to a[] */
for (i = p, k = 0; i <= r; i++, k++)
a[i] = temp[k];
free(temp);
}
void merge_sort(int* a, int first, int last)
{
int middle;
if (first < last) {
middle = (first + last) / 2;
merge_sort(a, first, middle);
merge_sort(a, middle + 1, last);
merge(a, first, middle, last);
}
}
void swap(int* v, int* u)
{
int temp;
temp = *v;
*v = *u;
*u = temp;
}
int bin_search_first(int key, int* a, int n)
{
int low, high, mid;
low = 0;
high = n - 1;
while (low <= high)
{
mid = (low + high) / 2; // low + (high - low) / 2
if (key > a[mid])
low = mid + 1;
else
if (key < a[mid])
high = mid - 1;
else //key==a[mid]
if ((low == high) || (a[mid - 1] < key))
return mid;
else
high = mid - 1;
}
return -1;
}
Here is my idea:
Sort the array (nlogn)
Loop over the array and for each value, save a pointer to its first occurence (n)
Loop over the original array and insert the value into a result array if it is the values first occurrence. Whether or not it is the first occurrence can be checked using the sorted array: each element in this array has an additional flag that will be set if the value has already been seen. So, search for the element using bsearch, if seen append to back of result array (order does not matter), if not seen append to beginning of array and set seen value. (nlogn, since bsearch doesn't need to seek the first element because it was precomputed thus logn, over the array n)
Here is an example code (you can replace the qsort by mergesort to make the algorithm actually nlogn, I just used qsort because it is given):
#include <stdio.h>
#include <stdlib.h>
struct arr_value {
int value;
int seen;
struct arr_value *first;
};
int compar(const void *p1,const void *p2) {
struct arr_value *v1 = (struct arr_value *)p1;
struct arr_value *v2 = (struct arr_value *)p2;
if(v1->value < v2->value) {
return -1;
} else if(v1->value == v2->value) {
return 0;
}
return 1;
}
int main()
{
#define NumCount (12)
int arr[NumCount] = { 7, 3, 1, 2, 7, 9, 3, 2, 5, 9, 6, 2 };
int arrResult[NumCount];
int resultCount = 0;
int resultCountBack = 0;
struct arr_value arrseen[NumCount];
for(int i = 0; i < NumCount; ++i) {
arrseen[i].value = arr[i];
arrseen[i].seen = 0;
}
qsort(arrseen, NumCount, sizeof(struct arr_value), compar);
struct arr_value *firstSame = arrseen;
firstSame->first = firstSame;
for(int i = 1; i < NumCount; ++i) {
if(arrseen[i].value != firstSame->value) {
firstSame = arrseen + i;
}
arrseen[i].first = firstSame;
}
struct arr_value key;
for(int i = 0; i < NumCount; ++i) {
key.value = arr[i];
struct arr_value *found = (struct arr_value *)bsearch(&key, arrseen, NumCount, sizeof(struct arr_value), compar);
struct arr_value *first = found->first;
if(first->seen) {
// value already seen, append to back
arrResult[NumCount - 1 - resultCountBack] = first->value;
++resultCountBack;
} else {
// value is new, append
arrResult[resultCount++] = first->value;
first->seen = 1;
}
}
for(int i = 0; i < NumCount; ++i) {
printf("%d ", arrResult[i]);
}
return 0;
}
Output:
7 3 1 2 9 5 6 2 9 2 3 7
To begin with, memmove doesn't run in a constant time, so the loop
for (size_t i = 0; i < n - 1 - dupes_found;)
{
if (newArr[i] == newArr[i + 1])
{
dupes_found++;
int temp = newArr[i];
memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
newArr[n - 1] = temp;
}
else {
i++;
}
}
drives the time complexity quadratic. You have to rethink the approach.
It seems that you are not using a crucial point:
all the values in the arrays are positive
It seriously hints that changing values to their negatives is a way to go.
Specifically, as you iterate over the initial array, and bin-search its elements in temp, comparing the _ absolute values_. When an element is found in temp, and it is still positive there, flip all its dupes in temp to negative. Otherwise flip it in initial.
So far, it is O(n log n).
Then perform an algorithm known as stable_partition: all positives are moved in front of negatives, retaining the order. I must not spell it here - I don't want to deprive you of a joy figuring it out yourself (still O(n log n)
And finally flip all negatives back to positives.

Insert elements from one array to another such that inversions are minimised

Let say I have array A and B ( always equal size)
A = 5 4 2 1
B = 8 3 6 7
I am to insert elements from B in to A while keeping the relative order of A while minimising inversions.
So the answer would be 3 5 4 1 2 6 7 8 (7 inversions)
I have tried sorting B first then poping min(a[0] b[0]) into an array C but cases like
A = 99999 1 2 3
B = 5 6 7 8
Gives the wrong 5 6 7 8 99999 1 2 3 (15 inversions)
When the correct is 99999 1 2 3 5 6 7 8 (7 inversions)
I am at a lost please help
Okay, this is an interesting question. My current solution works in O(nlog(n)).
The logic behind this solution can be found here.
However, since there was no implementation there, I've decided to place it here.
The overall logic relies on two things:
For the array that does not need to maintain order, sort it in O(n log n).
Find the middle element, and insert it into the location in the array that minimizes inversions. This can be done in T(2n) = O(n).
The elements to the left of that middle element in the sorted array should be on the left of that element in the combined array to minimize inversions. The elements to the right of that middle element in the sorted array should be on the right of that element in the combined array to minimize inversions. This knowledge reduces the space you have to search to find the insertion point with least inversions each iteration. Hence, you can recurse by applying the above logic on the left half of the sorted array with the left half of the combined array.
Now, onto the code:
#include <bits/stdc++.h>
using namespace std;
long long merge(vector<int>& v, int temp[], int left, int mid, int right) {
int i,j,k;
long long inv_count = 0;
i = left;
j = mid;
k = left;
while ((i <= mid - 1) && (j <= right)) {
if (v[i] <= v[j]) {
temp[k++] = v[i++];
} else {
temp[k++] = v[j++];
inv_count += mid - i;
}
}
while (i <= mid - 1)
temp[k++] = v[i++];
while (j <= right)
temp[k++] = v[j++];
for (i = left; i <= right; i++)
v[i] = temp[i];
return inv_count;
}
long long _mergeSort(vector<int>& v, int temp[], int left, int right) {
int mid;
long long inv_count = 0;
if (v.size() < 2) return 0;
if (right > left) {
mid = (right + left) / 2;
inv_count += _mergeSort(v, temp, left, mid);
inv_count += _mergeSort(v, temp, mid + 1, right);
inv_count += merge(v, temp, left, mid + 1, right);
}
return inv_count;
}
long long countInversionsInVector(vector<int>& v) {
int temp[v.size()];
return _mergeSort(v, temp, 0, v.size() - 1);
}
void solveHelper(vector<int> &a, int sa, int ea, vector<int>& b, int sb, int eb, vector<int>& I) {
if (sb >= eb) return;
int mb = (sb + eb) / 2;
int b_elem = b[mb];
vector<int> sliced_a(ea - sa + 1);
for (auto index = a.begin() + sa; index < a.begin() + ea; index++) {
sliced_a.push_back(*index);
}
long long invCount = 0;
for (long long i = sa; i < ea; i++) {
if (a[i] < b_elem) {
invCount += 1;
}
}
long long minInvCount = invCount;
int insertionIndex = sa;
for (int i = sa; i < ea; i++) {
if (a[i] < b[mb]){
invCount -= 1;
} else {
invCount += 1;
}
if (invCount < minInvCount) {
minInvCount = invCount;
insertionIndex = i + 1;
}
}
I[mb] = insertionIndex;
solveHelper(a, sa, insertionIndex, b, sb, mb, I);
solveHelper(a, insertionIndex, ea, b, mb + 1, eb, I);
return;
}
void mergeFinal(vector<int>& a, vector<int>& b, vector<int>& I, vector<int>& final) {
int index_a = 0;
int index_b = 0;
for (int i = 0; i < 2 * a.size(); i++) {
if (i == I[index_b] + index_b) {
final[i] = b[index_b];
index_b++;
} else {
final[i] = a[index_a];
index_a++;
}
}
}
long long solve(vector<int>& a, vector<int>& b) {
sort(b.begin(), b.end());
vector<int> I(b.size());
solveHelper(a, 0, a.size(), b, 0, b.size(), I);
vector<int> final(2*a.size());
mergeFinal(a, b, I, final);
return countInversionsInVector(final);
}
int main() {
int n;
ios_base::sync_with_stdio(false); // speed up reading input
cin >> n;
vector<int> a(n), b(n);
for(int i = 0; i < n; i++) {
cin >> a[i];
}
for(int i = 0; i < n; i++) {
cin >> b[i];
}
cout << solve(a, b) << "\n";
}

Optimized Bubble Sort time for sorting int arrays

I'm currently working on an essay, in which I compare sorting times of certain algorithms. I've written an optimized version of bubble sort, which checks if there is a swap, if not, it stops.
void bubble_sort(int* tab, int n) {
int zamiana, x, i;
do {
zamiana = 0;
for (int counter = 0, i = 1; i < n; ++counter, ++i) {
if (tab[counter] > tab[i]) {
x = tab[counter];
tab[counter] = tab[i];
tab[i] = x;
zamiana = 1;
}
}
} while (zamiana != 0);
}
I have found that it takes almost 0s to sort array sorted in ascending order, now I'm testing it on an array sorted in descending order, and times are almost the same as for ascending order. Is it normal?
Code tested:
#include <time.h>
#include <stdio.h>
void quickSort(int* tab, int lewy, int prawy) {
int x, y = lewy - 1, z = prawy + 1, pivot = tab[(lewy + prawy) / 2];
while (1) {
while (pivot < tab[++y]);
while (pivot > tab[--z]);
if (y <= z) {
x = tab[y];
tab[y] = tab[z];
tab[z] = x;
}
else {
break;
}
}
if (z > lewy) {
quickSort(tab, lewy, z);
}
if (y < prawy) {
quickSort(tab, y, prawy);
}
}
void bubble_sort(int* tab, int n) {
int zamiana, x, i;
do {
zamiana = 0;
for (int counter = 0, i = 1; i < n; ++counter, ++i) {
if (tab[counter] > tab[i]) {
x = tab[counter];
tab[counter] = tab[i];
tab[i] = x;
zamiana = 1;
}
}
} while (zamiana != 0);
}
int main (){
int* tab;
int n;
srand(time(NULL));
scanf("%d", &n); //user input array size
tab = (int*)malloc(n * sizeof(int*));
for (int counter = 0; counter < n; ++counter) {
tab[counter] = (rand() % 200) - 100; //<-100;100>
}
quickSort(tab, 0, n); //sorting array to get descending order
clock_t start = clock();
bubble_sort(tab, n); //sorting array
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;
printf("Time elapsed: %f", seconds);
}

second smallest element in an array

as a part of a C program I wrote the following function, which finds the second smallest element of an array
unsigned int array_second_min (unsigned int w[], unsigned int n)
{
unsigned int i, erst = UINT_MAX, zweit = UINT_MAX, count = 0;
if (n < 2)
return UINT_MAX;
for (i = 0;i < n; i++) {
if (w[i] == w[i + 1])
count++;
}
if (count == n - 1)
return UINT_MAX;
for (i = 0;i < n;i++) {
if (w[i] < erst)
erst = w[i];
}
for (i = 0;i < n;i++) {
if (w[i] == erst)
continue;
if ((w[i] - erst) < zweit)
zweit = w[i];
}
return zweit;
}
the problem is that it is not really functioning as it should. I think the problem is in the last for loop, but am not sure about that.
Thank you for your help
picture of the output:
The following code will return the second smallest element
unsigned int array_second_min (unsigned int w[], unsigned int n){
unsigned int i, first = UINT_MAX, second = UINT_MAX;
if(n < 2)
return UINT_MAX;
sort(w, w+n);
second = w[n-2];
return second;
}
This is a somewhat more efficient solution, as it is O(n):
struct pair {
int r[2];
};
struct pair small2(int *a, int n) {
int r[2];
int order;
r[0] = a[0];
r[1] = a[1];
order = (r[0] >= r[1]);
for (int i = 2; i < n; i++) {
if (a[i] <= r[order]) {
r[!order] = a[i];
order = !order;
} else if (a[i] <= r[!order]) {
r[!order] = a[i];
}
}
struct pair x;
x.r[0] = r[order];
x.r[1] = r[!order];
return x;
}
There is a lack of detail about duplicates, this handles them in an unsurprising fashion. Note the trickiness of the order variable; this works because you are only interested in the least two, if you wanted the least 3, you would have to add the extra tests. It would remain O(n), but the C would be greater.

Access Violation in C program involving pointer variable?

I was trying to solve Project Euler question 16 using c. I did not use bignnum libraries. The question asks 2^1000. I decided to store every digit of that number in an array.
For Example: 45 means arr[0]=4, arr[1]=5;
The problem is definitely i the function int multi.
#include<stdio.h>
#include<conio.h>
int multi(int *base, int k);// does the multiplication of array term by 2
void switcher();//switches every term when the fore mostvalue is >10
int finder();// finds the array address of last value
int arr[1000];
int summer();//sums all values of the array
int main()
{
arr[1000] = { 0 };
arr[0] = 1;
int i, j, sum, k, p;
for (i = 0; i < 1000; i++)
{
j = 0;
k = finder();
p = multi(arr + k, j);
}
sum = summer();
printf("sum of digits of 2^1000 is %d", sum);
_getch();
}
int multi(int *base, int k)
{
int p;
if (base == arr)
{
*base = *base - 1;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
switcher();
}
return 0;
}
*base = *base * 2;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
p = multi(base - 1, 1);
}
else
{
p = multi(base - 1, 0);
}
}
void switcher()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
j--;
for (; j > 0; j--)
{
arr[j + 1] = arr[j];
}
arr[0] = 1;
}
int finder()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
return --j;
}
int summer()
{
int summ, i;
summ = 0;
for (i = 0; i<1000; i++)
{
summ = summ + arr[i];
if (arr[i] == 0)
break;
}
return summ;
}
It compiles but during runtime it shows Access Write Violation, base was ......
Please explain this error and how to resolve it ?
Array is of 100 Bytes but you are looping for 1000. Also in function Finder() , you do not have a limit on variable j so your array size is going beyond 100 bytes.
Also use memset to assign array variables to 0.
As said in the comments, 2^1000 has 302 decimal digits.
You're going far outside your array.
But your code is very complicated because you store the digits with the most significant one first.
Since you're only interested in the digits and not the order in which they would be written, you can store the number "in reverse", with the least significant digit first.
This makes the code much simpler, as you can loop "forwards" and no longer need to shuffle array elements around.
Using -1 as "end of number" marker, it might look like this:
void twice(int* digits)
{
int i = 0;
int carry = 0;
while (digits[i] >= 0)
{
digits[i] *= 2;
digits[i] += carry;
if (digits[i] >= 10)
{
carry = 1;
digits[i] -= 10;
}
else
{
carry = 0;
}
i++;
}
if (carry)
{
digits[i] = 1;
digits[i+1] = -1;
}
}
int main()
{
int digits[302] = {1, -1}; /* Start with 1 */
twice(digits); /* digits is now { 2, -1 } */
return 0;
}

Resources