Size of Array not showing the expectation - c

The goal is to get the number of even arrays and that of the odd arrays.
The output should be approximately 50% each, I have tried:
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
int arr[10]={0}, random_number, i, odd_saver[]={0}, even_saver[]={0};
srand( time( NULL ) );
for (i=0; i<10000; i++){
random_number= (10*rand())/(RAND_MAX+1);
arr[random_number]+=1;
if (arr[random_number]%2==0){
even_saver[random_number]+=1;
}else{
odd_saver[random_number]+=1;
}
}
printf("\n");
size_t even_size = sizeof(even_saver[random_number]) / sizeof(even_saver[0]);
size_t odd_size = sizeof(odd_saver[random_number]) / sizeof(odd_saver[0]);
printf("%d %.2f%%\n", (int)even_size, (double)(even_size*100)/10000);
printf("%d %.2f%%\n", (int)odd_size, (double)(odd_size*100)/10000);
return 0;
}
but the output is not according to my expectation.
I need help, and more explanation about what I am doing wrong will be highly appreciated.
The output:
1 0.01%
1 0.01%

As H.R. Emon has implied, in C you cannot create odd_saver[]={0}, even_saver[]={0}; as arrays of size 1 and later try to increase their size by adding to them.
You aim to calculate your indexes for accessing all arrays in your code to be 0..9, which matches the array arr of size 10. (Though the method of calculating random numbers could be discussed...)
With that assumption, you can create all of your arrays the same way:
int arr[10]={0}, random_number, i, odd_saver[10]={0}, even_saver[10]={0};
I think your goal is to output the number of different even and different odd numbers (i.e. not counting multiple occurences of the same).
For that you cannot use the size of the even/odd arrays. For one because in C there are no dynamically growing arrays (as H.R. Emon has pointed out). But also because once you have an 8 or 9 occurring, incrementing that index in the arrays would (if such arrays would exist in C) falsely get you too high a size.
You will simply have to count the non-zeros in your even/odd arrays.
(By the way, it should be possible to use even/odd arrays of half the size, by dividing the index by 2 and using appropriate offsets.)

i am afraid you are trying to do things that c doesn't allow you to do. you are trying to invoke dynamic array in c. but c don't support dynamic array. so it will lead to you undefined behavior. if you need dynamic allocation you can use vector std::vector it's a stl function which helps you to use to allocate memory dynamically.
vector details

Related

How to solve a runtime error happening when I use a big size of static array

