Why unintialized array elements are not 0 always in C - arrays

I input 4566371 and find out that uninitialized array elements are not 0 as said in our texts
#include <stdio.h>
#define MAX 10
// Function to print the digit of
// number N
void printDigit(long long int N)
{
// To store the digit
// of the number N
int array_unsorted[MAX];//array_unsorteday for storing the digits
int i = 0;//initializing the loop for the first element of array_unsorted[]
int j, r;
// Till N becomes 0,we will MOD the Number N
while (N != 0) {
// Extract the right-most digit of N
r = N % 10;
// Put the digit in array_unsorted's i th element
array_unsorted[i] = r;
i++;
// Update N to N/10 to extract
// next last digit
N = N / 10;
}
// Print the digit of N by traversing
// array_unsorted[] reverse
for (j =MAX; j >=0; j--)
{
printf("%d ", array_unsorted[j]);
}
}
// Driver Code
int main()
{
long long int N;
printf("Enter your number:");
scanf("%lld",&N);
printDigit(N);
return 0;
}
output:
Enter your number:4566371
77 0 8 32765 4 5 6 6 3 7 1
Process returned 0 (0x0) execution time : 2.406 s
Press any key to continue.
The other values should be o right?Why 77,0,32765 this way?Why not all are 0?like 0 0 0 0 4 5 6 6 3 7 1?

An array of integers declared inside a function has indeterminate values if it is uninitialized. If a similar array is declared at global scope, outside all functions, it will be initialized with zeros by default.
To make an array that is always initialized to zeros, do this:
int array_unsorted[MAX] = {0};
This works because in C, = {0} will initialize all values with zero. If you say = {10, 20} it will initialize the first two elements as written, and the rest to zero.

You have correctly reserved a memory space for your array array_unsorted but the memory has not been cleaned before use. This memory reserved it was probably used by another function or variable before yours! This is why it already has some values in it. You should set it to 0 manually before starting to use it.

As noted in other answers, you may want to initialize your integer array. Whether or not you do that, you might want to replace the for loop statement conditions of:
for (j =MAX; j >=0; j--)
with:
for (j = i - 1; j >=0; j--) /* Start at the place the digit storage ended */
That way, you are not moving into array elements that were not used in the digit storage portion of your function.
Regards.

Related

First number in array not transferring to new array correctly

I am writing a program to break numbers in an array into their digits then store those digits in a new array. I have two problems:
It does not display the first number in the array (2) when transferred to the second array, and I am not entirely sure why.
The array may contain 0's, which would break my current for loop. Is there another way to implement a for loop to only run for as many numbers are stored in a array without knowing how big the array is?
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// Setting an array equal to test variables
int sum[50] = { 2, 6, 3, 10, 32, 64 };
int i, l, k = 0, sumdig[10], dig = 0;
// Runs for every digit in array sum, increases size of separate variable k every time loop runs
for (i = 0; sum[i] > 0; i++ && k++)
{
sumdig[k] = sum[i] % 10;
dig++;
sum[i] /= 10;
// If statement checks to see if the number was two digits
if (sum[i] > 0)
{
// Advancing a place in the array
k++;
// Setting the new array position equal to the
sumdig[k] = sum[i] % 10;
dig++;
}
}
// For testing purposes - looking to see what digits have been stored
for (l = 0; l < dig; l++)
{
printf("%i\n", sumdig[l]);
}
}
This is the output:
6
3
0
1
2
3
4
6
0
Solution:
It does not display the first number in the array (2) when transferred to the second array
changes i++ && k++ into i++,k++
Is there another way to implement a for loop to only run for as many numbers are stored in an array
There are many different ways but here is some to illustrate it in a few different scenarios:
1. The array length is known and fixed:
Let the compiler automatically allocate the array for you. And then for(i=0; i<6; i++)
2. Able to calc the array length:
Then count the number of elements when initializing the array into a varible. Then just for(i=0; i<SizeCount; i++)
3. Not-able to know array size for some reason:
It is rare but, in that case, you can pre-set a stop criteria i.e. -1 or some other flag so that you can stop when it reaches the terminator i.e. set or pre-set all other values of sum to be -1. Then you can while(sum[i] != -1) This is how string lengths work in C, either with NULL termination (string end with the number 0 or value NULL) or, with input, the line break character \n indicating a termination.
DEMO
Here is a demo of full code with some explanation:
#include <stdio.h>
int main(void){
int sum[] = {2, 6, 3, 10, 32, 64}; // compiler is smart enough know the size
int i, k = 0, sumdig[10], dig = 0;
// Runs for every digit in array sum, increases size of seperate variable k everytime loop runs
for(i = 0; i < sizeof(sum)/sizeof(int); i++, k++){
sumdig[k] = sum[i] % 10;
dig++;
sum[i] /= 10;
// If statement checks to see if the number was two digits
if (sum[i] > 0)
{
// Advancing a place in the array
k++;
// Setting the new array position equal to the
sumdig[k] = sum[i] % 10;
dig++;
}
}
// For testing purposes - looking to see what digits have been stored
for(i = 0; i < dig; i++){
printf("%i\n", sumdig[i]);
}
}
Compile and run
gcc -Wall demo.c -o demo
./demo
Output
2
6
3
0
1
2
3
4
6

