"terminating" array in C [closed] - arrays

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
if my program needs an int array of size of at most 10 and my user is given the option to "terminate" the data set when entering -1, what are some ways i can acheive this?
By "terminating", I am referring to if my user enters -1 while inputting the values in the array, the array stopps scanning user input values immediately and returns the values that were entered previously, discarding -1.
The array size can be at most 10, but i do not know how to process the array when my user enters less than 10 values.
Example:
Enter data -> 1 2 3 4 5 -1
data[10] contains {1, 2, 3, 4, 5}
Enter data -> 1 2 3 4 5 6 7 8 9 10
data[10] contains {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Enter data -> 1 2 3 4 5 6 7 -1
data[10] = {1, 2, 3, 4, 5, 6, 7}
I'm not allowed to use break statements. Right now I can only think of searching for -1 and turning it and the reset of the values into 0. This is what i have so far:
int getValues(int arr[])
{
int loop; // used to iterate through for loop
int terminate; // used to iterate through for loop when user terminates data set
loop = 0;
terminate = 0;
printf("Enter 10 integer values -> ");
for (loop = 0; loop < 10; loop++)
{
scanf("%d", &arr[loop]);
if (arr[loop] == -1)
{
arr[loop] = 0;
for (terminate = loop; terminate < 10; terminate++)
{
arr[terminate] = 0;
}
}
}
printf("\n");
return 0;
}

Maybe you want this: We stop the loop as soon as the user has entered -1 but we simply store that -1 in the array and we use that -1 one as terminator.
#include <stdio.h>
int getValues(int arr[])
{
int loop; // used to iterate through for loop
printf("Enter 10 integer values -> ");
for (loop = 0; loop < 10; loop++)
{
scanf("%d", &arr[loop]);
if (arr[loop] == -1)
{
loop = 10 - 1; // simulate a break
}
}
printf("\n");
return 0;
}
int main()
{
int arr[10];
getValues(arr);
// print array values and stop at the -1 terminator
for (int i = 0; i < 10 && arr[i] != -1; i++)
printf("arr[%d] = %d\n", i, arr[i]);
}
Another possibility is to store the size of the array:
#include <stdio.h>
int getValues(int arr[], int *size)
{
int loop; // used to iterate through for loop
printf("Enter 10 integer values -> ");
for (loop = 0; loop < 10; loop++)
{
scanf("%d", &arr[loop]);
if (arr[loop] == -1)
{
*size = loop; // store the size
loop = 10 - 1; // simulate a break
}
}
printf("\n");
return 0;
}
int main()
{
int arr[10];
int size;
getValues(arr, &size);
// now size contains the number of elements of the array
for (int i = 0; i < size; i++)
printf("arr[%d] = %d\n", i, arr[i]);
}
There are still issues with this code:
the return value of scanf is ignored
there is no check for out of bounds array access, In other words, the user can enter more than 10 numbers and thus write beyond the array bounds which will lead to undefined behaviour (google that term).
the hard coded value 10 is all over the place

Related

countdown kick start wrong answer [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
i was trying this kick start question, the test give the right answer yet when submitting attempt it says wrong answer, it's second question i'm doing and not sure how this really works here's my code :
function :
int num_subarray (int array[], int array_size, int k) {
int sum = 0, j = 1, i;
for (i = array_size - 1; 0 <= i; i--) {
if (array[i] == j) j++;
else j = 1;
if (j == k) {
sum++;
j = 1;
}
}
return sum;
}
here's the main :
int main () {
int t, n, k, array[N], i, j = 1;
scanf ("%d", &t);
do {
scanf ("%d%d", &n, &k);
i = 0;
do {
scanf ("%d", &array[i]);
i++;
} while (i < n);
printf ("\n Case #%d: %d", j, num_subarray (array, n, k));
j++;
} while (j <= t);
return 0;
}
here's the question :
Countdown - Kick Start
Continuing from my comments, at least from my reading of the question, a k-countdown actually starts with 'k' and counts down to 1, so in the example a 3-countdown is 3, 2, 1 a 6-countdown is 6, 5, 4, 3, 2, 1, etc...
You are also given limits on the array size of 2x10^5 (200000). The consideration there is that on some compilers 200000 4-byte int values will exceed the default stack size, so you may as well make array a global or static to avoid that issue altogether.
Another check you will want to impose is on the read of the values from the file. You will have k at that point and for there to be a k-countdown, the input must contain k and it must be at an index of i < n - k in order for there to be enough elements left in that array to hold a k-countdown. so if you are given k = 10 in a 10-element input, if the 1st element isn't 10 -- that array can't hold a k-countdown (that implementation is left to you -- but if you are failing a large check -- I would suspect that as one of the probable causes)
Putting that together and using the function name kcountdowns instead of your num_subarray and using kcd as your sum, a quick attempt could look like:
#include <stdio.h>
#define NMAX 200000
int arr[NMAX]; /* global storage for array, up to 2x10^5 elements */
/** function to compute no. of kcountdowns in n elements of arr */
int kcountdowns (int n, int k)
{
int i = 0, /* array index */
in = 0, /* flag & counter in(true)/out(false) of a kcountdown */
kcd = 0; /* number of kcountdowns found */
do { /* loop over all elements */
if (in) { /* if in a kcountdown */
if (arr[i] + 1 == arr[i-1]) { /* check current is 1 less than last */
in++; /* increment in flag/count */
if (in == k) { /* full sequence found */
kcd += 1; /* add a kcountdown to sum */
in = 0; /* reset in 0/false */
}
}
else /* otherwise set flag false */
in = 0;
}
if (arr[i] == k) /* if k found, set in to 1-true */
in = 1;
} while (++i < n);
return kcd; /* return number of kcountdows found */
}
(note: the use of the global arr. Generally the use of global variables is discouraged, but here with the potential stack size issue, using a global or making the array static are two reasonable options)
A quick main() that leaves the input check to you to implement could be:
int main (void) {
int t;
if (scanf ("%d", &t) != 1 || t < 1 || 100 < t) /* read/validate t */
return 1;
for (int i = 0; i < t; i++) { /* loop over each case */
int n, k;
if (scanf ("%d %d", &n, &k) != 2 || n < 2 || n < k) /* read/validate n & k */
return 1;
for (int j = 0; j < n; j++) /* loop reading/validating elements */
if (scanf ("%d", &arr[j]) != 1)
return 1;
printf ("Case #%d: %d\n", i + 1, kcountdowns (n, k)); /* output result */
}
(note: you would normally want to read each line into a buffer so you can enforce a validation of only reading a single line of input for the array values. Reading with scanf -- it will happily ignore a '\n' and start reading the next testcase if there is a defect in the input file)
At least with the input given, the results match all testcases, e.g.
Example Test Input
3
12 3
1 2 3 7 9 3 2 1 8 3 2 1
4 2
101 100 99 98
9 6
100 7 6 5 4 3 2 1 100
Example Use/Output
$ ./bin/kcountdown <dat/kcountdown.txt
Case #1: 2
Case #2: 0
Case #3: 1
error check:
$ echo $?
0
Let me know if you have further questions.

Why doesn't my nested for / do-while loop to sort through an array not output my final prints in C?

Why can't I get this loop to stop? My tracker is an array filled with a random number of elements in the range of 1 to 10. Lets say the size of this array is 50. I want to check all values 1 to 10 are in the array by checking the entry of when the number appears first in the array. I also want to keep track of the biggest value for the entry and store it as numberOfHops and so if all numbers are in the array, the output should be numberOfHops.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, k, m, entry = 0, numberOfHops = 0;
const int L = 10;
int tracker[50] ={1, 2, 3, 2, 1, 10, 9, 8, 7 , 6 //etc etc//};
int sitesVisited = 0;
for (k =1; k<=L; k++ )
{ do {
m=0;
if (k == tracker[m])
{
sitesVisited += 1;
entry = m;
}
if (entry > numberOfHops)
{
numberOfHops = entry;
}
m++;
} while (sitesVisited < k);
}
if (sitesVisited == L) {
printf("Particle took %d hops to explore environment.\n", numberOfHops);
}
else {
printf("Particle did not explore entire environment.");
}
}
The problem is in m=0; line. You should declare it before do { cycle start.
Every loop you initialize it with 0 instead of increasing.

Finding duplicate values in array in c

I am trying to find the duplicate values in an array. When a number is duplicated once like (25,25) program correctly prints 25 once but when a number duplicated twice like (12,12,12) program prints 12 three times while it should print it once.
#include<stdio.h>
int main()
{
int numbers[15]={1,1,2,2,2,3,4,5,6,6,7,7,7,8,9},i,j;
for(i=0;i<15;i++)
{
for(j=i;j<14;j++)
{
if(numbers[i]==numbers[j+1])
{
printf("Number %d has duplicate values\n",numbers[i]);
}
}
}
return 0;
}
Output:
Number 1 has duplicate values
Number 2 has duplicate values
Number 2 has duplicate values
Number 2 has duplicate values
Number 6 has duplicate values
Number 7 has duplicate values
Number 7 has duplicate values
Number 7 has duplicate values
The arrays cannot be assumed to be ordered so the program should work even with {1,2,1,2,3,4,2,5,6,6,7,7,7,8,9}.
The problem at hand is essentially simple. There is no need for any complicated code fragments. All it takes is just a little modification to the limits of the for loops and how you check for duplicates.
The solution:
Just introduce another array which is going to store the elements which are repeated in the array. Start filling this array from the 0th index as and when you find a NEWLY REPEATED element. This can easily be done iterating through this new array and checking if the currently encountered repeated element is already present or not. If it is not present there, then insert into the new array, which in the code I have given below is arr2[].
Hence whatever elements will be held by this new array are the unique repeated elements. I have attached the code and corresponding output below.
CODE:
#include<stdio.h>
int main()
{
int numbers[15] = {1,1,2,2,2,3,4,5,6,6,7,7,7,8,9}, i, j;
int arr2[15], k = 0, k1 = 0;
int flag = 0;
for(i = 0; i < 15; i++)
{
for(j = 0; j < 15; j++)
{
flag = 0;
if(i != j && numbers[i] == numbers[j])
{
for(k1 = 0; k1 < k; k1++)
if(arr2[k1] == numbers[j])
flag = 1;
if(flag != 1)
arr2[k++] = numbers[j];
}
}
}
for(i = 0; i < k; i++)
printf("Number %d has duplicate values\n",arr2[i]);
return 0;
}
OUTPUT:
Number 1 has duplicate values
Number 2 has duplicate values
Number 6 has duplicate values
Number 7 has duplicate values
Hope this helps.
A solution which doesn't introduce additional memory requirements and finds unique duplicates in a worst case of O(N²):
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
// macro that evaluates to the number of elements in an array:
#define SIZEOF_ARRAY(arr) sizeof(arr) / sizeof(*arr)
// contains() returns true if [values, values + size) contains value
bool contains(int *values, size_t size, int value)
{
for (size_t i = 0; i < size; ++i)
if (values[i] == value)
return true;
return false;
}
int main(void)
{
int numbers[] = { 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8, 9 };
for (size_t i = 0; i < SIZEOF_ARRAY(numbers) - 1; ++i)
{
if (contains(numbers, i, numbers[i])) // if we already encountered numbers[i]
continue; // it was already identified as dup.
if(contains(numbers + i + 1, SIZEOF_ARRAY(numbers) - i , numbers[i]))
printf("Number %d has duplicate values\n", numbers[i]);
}
}
Output:
Number 1 has duplicate values
Number 2 has duplicate values
Number 6 has duplicate values
Number 7 has duplicate values
If you deal with low numbers, you can always go via index table
#include <stdio.h>
int main() {
int index[256] = {0};
int table[15] = {1, 2, 3, 5, 5, 6, 1, 2, 9, 10, 11, 2, 3, 4, 5 };
for(int i=0; i<15; i++) {
index[table[i]] ++;
}
for(int i=0; i<256; i++) {
index[i] > 1 ? printf("%d\n",i) : 0;
}
}
In your example consider the indexes of the 7: they are 10, 11, 12.
The first print happens when i=10 and j=10 because your are indexing numbers[10] and numbers[11].
At the next iteration of the inner loop you have i=10 and j=11 and the condition is verified again by the elements numbers[10] and numbers[12].
Finally the third condition happens when i=11 and j=11 because you are referring to numbers[11] and numbers[12].
All this becomes clear if you print your indexes when the condition happens. For example you can substitute your printf with this:
printf("Number %d has duplicate values with indexes i=%d, j=%d\n",numbers[i], i,j);
which prints:
Number 1 has duplicate values with indexes i=0, j=0
Number 2 has duplicate values with indexes i=2, j=2
Number 2 has duplicate values with indexes i=2, j=3
Number 2 has duplicate values with indexes i=3, j=3
Number 6 has duplicate values with indexes i=8, j=8
Number 7 has duplicate values with indexes i=10, j=10
Number 7 has duplicate values with indexes i=10, j=11
Number 7 has duplicate values with indexes i=11, j=11
If your values are ordered you can do something like this:
#include<stdio.h>
int main()
{
int numbers[15]={1,1,2,2,2,3,4,5,6,6,7,7,7,8,9},i,j;
int last_dup = -1;
for(i=0;i<15;i++)
{
for(j=i+1;j<14;j++)
{
if(numbers[i]==numbers[j] && numbers[i]!=last_dup)
{
printf("Number %d has duplicate values with indexes i=%d, j=%d\n",numbers[i], i,j);
last_dup = numbers[i];
break;
}
}
}
return 0;
}
I initialized to -1 assuming your numbers are all positive. If not you can save the index of the last duplicate and reference using in the check numbers[last_dup_idx] (be careful to initialize the value properly and not go out the length of the array). I also added a break: since you already found a duplicate there is no need to continue the second loop.
If your array is not ordered, you can create an additional array saving the duplicates elements every time you find one and then iterate through this array to check.
FOR NOT ORDERED ARRAYS
#include<stdio.h>
int main()
{
int numbers[15]={1,1,2,2,2,3,4,5,6,6,7,7,7,8,9},i,j;
int dups [7];//at most 15/2 duplicates
char dup_idx=0;
char found_new_duplicate; //initialized later
for(i=0;i<15;i++)
{
for(j=i+1;j<14;j++)
{
if(numbers[i]==numbers[j])
{
found_new_duplicate = 1;
//check in the duplicates array
for (int kk=0; kk<=dup_idx; kk++)
{
if (dups[kk]==numbers[i] && !(i==0 && j==1))
{
found_new_duplicate = 0;
break;
}
}
if (found_new_duplicate)
{
dups[dup_idx] = numbers[i]; //insert the new duplicate in the duplicates array
printf("Number %d has duplicate values with indexes i=%d, j=%d\n",numbers[i], i,j);
printf("New duplicate %d\n", dups[dup_idx]);
dup_idx++;//increase the index
break;
}
}
}
}
for (int kk=0; kk< dup_idx; kk++)
printf("%d\n", dups[kk]);
return 0;
}

Printing stars for a specific number of freq in arrays

I am still new to C, and I need to figure a way to print the same number of stars as the number of frequencies.
Here's my code:
int arrayHistogram(int array[]){
int i;
int j;
int count=0;
int freq[SIZE];
char stars[SIZE];
for(i = 0; i < SIZE; i++){
count =1;
for(j = i+1; j < SIZE; j++){
if(array[i]==array[j]){
count++;
freq[j]=0;
}
}
if(freq[i] != 0){
freq[i] = count;
}
}
//for ( i = 0; i < SIZE; i++){
//int num = freq[i];
//stars[i]= '*'*num;
}
printf("Value ");
printf("Frequency ");
printf("Histogram\n");
for(i = 0; i < SIZE; i++){
if(freq[i] != 0){
printf("%5d%10d%10d\n", array[i], freq[i], stars[i]);
}
}
}
I know that I can't multiply char by int here to print the stars, but I put here just to show where I need to print those stars (i.e. the histogram).
My Output:
Value Frequency Histogram
7 4 -46
8 3 126
4 6 84
Expected output:
Value Frequency Histogram
7 4 ****
8 3 ***
4 6 ******
Well, you already know everything to do that i.e. loop.
Simply, loop up to a frequency and print that many stars.
Something like this (pseudo code):
loop until freq[i]
print '*'
end loop
It's just an idea. You know how a loop works. Just put a nested loop (i.e. for loop) where you need to print the stars. Mind the newline. You need a newline at the end of each line after printing the stars.
UPDATE:
As observed, you've frequencies up to 10 i.e. a fixed size that you already know. You can simply use a string of stars and then print it using printf() with %.*s format specifier with field width and string length.
Here's an example (live code):
#include <stdio.h>
#define SIZE 10
int main(void)
{
const char* stars = "**********";
const int freqs[ SIZE ] = { 3, 5, 6, 2, 0, 7, 10, 9, 4, 8 };
for ( int i = 0; i < SIZE; i++ )
{
printf("%5d \t %10.*s\n", freqs[i], freqs[i], stars);
}
return 0;
}
OUTPUT:
3 ***
5 *****
6 ******
2 **
0
7 *******
10 **********
9 *********
4 ****
8 ********
how about building char stars[SIZE] with a loop?
int nStars = freq; // in you situation.
for(int i=0; i < nStars;++i)
{
stars[i] = '*'; // set char i to be '*'
}
stars[nStars] = '\0'; // don't forget to terminate your string
you can make a simple utility function void fillChar(char* buff, char ch, int count); of it.
Take Caution not to exceed the size of the allocated string or bad things gona happen.
Cheers.

How to get indexes alone from an array

I have the following array and index
0 1 2 3 4 5 6 7 8 <-indexes -- n values
7 7 8 8 6 9 8 7 9 <-values -- array x
I have another array with the indices
0 1 2 3 4 5 6 7 8 <-indexes -- m values
7 8 9 9 8 7 7 8 9 <-values -- array y
what I want is to obtain all the index(in reverse order of array x):
6: 4
7: 7 1 0
8: 6 3 2
9: 8 5
And then, for each element in the y array, I want to make another array index[ ] have the values. So, index[6] = 4, index[7] = 7, 1, 0 etc.
I have done:
for (i=n-1; i>=0; i--) {
index[y[i]] = index[y[i]]+i;
}
for (i=0; i<m; i++) {
strings[i] = strings[i] + index[x[i]];
}
for (i=0; i<m; i++) {
printf("%d",strings[i]);
}
The desired output is to print a sequence like 710632858563271071063285 but this is not printing the desired output.
int i;
int j;
// Assuming 9 is the highest integer possible
for(j=0;j<=9;j++){
int k=0;
for(i=n-1;i>=0;i--){
if(x[i]==j){
index[j][k]=i;
k++;
}
}
// Adding a -1 to denote that no more indices were found
index[j][k]=-1;
}
PS: Make sure that index is big enough...
#include <stdio.h>
#include <string.h>
int main(void) {
int x[] = {7, 7, 8, 8, 6, 9, 8, 7, 9};
int n = sizeof(x)/sizeof(*x);
int y[] = {7, 8, 9, 9, 8, 7, 7, 8, 9};
int m = sizeof(y)/sizeof(*y);
int index[10][10];
memset(index, -1, sizeof(index));
for(int i = n -1; i >= 0; --i){
int j = 0;
while(index[x[i]][j] >= 0)
++j;
index[x[i]][j] = i;
}
for(int i = 0; i < m; ++i){
for(int j = 0; j < 10 && index[y[i]][j] >= 0; ++j){
printf("%d", index[y[i]][j]);
}
}
return 0;
}
I'd say that array is not the best for this purpose as you have to iterate multiple times over it every time you want to know what numbers are at what indexes. If memory isn't an issue you will do much better with combination of data structures to efficiently perform this task.
An array is fine for matching index with value. What I suggest is to keep numbers in linked list. Every node would also keep linked list of indexes that number appears on. This way you'd do much better because of search time.
Adding value would mean that you:
1) check if there is already value at given index in an array. If there is - you remove this index from linked list of indexes for given number.
2) Then you put new value at given index and if this is first appearance of this value, else you add new index to list of indexes this value appears.
If you implement adding to the linked list of indexes in descending order to get all the numbers and indexes you just need to iterate over list of values and print list of indexes.
This might look like an overkill but I don't know a thing about the actual problem at hand. Your array might be thousands indexes long. That would set you up for handling these more efficiently.
try this one:
#include <stdio.h>
int main()
{
int A[]={7,7,8,8,6,9,8,7,9};
for(int i=0;i<=9;i++)
{
int flag=0;
for(int j=8;j>=0;j--)
{
if(A[j]==i)
{
if(flag==0)
printf("%d:",i);
flag=1;
printf(" %d",j);
}
}
if(flag==1)
printf("\n");
}
return 0;
}
This should work as expected. Note, that the main loop is simpler than the output loop.
#include <stdio.h>
int idx[9][9] = {{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1}};
int x[9] = {7, 7, 8, 8, 6, 9, 8, 7, 9};
void buildIndex(int maxval, int idx_len, int x_len) {
assert(maxval >= x_len);
for(int i = 0; i < x_len; i++)
for(int j = idx_len - 1; j >= 0; j--)
if(idx[x[i]-1][j] == -1) {
idx[x[i]-1][j] = i;
break;
}
}
int main() {
buildIndex(9, 9, 9);
/* output the idx */
for(int k = 0; k < 9; k++)
if(idx[k][8] != -1) { /* ignore empty idx lines */
printf("%d: ", k+1);
for(int l = 0; l < 9; l++)
if(idx[k][l] != -1) /* write all valid numbers */
printf("%d ", idx[k][l]);
printf("\n");
}
}
This program outputs:
6: 4
7: 7 1 0
8: 6 3 2
9: 8 5
I am sure, you can adapt the output to your needs yourself. The "big" idea in this code is to fill the arrays in idx backwards and in the output just ignore the unset values at the beginning.

Resources