my development environment : visual studio
Now, I have to create a input file and print random numbers from 1 to 500000 without duplicating in the file. First, I considered that if I use a big size of local array, problems related to heap may happen. So, I tried to declare as a static array. Then, in main function, I put random numbers without overlapping in the array and wrote the numbers in input file accessing array elements. However, runtime errors(the continuous blinking of the cursor in the console window) continue to occur.
The source code is as follows.
#define SIZE 500000
int sort[500000];
int main()
{
FILE* input = NULL;
input = fopen("input.txt", "w");
if (sort != NULL)
{
srand((unsigned)time(NULL));
for (int i = 0; i < SIZE; i++)
{
sort[i] = (rand() % SIZE) + 1;
for (int j = 0; j < i; j++)
{
if (sort[i] == sort[j])
{
i--;
break;
}
}
}
for (int i = 0; i < SIZE; i++)
{
fprintf(input, "%d ", sort[i]);
}
fclose(input);
}
return 0;
}
When I tried to reduce the array size from 1 to 5000, it has been implemented. So, Carefully, I think it's a memory out phenomenon. Finally, I'd appreciate it if you could comment on how to solve this problem.
“First, I considered that if I use a big size of local array, problems related to heap may happen.”
That does not make any sense. Automatic local objects generally come from the stack, not the heap. (Also, “heap” is the wrong word; a heap is a particular kind of data structure, but the malloc family of routines may use other data structures for managing memory. This can be referred to simply as dynamically allocated memory or allocated memory.)
However, runtime errors(the continuous blinking of the cursor in the console window)…
Continuous blinking of the cursor is normal operation, not a run-time error. Perhaps you are trying to say your program continues executing without ever stopping.
#define SIZE 500000<br>
...
sort[i] = (rand() % SIZE) + 1;
The C standard only requires rand to generate numbers from 0 to 32767. Some implementations may provide more. However, if your implementation does not generate numbers up to 499,999, then it will never generate the numbers required to fill the array using this method.
Also, using % to reduce the rand result skews the distribution. For example, if we were reducing modulo 30,000, and rand generated numbers from 0 to 44,999, then rand() % 30000 would generate the numbers from 0 to 14,999 each two times out of every 45,000 and the numbers from 15,000 to 29,999 each one time out of every 45,000.
for (int j = 0; j < i; j++)
So this algorithm attempts to find new numbers by rejecting those that duplicate previous numbers. When working on the last of n numbers, the average number of tries is n, if the selection of random numbers is uniform. When working on the second-to-last number, the average is n/2. When working on the third-to-last, the average is n/3. So the average number of tries for all the numbers is n + n/2 + n/3 + n/4 + n/5 + … 1.
For 5000 elements, this sum is around 45,472.5. For 500,000 elements, it is around 6,849,790. So your program will average around 150 times the number of tries with 500,000 elements than with 5,000. However, each try also takes longer: For the first try, you check against zero prior elements for duplicates. For the second, you check against one prior element. For try n, you check against n−1 elements. So, for the last of 500,000 elements, you check against 499,999 elements, and, on average, you have to repeat this 500,000 times. So the last try takes around 500,000•499,999 = 249,999,500,000 units of work.
Refining this estimate, for each selection i, a successful attempt that gets completely through the loop of checking requires checking against all i−1 prior numbers. An unsuccessful attempt will average going halfway through the prior numbers. So, for selection i, there is one successful check of i−1 numbers and, on average, n/(n+1−i) unsuccessful checks of an average of (i−1)/2 numbers.
For 5,000 numbers, the average number of checks will be around 107,455,347. For 500,000 numbers, the average will be around 1,649,951,055,183. Thus, your program with 500,000 numbers takes more than 15,000 times as long than with 5,000 numbers.
When I tried to reduce the array size from 1 to 5000, it has been implemented.
I think you mean that with an array size of 5,000, the program completes execution in a short amount of time?
So, Carefully, I think it's a memory out phenomenon.
No, there is no memory issue here. Modern general-purpose computer systems easily handle static arrays of 500,000 int.
Finally, I'd appreciate it if you could comment on how to solve this problem.
Use a Fischer-Yates shuffle: Fill the array A with integers from 1 to SIZE. Set a counter, say d to the number of selections completed so far, initially zero. Then pick a random number r from 1 to SIZE-d. Move the number in that position of the array to the front by swapping A[r] with A[d]. Then increment d. Repeat until d reaches SIZE-1.
This will swap a random element of the initial array into A[0], then a random element from those remaining into A[1], then a random element from those remaining into A[2], and so on. (We stop when d reaches SIZE-1 rather than when it reaches SIZE because, once d reaches SIZE-1, there is only one more selection to make, but there is also only one number left, and it is already in the last position in the array.)

Making a character array rotate its cells left/right n times