How to find the longest increasing subsequence without sorting?

I want to find the longest increasing subsequence without sorting it, and to then sum the numbers of the period, for example like :
12, 15, 16, 4, 7, 10, 20,25
12,15,16 is an increasing subsequence.
4,7,10,20 is another increasing subsequence.
but since 4,7,10,20,25 are 5 elements and 12,15,16 are 3 which is less than the 4, the output should be the sum of the longer period which is the sum of the 5 elements, 66.
How could such a thing be done using c?
I am new to C so this is all what I could think of.
#include<stdio.h>
int main() {
int count = 0;
int n;
int max = 0;
scanf("%d", &n);
int arr[1000];
for(int i = 0;i<n;i++){
if(arr[i+1>arr[i])
count++;
if(count>max)
max = count;
}
You really need two loops.
One that iterates through all elements. This is the "starting" index of a sequence.
Then, an inner loop that starts at one element to the right of the start. It loops to the end of the array but stops if it sees the current element is out of sequence.
After the second loop ends, the difference of these two indexes is the sequence length.
Here is some refactored code. It is annotated:
#include <stdio.h>
int arr[] = { 17, 18, 19, 5, 6, 23, 24, 25, 24, 25, 17, 18, 19 };
// show -- print a sequence
void
show(int begidx,int count,const char *tag)
{
printf("%s: %d %d --",tag,begidx,count);
for (; count > 0; --count, ++begidx)
printf(" %d",arr[begidx]);
printf("\n");
}
// sum -- get sum of the sequence
int
sum(int begidx,int count)
{
int sum = 0;
for (; count > 0; --count, ++begidx)
sum += arr[begidx];
return sum;
}
int
main(void)
{
int count = sizeof(arr) / sizeof(arr[0]);
int maxlen = 0;
int maxidx = -1;
show(0,count,"ORIG");
// loop through all possible starting points for sequence
for (int ilhs = 0; ilhs < count; ++ilhs) {
int lval = arr[ilhs];
// loop through all numbers to the right of the starter
// stop at the array end or when we get a number that is out of sequence
int irhs;
for (irhs = ilhs + 1; irhs < count; ++irhs) {
int rval = arr[irhs];
// out of sequence -- we've hit the end
if (rval < lval)
break;
lval = rval;
}
// get length of the sequence we just saw
int curlen = irhs - ilhs;
// remember a larger sequence
if (curlen > maxlen) {
maxlen = curlen;
maxidx = ilhs;
show(maxidx,maxlen,"NEW");
}
}
// show the maximum sequence
show(maxidx,maxlen,"FINAL");
// sum the sequence
printf("SUM: %d\n",sum(maxidx,maxlen));
return 0;
}
Here is the program output:
ORIG: 0 13 -- 17 18 19 5 6 23 24 25 24 25 17 18 19
NEW: 0 3 -- 17 18 19
NEW: 3 5 -- 5 6 23 24 25
FINAL: 3 5 -- 5 6 23 24 25
SUM: 83
UPDATE:
A [considerable] speedup for the above is to change:
for (int ilhs = 0; ilhs < count; ++ilhs) {
Into:
for (int ilhs = 0; ilhs < count; ilhs = irhs) {
And, move the int irhs; above the outer loop.
This reduces the time from O(n^2) to O(n)
Here's an outline of one possible algorithm that will solve it using one loop.
Building blocks:
A variable that stores the number of elements in the longest sequence encountered so far, let's call it longest_seq.
A variable that stores the sum of the longest sequence encountered so far, longest_sum.
A variable for counting the length of the sequence you are currently examining, running_seq.
A variable keeping the sum of the current sequence, running_sum.
Start by initializing:
longest_seq = 0
longest_sum = 0
Then initialize the running variables to handle the first element. The way the following loop is created should make it clear why.
running_seq = 1
running_sum = arr[0]
Now to the interesting part:
Let an index variable, i, loop from 1 (not 0 as usual, we handled the first element before the loop) to the number of elements you have in arr, minus 1.
If arr[i] is greater than arr[i-1] (the previous element), the running sequence is still going on, so
Increase running_seq by 1.
else, if arr[i] is not greater than arr[i-1], the running sequence is broken, so
Check if running_seq is greater than longest_seq. If it is:
Save running_seq and running_sum to longest_seq and longest_sum.
Reset running_seq = 1 and running_sum = 0.
Unconditionally add arr[i] to running_sum
When the loop is done, you need to check if running_seq is greater than longest_seq again (and save the values in case it is) just in case the longest sequence happened to be at the end of the array.
The answers when this is done are in longest_seq and longest_sum.
Demo implementation
A variant with a minor difference is to change the loop slightly with regards to the updating of running_sum:
Let an index variable, i, loop from 1 (not 0 as usual, we handled the first element before the loop) to the number of elements you have in arr, minus 1.
If arr[i] is greater than arr[i-1] (the previous element), the running sequence is still going on, so
Increase running_seq by 1.
Add arr[i] to running_sum
else, if arr[i] is not greater than arr[i-1], the running sequence is broken, so
Check if running_seq is greater than longest_seq. If it is:
Save running_seq and running_sum to longest_seq and longest_sum.
Reset running_seq = 1 and running_sum = arr[i].
Demo implementation

Find consecutive rows of a 2D array with maximum number of 1s

I have 2D array of size m*m with element values either 0s or 1s. Furthermore, each column of the array has a contiguous block of 1s (with 0 outside that block). The array itself is too large to be held in memory (as many as 10^6 rows), but for each column I can determine the lower bound, a, and the upper bound, b, of the 1s in that column. For a given n, I need to find out those n consecutive rows which have the maximum number of 1s. I can easily do it for smaller numbers by calculating the sum of each row one by one, and then choosing n consecutive rows whose sum comes out to be maximum, but for large numbers, it is consuming too much time. Is there any efficient way for calculating this? Perhaps using Dynamic Programming?
Here is an example code fragment showing my current approach, where successive calls to read_int() (not given here) provide the lower and upper bounds for successive columns:
long int harr[10000]={0}; //initialized to zero
for(int i=0;i<m;i++)
{
a=read_int();
b=read_int();
for(int j=a;j<=b;j++) // for finding sum of each row
harr[j]++;
}
answer=0;
for(int i=0;i<n;i++)
{
answer=answer+harr[i];
}
current=answer;
for(int i=n;i<m;i++)
{
current=current+harr[i]-harr[i-n];
if(current>answer)
{
answer=current;
}
}
For example (with m = 6 and n = 3)
Here the answer would be row 1 to row 3 with a total 1-count of 13 in those rows. (Row 2 to row 4 also maximizes the sum as there is a tie.)
Here is a different approach. Think of each pair a, b as defining an interval of the form [a,b+1). The task is to find the n consecutive indices which maximizes the sum of the parenthesis depth of the numbers in that interval. Every new a bumps the parenthesis depth at a up by 1. Every new b causes the parenthesis depth after b to go down by 1. In the first pass -- just load these parentheses depth deltas. Then one pass gets the parenthesis depths from these deltas. The following code illustrates this approach. I reduced m to 6 for testing purposes and replaced calls to the unkown read_int() by accesses to hard-wired arrays (which correspond to the example in the question):
#include <stdio.h>
int main(void){
int a,b,answer,current,lower,upper;
int n = 3;
int lower_bound[6] = {0,1,2,3,1,2};
int upper_bound[6] = {3,4,3,5,2,4};
int m = 6;
int harr[6]={0};
//load parenthesis depth-deltas (all initially 0)
for(int i=0;i<m;i++)
{
a = lower_bound[i];
b = upper_bound[i];
harr[a]++;
if(b < m-1)harr[b+1]--;
}
//determine p-depth at each point
for(int i = 1; i < m; i++){
harr[i] += harr[i-1];
}
//find optimal n-rows by sliding-window
answer = 0;
for(int i=0;i<n;i++)
{
answer = answer+harr[i];
}
current =answer;
lower = 0;
upper = n-1;
for(int i=n;i<m;i++)
{
current = current+harr[i]-harr[i-n];
if(current>answer)
{
answer = current;
lower = i-n+1;
upper = i;
}
}
printf("Max %d rows are %d to %d with a total sum of %d ones\n", n,lower,upper,answer);
return 0;
}
(Obviously, the loop which loads harr can be combined with the loop which computes answer. I kept it as two passes to better illustrate the logic of how the final harr values can be obtained from the parentheses deltas).
When this code is compiled and run its output is:
Max 3 rows are 1 to 3 with a total sum of 13 ones
I'm not sure how the following will scale for your 10^6 rows, but it manages the the trailing sum of x consecutive rows in a single pass without function call overhead. It may be worth a try. Also insure you are compiling with full optimizations so the compiler can add its 2 cents as well.
My original thought was to find some way to read x * n integers (from your m x n matrix) and in some fashion look at a population of set bits over that number of bytes. (checking the endianness) and taking either the first or last byte for each integer to check whether a bit was set. However, the logic seemed as costly as simply carrying the sum of the trailing x rows and stepping through the array while attempting to optimize the logic.
I don't have any benchmarks from your data to compare against, but perhaps this will give you another idea or two.:
#include <stdio.h>
#include <stdlib.h>
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef INT_MIN
#define INT_MIN -(1U << (sizeof (int) * CHAR_BIT - 1))
#endif
int main (int argc, char **argv) {
/* number of consecutive rows to sum */
size_t ncr = argc > 1 ? (size_t)atoi (argv[1]) : 3;
/* static array to test summing and row id logic, not
intended to simulate the 0's or 1's */
int a[][5] = {{1,2,3,4,5},
{2,3,4,5,6},
{3,4,5,6,7},
{4,5,6,7,8},
{3,4,5,6,7},
{0,1,2,3,4},
{1,2,3,4,5}};
int sum[ncr]; /* array holding sum on ncr rows */
int sumn = 0; /* sum of array values */
int max = INT_MIN; /* variable holding maximum sum */
size_t m, n, i, j, k, row = 0, sidx;
m = sizeof a / sizeof *a; /* matrix m x n dimensions */
n = sizeof *a / sizeof **a;
for (k = 0; k < ncr; k++) /* initialize vla values */
sum[k] = 0;
for (i = 0; i < m; i++) /* for each row */
{
sidx = i % ncr; /* index for sum array */
if (i > ncr - 1) { /* sum for ncr prior rows */
for (k = 0; k < ncr; k++)
sumn += sum[k];
/* note 'row' index assignment below is 1 greater
than actual but simplifies output loop indexes */
max = sumn > max ? row = i, sumn : max;
sum[sidx] = sumn = 0; /* zero index to be replaced and sumn */
}
for (j = 0; j < n; j++) /* compute sum for current row */
sum [sidx] += a[i][j];
}
/* output results */
printf ("\n The maximum sum for %zu consecutive rows: %d\n\n", ncr, max);
for (i = row - ncr; i < row; i++) {
printf (" row[%zu] : ", i);
for (j = 0; j < n; j++)
printf (" %d", a[i][j]);
printf ("\n");
}
return 0;
}
Example Output
$./bin/arraymaxn
The maximum sum for 3 consecutive rows: 80
row[2] : 3 4 5 6 7
row[3] : 4 5 6 7 8
row[4] : 3 4 5 6 7
$./bin/arraymaxn 4
The maximum sum for 4 consecutive rows: 100
row[1] : 2 3 4 5 6
row[2] : 3 4 5 6 7
row[3] : 4 5 6 7 8
row[4] : 3 4 5 6 7
$ ./bin/arraymaxn 2
The maximum sum for 2 consecutive rows: 55
row[2] : 3 4 5 6 7
row[3] : 4 5 6 7 8
Note: if there are multiple equivalent maximum consecutive rows (i.e. two sets of rows where the 1's add up the the same number), the first occurrence of the maximum is selected.
I'm not sure what optimizations you are choosing to compile with, but regardless which code you use, you can always try the simple hints to the compiler to inline all functions (if you have functions in your code) and fully optimize the code. Two helpful ones are:
gcc -finline-functions -Ofast

C Program compiles, but fails at runtime (too big of an array?). And 'checklist' suggestions?

I'm writing a program to look for the longest Collatz sequence starting under 1,000,000.
I was really proud of this code, it seemed so efficient and clean and well written... until I tried to run it. After a little debugging to get it to compile, I found that when I run the program, it crashes.
I have used both
int array[1000000];
and
int *array;
array = (int*)calloc(s, sizeof(int));
(where s=1000000)
to declare an array of 1,000,000 spaces.
So part A) of my question: Is it ridiculous or possible to declare an array of that size?
and part B) of my question: This is used for a 'checklist' of sorts, checking which numbers have already been seen. Is there a simpler or better or just different method of 'checking off' numbers that I should be using instead?
the code is as follows:
// This is a program to find the longest Collatz sequence starting under 1,000,000
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Collatz sequence: IF EVEN n/2 :: IF ODD 3n+1
//define ints
int i;
int n;
int c; // counter of sequence length
int longestsequence = 0;
int beststart;
int s = 1000000; //size of array
//define int array
//int array[999999];
//define array using calloc
//define pointer for calloc int array
int *array;
// do your calloc thing
array = (int*)calloc(s, sizeof(int)); // allocates 1,000,000 spots (s) of size "int" to array "array"
//fill array
for(i = 0; i < 1000000; i++)
{
array[i] = i;
}
for(i = 999999; i > 500000; i--)
{
if(array[i] == 0) // skip if number has already been seen
goto done;
n = i;
c = 0;
//TEST
printf("Current starting number is: %d\n", i);
//TEST
while(n != 4) // run and count collatz sequence
{
//TEST
//printf("test1\n");
//TEST
if(n % 2 == 0) // EVEN
n = n/2;
else // ODD
n = 3 * n + 1;
//TEST
//printf("test2\n");
//TEST
c++;
//TEST
//printf("test3\n");
//TEST
if(n < 1000000 && array[n] != 0) // makes note of used numbers under 1000000
array[n] = 0;
//TEST
//printf("test4\n");
//TEST
}
if(longestsequence < c)
{
longestsequence = c;
beststart = i;
//TEST
printf("Current best start is: %d\n", beststart);
//TEST
}
done:
}
printf("the starting number that produces the longest Collatz sequence is...\n");
printf("%d\n", beststart);
getchar();
return 0;
}
Thanks for any and all help and suggestions! Links to helpful sources are always appreciated.
UPDATE!
1.My code now looks like this^^^^
and
2.The program runs, and then mysteriously stops at i value 999167
for(i = 999999; i > 4; i++)
You easily go beyond array boundary here. I guess what you meant was
for(i = 999999; i > 4; --i)
// ^^^
Also, as in your implementation, 1 million element is not enough.
Take n == 999999 as example. In the 1st step, you compute 3 * n + 1, which is obviously way larger than 1000000. A simple solution would be change
if(array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
into
if(n < s && array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
which just disables result lookup when n is over array boundary.
You could use a simple linked list of numbers, which will reduce the memory requirements at the expense of "long" search times. I've always noticed a bit of repetition:
1
2 → 1 (already seen in 1, so link to the existing 1)
3 → 5 → 16 → 8 → 4 → 2 (already seen in 2, so link to the existing 2)
4 (link to existing after 8)
5 (link to existing after 5)
etc.
You would have a number A and possibly one more number B link to a number N for some numbers, but N would only link to one number C. For example:
A -> N -> C
3 -> 10 -> 5
20 -> 10 -> 5
B -> N -> C
Of course, you could optimize it by storing a length of the list and an extra pointer containing the next adjacent number, allowing you to implement a binary search using that length as a guide.
However, if you're only looking for the longest sequence length instead of the sequence itself, why aren't you merely storing the longest length found and comparing it to the length of the current sequence? Storing the numbers only for calculating the length seems like overkill. Something like the following pseudocode:
Longest := 0
For N = 1 To 1000000
Length := 1
X := N
While X != 1
Length := Length + 1
If IsEven(X) Then
X := 3 * X + 1
Else
X := X / 2
End If
End While
If Length > Longest Then
Longest := Length
End If
End For
Print("Longest sequence less than 1000000 is: ", Longest)
The line
n = 3 * n + 1;
ends up setting the value of n to be higher than the valid index. The highest valid index is 999999. You have to make sure that n is less than or equal to 1000000 before you access the array in:
if(array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
You don't check the array index [n-1] within the while loop to ensure it doesn't exceed the array bounds of 1,000,000. For example, in your first loop i = 999,999 which makes `n = 999999*3+1 = 2,999,998'.
Solution is to make sure n doesn't exceed your array size.

What needs to be modified to get desired result in this C code

I have written a small piece of code that would perform Run length encoding kind of stuff on 1-D array but still far from desired result.
main()
{
int a[8]={2,0,0,0,3,0,0,9};
int i,temp,ct=0,flag,m;
int found[90]={0};
for(i=0;i<=7;i++)
{
if(!a[i])
{
ct++;
if(!found[a[i]])
{
flag=i;
found[a[i]]=1;
}
}
}
a[flag]=ct;
m=ct;
for(i=0;i<m;i++)
{
printf("%d",a[i]);
}
}/* end of main*/
Now for above array i would like to have output something below
2 5 0 3 9
But with my piece of code am getting
2 5 0 0 3
Can I have any suggestion on that?
Shouldn't run length encoding turn 2,0,0,0,3,0,0,9 into 2 1 0 3 3 1 2 0 9 1?
1) The first thing I see is wrong is that you aren't looking at the entire array. You're using < to stop before 8, but also stopping at 7, so you only evaluate array items 0 - 6.
2) If ct stands for count it's never reset (ct=0 only on declaration). Also it's assignment is this: a[flag]= ct; which overwrites your original data. It basically tracks the value of i.
This is my version I've just put together:
#define SZ 8
main()
{
int a[SZ]={2,0,0,0,3,0,0,9};
int i; //absolute position
int runningCount = 1; //because we start at array index 1 and not zero
for (i = 1; i <= SZ; i++) {
if (a[i - 1] == a[i]) //value same as one before it...
runningCount++;
else { // new value found. print last one, and the count of the last one.
printf("%d %d ", a[i - 1], runningCount);
runningCount = 1; //reset for next loop
}
}
return 0;
}
The output is 2 1 0 3 3 1 0 2 9 1
Ok based on the comment left below, your algorithm would actually look like this:
#define SZ 8
main()
{
int a[SZ]={2,0,0,0,3,0,0,9};
int i; //absolute position
int zero_count = 0; //target zeros specifically...
for (i = 0; i < SZ; i++) {
if (a[i] == 0)
zero_count++;
}
//now write it out in a bizarre, unparsable format again...
for (i = 0; i < SZ; i++) {
if (a[i] != 0) //write out all non zero values
printf("%d ", a[i]);
if (i == 0) { //this says put the zero count after the first number was printed
printf("%d 0 ", zero_count); //inserting it into a strange place in the array
}
}
return 0;
}
which outputs: 2 5 0 3 9
You need a <= in your for loop:
for(i=0;i<=7;i++)
instead of
for(i=0;i< 7;i++)
Otherwise you miss the last element.
All you appear to be doing is (a) counting the number of times 0 occurs in the array, and (b) replacing the first occurrence of 0 with that count. It's not clear how this is meant to be a useful encoding.
In any case, you're not getting your desired result, at least in part, because you're only modifying one element of the array. I suspect what you want, or at least think you want, is to shift the non-zero elements of the array to the left as you encounter them.
What is the utility of compressing the array in the way you propose? Is some other piece of code going to have to reconstruct the original, and if so how do you expect to do so from your desired result?

Resources