I'm totally new here but I heard a lot about this site and now that I've been accepted for a 7 months software development 'bootcamp' I'm sharpening my C knowledge for an upcoming test.
I've been assigned a question on a test that I've passed already, but I did not finish that question and it bothers me quite a lot.
The question was a task to write a program in C that moves a character (char) array's cells by 1 to the left (it doesn't quite matter in which direction for me, but the question specified left). And I also took upon myself NOT to use a temporary array/stack or any other structure to hold the entire array data during execution.
So a 'string' or array of chars containing '0' '1' '2' 'A' 'B' 'C' will become
'1' '2' 'A' 'B' 'C' '0' after using the function once.
Writing this was no problem, I believe I ended up with something similar to:
void ArrayCharMoveLeft(char arr[], int arrsize, int times) {
int i;
for (i = 0; i <= arrsize ; i++) {
ArraySwap2CellsChar(arr, i, i+1);
}
}
As you can see the function is somewhat modular since it allows to input how many times the cells need to move or shift to the left. I did not implement it, but that was the idea.
As far as I know there are 3 ways to make this:
Loop ArrayCharMoveLeft times times. This feels instinctively inefficient.
Use recursion in ArrayCharMoveLeft. This should resemble the first solution, but I'm not 100% sure on how to implement this.
This is the way I'm trying to figure out: No loop within loop, no recursion, no temporary array, the program will know how to move the cells x times to the left/right without any issues.
The problem is that after swapping say N times of cells in the array, the remaining array size - times are sometimes not organized. For example:
Using ArrayCharMoveLeft with 3 as times with our given array mentioned above will yield
ABC021 instead of the expected value of ABC012.
I've run the following function for this:
int i;
char* lastcell;
if (!(times % arrsize))
{
printf("Nothing to move!\n");
return;
}
times = times % arrsize;
// Input checking. in case user inputs multiples of the array size, auto reduce to array size reminder
for (i = 0; i < arrsize-times; i++) {
printf("I = %d ", i);
PrintArray(arr, arrsize);
ArraySwap2CellsChar(arr, i, i+times);
}
As you can see the for runs from 0 to array size - times. If this function is used, say with an array containing 14 chars. Then using times = 5 will make the for run from 0 to 9, so cells 10 - 14 are NOT in order (but the rest are).
The worst thing about this is that the remaining cells always maintain the sequence, but at different position. Meaning instead of 0123 they could be 3012 or 2301... etc.
I've run different arrays on different times values and didn't find a particular pattern such as "if remaining cells = 3 then use ArrayCharMoveLeft on remaining cells with times = 1).
It always seem to be 1 out of 2 options: the remaining cells are in order, or shifted with different values. It seems to be something similar to this:
times shift+direction to allign
1 0
2 0
3 0
4 1R
5 3R
6 5R
7 3R
8 1R
the numbers change with different times and arrays. Anyone got an idea for this?
even if you use recursion or loops within loops, I'd like to hear a possible solution. Only firm rule for this is not to use a temporary array.
Thanks in advance!
If irrespective of efficiency or simplicity for the purpose of studying you want to use only exchanges of two array elements with ArraySwap2CellsChar, you can keep your loop with some adjustment. As you noted, the given for (i = 0; i < arrsize-times; i++) loop leaves the last times elements out of place. In order to correctly place all elements, the loop condition has to be i < arrsize-1 (one less suffices because if every element but the last is correct, the last one must be right, too). Of course when i runs nearly up to arrsize, i+times can't be kept as the other swap index; instead, the correct index j of the element which is to be put at index i has to be computed. This computation turns out somewhat tricky, due to the element having been swapped already from its original place. Here's a modified variant of your loop:
for (i = 0; i < arrsize-1; i++)
{
printf("i = %d ", i);
int j = i+times;
while (arrsize <= j) j %= arrsize, j += (i-j+times-1)/times*times;
printf("j = %d ", j);
PrintArray(arr, arrsize);
ArraySwap2CellsChar(arr, i, j);
}
Use standard library functions memcpy, memmove, etc as they are very optimized for your platform.
Use the correct type for sizes - size_t not int
char *ArrayCharMoveLeft(char *arr, const size_t arrsize, size_t ntimes)
{
ntimes %= arrsize;
if(ntimes)
{
char temp[ntimes];
memcpy(temp, arr, ntimes);
memmove(arr, arr + ntimes, arrsize - ntimes);
memcpy(arr + arrsize - ntimes, temp, ntimes);
}
return arr;
}
But you want it without the temporary array (more memory efficient, very bad performance-wise):
char *ArrayCharMoveLeft(char *arr, size_t arrsize, size_t ntimes)
{
ntimes %= arrsize;
while(ntimes--)
{
char temp = arr[0];
memmove(arr, arr + 1, arrsize - 1);
arr[arrsize -1] = temp;
}
return arr;
}
https://godbolt.org/z/od68dKTWq
https://godbolt.org/z/noah9zdYY
Disclaimer: I'm not sure if it's common to share a full working code here or not, since this is literally my first question asked here, so I'll refrain from doing so assuming the idea is answering specific questions, and not providing an example solution for grabs (which might defeat the purpose of studying and exploring C). This argument is backed by the fact that this specific task is derived from a programing test used by a programing course and it's purpose is to filter out applicants who aren't fit for intense 7 months training in software development. If you still wish to see my code, message me privately.
So, with a great amount of help from #Armali I'm happy to announce the question is answered! Together we came up with a function that takes an array of characters in C (string), and without using any previously written libraries (such as strings.h), or even a temporary array, it rotates all the cells in the array N times to the left.
Example: using ArrayCharMoveLeft() on the following array with N = 5:
Original array: 0123456789ABCDEF
Updated array: 56789ABCDEF01234
As you can see the first cell (0) is now the sixth cell (5), the 2nd cell is the 7th cell and so on. So each cell was moved to the left 5 times. The first 5 cells 'overflow' to the end of the array and now appear as the Last 5 cells, while maintaining their order.
The function works with various array lengths and N values.
This is not any sort of achievement, but rather an attempt to execute the task with as little variables as possible (only 4 ints, besides the char array, also counting the sub function used to swap the cells).
It was achieved using a nested loop so by no means its efficient runtime-wise, just memory wise, while still being self-coded functions, with no external libraries used (except stdio.h).
Refer to Armali's posted solution, it should get you the answer for this question.

2-D Array in C storing user inputs

total C newbie here. Thanks for any help beforehand.
I am required to write a code which has the following properties:
Asking user to input the number of rows and columns they would like in their 2-D array
creates a 2-D array with that many rows and columns for storing integers
fills the array with random numbers between 1 and 1000
outputs the largest number in the array
This is where I could go for now:
#include <stdio.h>
int main(){
int rows;
int columns;
scanf("%d", &rows);
scanf("%d", &columns);
}
What should I do?
Sorry for the very open question, I am stuck and don't know what to do. A guideline will be perfect. Thanks :)
EDIT:
Thanks for the guideline, here is how I solved it:
SOLUTION:
#include <stdio.h>
#include <time.h>
int main () {
//Declare variables
int a,b,k,l,big,z[100][100];
//Ask user input
printf("ENTER ROWS & COLUMNS\n");
scanf("%d\n%d", &a, &b);
//Randomize array values
srand(time(NULL));
big = 1;
for (k=0;k<a;k++){
for(l=0;l<b;l++){
z[k][l]=rand()%1000 + 1;
if(z[k][l]>big) big=z[k][l];
printf("%d\t", z[k][l]);
}
printf("\n");
}
//Print biggest number
printf("\nBIGGEST NUMBER IN THE ARRAY: %d", big);
return 0;
}
A guideline will be perfect.
okay... let's go...
Asking user to input the number of rows and columns they would like in their 2-D array
Use scanf or better fgets followed by sscanf
creates a 2-D array with that many rows and columns for storing integers
Use malloc (search the net for "how to correctly malloc a 2D array" or simply see Correctly allocating multi-dimensional arrays)
fills the array with random numbers between 1 and 1000
Use srand, rand and the % operator
outputs the largest number in the array
Iterate all elements of the array and compare against a running max.
C does not support natively 2D arrays, you need to allocate an array of arrays. You don't know the size in advance, so you need to allocate the arrays memory dynamically using malloc.
For generating random numbers, you could use rand, but you need to set a seed first for the sequence of the pseudo-random integers using srand to get (possibly) a different number on every execution, or you can use rand_r to do the both operation with one function. Note that rand generate a random number between 0 and RAND_MAX, you need to use a trick with the modulus operator % to generate a random number in a specific range [min, max].
min + (rand() % (max - min + 1))
You can iterate over the arrays with two loops, to get the maximum number.
To know how to use these function, you can read the man pages: malloc rand
As a side note, you don't really need the 2D array to get the maximum number, you can calculate it directly with allocating any additional memory.
Your solution will work, but it's limited to 100 columns and 100 rows. If for instance the user enters higher numbers, your code will mostly crash. One solution is to validate the input and refuse numbers above 100 if you don't want to handle dynamic memory allocation, but in real world that is very much rare and dynamic memory allocation is a necessary.
You shouldn't name your variables with one-character names, especially if they live long. A good descriptive name like columnsNumber is preferred.

Optimising C for performance vs memory optimisation using multidimensional arrays

I am struggling to decide between two optimisations for building a numerical solver for the poisson equation.
Essentially, I have a two dimensional array, of which I require n doubles in the first row, n/2 in the second n/4 in the third and so on...
Now my difficulty is deciding whether or not to use a contiguous 2d array grid[m][n], which for a large n would have many unused zeroes but would probably reduce the chance of a cache miss. The other, and more memory efficient method, would be to dynamically allocate an array of pointers to arrays of decreasing size. This is considerably more efficient in terms of memory storage but would it potentially hinder performance?
I don't think I clearly understand the trade-offs in this situation. Could anybody help?
For reference, I made a nice plot of the memory requirements in each case:
There is no hard and fast answer to this one. If your algorithm needs more memory than you expect to be given then you need to find one which is possibly slower but fits within your constraints.
Beyond that, the only option is to implement both and then compare their performance. If saving memory results in a 10% slowdown is that acceptable for your use? If the version using more memory is 50% faster but only runs on the biggest computers will it be used? These are the questions that we have to grapple with in Computer Science. But you can only look at them once you have numbers. Otherwise you are just guessing and a fair amount of the time our intuition when it comes to optimizations are not correct.
Build a custom array that will follow the rules you have set.
The implementation will use a simple 1d contiguous array. You will need a function that will return the start of array given the row. Something like this:
int* Get( int* array , int n , int row ) //might contain logical errors
{
int pos = 0 ;
while( row-- )
{
pos += n ;
n /= 2 ;
}
return array + pos ;
}
Where n is the same n you described and is rounded down on every iteration.
You will have to call this function only once per entire row.
This function will never take more that O(log n) time, but if you want you can replace it with a single expression: http://en.wikipedia.org/wiki/Geometric_series#Formula
You could use a single array and just calculate your offset yourself
size_t get_offset(int n, int row, int column) {
size_t offset = column;
while (row--) {
offset += n;
n << 1;
}
return offset;
}
double * array = calloc(sizeof(double), get_offset(n, 64, 0));
access via
array[get_offset(column, row)]

C Programming : Sum of third upper anti-diagonal a squared matrix , help badly needed please

im doing a short course in c programming and i have been so busy lately with my other classes and and helping my bother prepare for his wedding (as im his best man)that I have fallen behind and need help. any help towards this short assignment would be much appreciated as im not familiar at all with matrixs and its due in a few days.
the assignment is to Sum of third upper anti-diagonal a squared matrix .
i have been given this information:
The matrix should be a square, integer matrix of size N. In this assignment the matrix will be stored
in a 1d block of memory. You will have to convert between the conceptual 2d matrix addressing and
1d block addressing with pointer arithmetic.
Note on random numbers:
rand() function returns the next integer a sequence of pseudo-random integers in the range
[0, RAND_MAX]. RAND_MAX is a very large number and varies from system to system. To get an
integer in the range [min, max]:
(int)((min)+rand()/(RAND_MAX+1.0) * ((max)-(min)+1))
srand(SEED) is used to set the seed for rand. If srand() is called with the same seed value, the
sequence of pseudo-random numbers is repeated. To get different random numbers each time a
programme runs use time(NULL) as the seed. Rand is in stdlib.h, which needs to be included.
The program should be structured as follows.
#define N 32 // Matrix size
#define MYSEED 1234 // Last 4 digits of your student number.
int *initialise( ) // Allocate memory for the matrix using malloc
// Initialise the matrix with random integers x, 1≤ x ≤ 9
// Use 'MYSEED' as the seed in the random generator.
// Return a pointer to the matrix
void print_matrix(int *) // Print matrix on screen
int compute_diagonal(int *) // Compute your required calculation using pointer arithmetic.
// (square bracket [ ] array indexes shouldn't be used)
// Return the solution.
void finalise(int *) //free the allocated memory.
int main() // The main function should print the solution to screen.
Without doing your homework assignment for you, here's a tip:
Make a functions that abstract storing and retrieving values out of the matrix. One of the signatures should look a lot like this:
int retrieve(int* matrix, int row, int col);
Ok since this is homework and you still have a few days I will not give you an exact answer here. But I will give you some thoughts with which it should be pretty easy to come to your answer.
Indexing a matrix 1D-way: You are not allowed to use matrix[x][y] here, but only a one-dimensional array. So just take a minute and think of how the index (x,y) can be computed within a 1D array. Keep in mind that C stores elements rowwise (i.e. the elements matrix[0][0], matrix[0][1], matrix[0][2] refer to matrix[0], matrix[1], matrix[2]). It is a simply forumla in terms of X, Y and N
Filling the matrix randomly is easy, the function to create a random int is already given, just walk the matrix along and fill every element
Adding the third anti-upper diagonal. This isn really a programming question. Just sketch a small matrix on a piece of paper and see what elements you have to add. Look at their indices and than combine your newly gained knowledge with your result from my point 1 and you will know what to add up
Edit: Since you are not allowed to use the bracket operator, keep in mind that matrix[5] is the same as *(matrix+5).
I think it's fair to tell you this ;)

Resources