How to split/divide array using user input - c

#include <stdio.h>
int main( )
{
int length = 0;
int divide = 0;
int count = 0;
int i;
printf("Set the length of array: \n");
scanf("%d", &length);
int array[length];
for(i = 0; i < length; i++)
{
scanf("%d", &array[i]);
}
printf("Divide array into subarray: \n");
scanf("%d", &divide);
for(i = 0; i < divide; i++)
{
int countfrom = length / divide * i;
int countto = countfrom + length / divide;
for(int j = countfrom; j < countto; j++)
{
if( array[j] == 1 && array[j+1] == 0 && array[j+2] == 1)
{
count++;
}
}
}
printf("count: %d\n", count);
return 0;
}
This is what I have so far. The purpose is to define the length of array from user input and divide it into subarray (int divide is also from the user input).
The main purpose is to count the number of times the sequence, 101 is found in the divided subarray. It works well, except for the value that is odd. For example, array[length(value: 17)] = {1, 0, 1, 2, 7, 9, 6, 5, 0, 1, 0, 1, 0, 1, 1, 0}, and if the divide value is 5, then the subarrays should be,
{1, 0, 1}, {2, 7, 9}, {6, 5, 0}, {0, 1, 0}, {1, 0, 1}, {1, 0}, and the value for the count should be 3. However, it prints out four.

I initially was misinterpreting "101 is found in the divided subarray" as meaning the subarray would have to actually be 101. the j loop is indeed needed if you want to search the subarray, but you do need a bounds check.
if( array[j] == 1 && array[j+1] == 0 && array[j+2] == 1)
should be
if( j+2 < countto && array[j] == 1 && array[j+1] == 0 && array[j+2] == 1)
(or you can initially decrement countto by 2 and adjust it tto at most length-2).
Original answer:
From your description, it doesn't look like you need the j loop or countto at all; in the i loop, you should just be checking array[countfrom]==1 && array[countfrom+1]==0 && array[countfrom+2]==1 (and also first checking that countfrom + 2 < length so you don't go past the end of your array).
But then your code is assuming you have "subarrays" of length 3; you should check that that is actually true given the input, and give an error message if it is not.

Related

Can I replace my Nested if loop with something more efficient?

I try to figure out how many 1, 2, 3, 4 and 5 there is by using a for loop and if else statement. My question is: is there a more efficient way of writing it?
int A[15] = {1,5,4,1,3,1,3,4,5,2,3,2,5,3,2};
int B[5] = {};
for (int i = 0; i <= 14; i++)
{
if (A[i] == 1)
{
B[0]++;
}
else if (A[i] == 2)
{
B[1]++;
}
else if (A[i] == 3)
{
B[2]++;
}
else if (A[i] == 4)
{
B[3]++;
}
else if (A[i] == 5)
{
B[4]++;
}
}
int[] a = {1, 5, 4,...};
int[] b = new int[5];
for (int n: a) {
assert 1 <= n && n <= 5;
b[n - 1]++;
}
n will be set to every element of a.
Array elements are initialized with 0, 0.0, false, null, that is the default value of the type.
You used square brackets in a C/C++ compatible syntax. Normally the more logical notation above is used: part of the type.
Variable and function names start with a small letter by convention, and names are in camelCase.
int[] studentScores =
Asserts one rarely sees: my bad conscience for the assumption no value is out of range.
Provided that the elements of array A are greater than 0:
#include <stdio.h>
int main()
{
int A[15] = { 1, 5, 4, 1, 3, 1, 3, 4, 5, 2, 3, 2, 5, 3, 2 };
int B[5] = { 0, 0, 0, 0, 0 };
for (int i = 0 ; i < sizeof(A)/sizeof(A[0]) ; i++)
++B[A[i] - 1];
for (int i = 0 ; i < sizeof(B)/sizeof(B[0]) ; i++)
printf("%d ", B[i]);
return 0;
}
This code produces the following output:
3 3 4 2 3

Checking for duplicate numbers in a 2D matrix and containing the data into two variables

I am trying to check 2D matrix array for the correct numbers and extras on each row and then printing them out only once per correct number/extra.
I.e. if 34 is twice in jackpot and once in the matrix row it should only record it once.
Correct numbers are first 7 numbers of jackpot array and the extras are the last 3 numbers.
Can anyone explain why the Row 2's 1 extra is being eliminated from my current output?
I am guessing it is because the correct number 34 is already recorded in previous[] and this is then compared to the extra 34 and thus extra is substracted by 1.
How would one go about fixing this, should I make another array that stores the previous extras or something?
The correct output:
Row 1 has 0 correct and 0 extras!
Row 2. has 1 correct and 1 extras!
Row 3. has 3 correct and 0 extras!
Row 4. had 1 correct and 1 extras!
Row 5. has 1 correct and 0 extras!
My current output:
Row 1. has 0 correct and 0 extras!
Row 2. has 1 correct and 0 extras!
Row 3. has 3 correct and 0 extras!
Row 4. has 1 correct and 1 extras!
Row 5. has 1 correct and 0 extras!
for (int z = 0; z < NUM_PER_ROW; z++)
{
if (previous[z] == jackpot[k] && k <= 6)
{
correct -=1;
break;
}
else if (previous[z] == jackpot[k] && k > 6)
{
extra -=1;
break;
}
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_ROWS 5
#define NUM_PER_ROW 7
#define MAX_NUM 40
int doStuff();
int doStuff()
{
int matrix[MAX_ROWS][NUM_PER_ROW] = {
{ 1, 2, 3, 4, 5, 6, 7},
{30, 38, 6, 34, 4, 39, 30},
{ 9, 37, 32, 27, 9, 39, 17},
{ 8, 26, 6, 31, 28, 29, 16},
{33, 21, 19, 7, 9, 19, 30} };
int jackpot[NUM_PER_ROW + 3] =
{20, 37, 22, 9, 34, 28, 34, 24, 26, 29};
int num = 0, i, j, cnt = 0, temp = 0;
for(i = 0; i < MAX_ROWS; i++)
{
int correct = 0;
int extra = 0;
for(j = 0; j < NUM_PER_ROW; j++)
{
int previous[7] = {0, 0, 0, 0, 0, 0, 0};
for (int k = 0; k < NUM_PER_ROW + 3; k++)
{
if (matrix[i][j] == jackpot[k])
{
for (int z = 0; z < NUM_PER_ROW; z++)
{
if (previous[z] == jackpot[k] && k <= 6)
{
correct -= 1;
break;
}
else if (previous[z] == jackpot[k] && k > 6)
{
extra -=1;
break;
}
}
if (k <= 6)
{
correct += 1;
}
else
{
extra += 1;
}
previous[j] = jackpot[k];
}
}
}
printf("Row %d. has %d correct and %d extras! \n", i + 1, correct, extra);
}
return 0;
}
int main()
{
int num;
srand(time(NULL));
doStuff(num);
return 0;
}
Thank you for your time!
I suggest using an array to mark the duplicates in jackpot[]:
char jp_dupe[NUM_PER_ROW + 3];
for (i = 0; i < NUM_PER_ROW + 3; i++)
{
for (j = 0; j < i && jackpot[i] != jackpot[j]; j++)
;
jp_dupe[i] = (i != j); /* 0 if first occurrence, 1 if a duplicate */
}
Then there is no need for the previous[] array or the z loop, and the k loop can be simplified:
for (int k = 0; k < NUM_PER_ROW + 3; k++)
{
if (!jp_dupe[k] && matrix[i][j] == jackpot[k])
{
if (k < NUM_PER_ROW)
{
correct += 1;
}
else
{
extra += 1;
}
}
}
I took the liberty of replacing the <= 6 test to avoid the magic number. The magic number 3 could also be replaced with a macro.

How do I stop counting duplicates of a particular value after its already counted once in an array in C?

For example I have an array:
arr[9] = {1, 3, 4, 9, 2, 9, 2, 9, 7}
I then sort the array to get
arr[9] = {1, 2, 2, 3, 4, 7, 9, 9, 9}
Then I count duplicates for each value using two for loops. The output I want is:
2 instances of 2
3 instances of 9
Instead, I get:
2 instances of 2
3 instances of 9
2 instances of 9
I know that after the loop goes once, when arr[6], the outer loop counts that there are two more 9 but after that is finished, and loop goes to arr[7], the outer loop still counts there is another 9 which is arr[8]. So my question, how do I stop the code when it has counted duplicates for each number in the array once. Thanks!
Example code:
#define NUM = 9
int main() {
arr[NUM] = {1, 3, 4, 9, 2, 9, 2, 9, 7};
sort_int_array(arr, NUM); //insertion sort function
int i, j, count=1;
for (i=0; i<NUM; i++) {
for (j=i+1;j<NUM; j++) {
if (arr[i] == arr[j]) {
count++;
}
if (arr[i] != arr[j] && count>1) {
printf("%d instances of %d\n", count, arr[i]);
count=1;
}
}
}
}
I found the answer guys, thank you for helping. I just needed to remove the 2nd for loop.
#define NUM = 9
int main() {
arr[NUM] = {1, 3, 4, 9, 2, 9, 2, 9, 7};
sort_int_array(arr, NUM); //insertion sort function
int i, count=1;
for (i=0; i<NUM; i++) {
if (arr[i] == arr[i+1]) {
count++;
}
if (arr[i] != arr[i+1] && count>1) {
printf("%d instances of %d\n", count, arr[i]);
count=1;
}
}
}
I think the problem is you go to the first nine, then it counts the next two. THEN it will go to the duplicate and also compare the duplicate against the other duplicate. I assume what you could do is check if arr[i] is not equal to arr[i - 1] so you don't compare duplicates
Here is a demonstrative program that shows how numbers of occurrences of elements of an array cam be calculated.
#include <stdio.h>
#include <stdlib.h>
int cmp( const void *a, const void *b )
{
int x = *( const int * )a;
int y = *( const int * )b;
return ( y < x ) - ( x < y );
}
int main(void)
{
int arr[] = {1, 3, 4, 9, 2, 9, 2, 9, 7};
const size_t N = sizeof( arr ) / sizeof( *arr );
qsort( arr, N, sizeof( int ), cmp );
for ( size_t i = 0; i != N; )
{
size_t j = i;
size_t count = 1;
while ( ++i != N && arr[i] == arr[j] ) ++count;
printf( "%zu instances of %d\n", count, arr[j] );
}
return 0;
}
The program output is
1 instances of 1
2 instances of 2
1 instances of 3
1 instances of 4
1 instances of 7
3 instances of 9
If you want you may substitute this call of printf
printf( "%zu instances of %d\n", count, arr[j] );
for this one
if ( count != 1 ) printf( "%zu instances of %d\n", count, arr[j] );
In this case the output will be
2 instances of 2
3 instances of 9
EDIT: As for your solution published as an answer to your own question then the code invokes undefined behavior due to accessing memory beyond the array in this expression arr[i+1] when i is equal to NUM - 1
for (i=0; i<NUM; i++) {
if (arr[i] == arr[i+1]) {
^^^^^^^^
count++;
}
if (arr[i] != arr[i+1] && count>1) {
^^^^^^^^
printf("%d instances of %d\n", count, arr[i]);
count=1;
}
}
You don't need to use two for loops for this, it would be inefficient and increases the complexity of the code.
If you are doing this with hand you would
Bring another sheet of paper.
for each number in the array:
if it's the first time you see this number:
Note it down and record it has count of 1
else:
then increment the count by 1
if you only need elements that occurred at least twice, you can filter out elements with count = 1.
As for the code:
// this is called frequency array, which we will use to store the
// number of occurrences (frequency) of a given number.
// The size of the array must be larger than the largest number in the array
int sz = 10 // sz = largest expected element + 1 (this only works for array of integers).
int freq[sz];
memset(freq, 0, sz * sizeof(int)); // reset all values in the array to 0
int arr[9] = {1, 2, 2, 3, 4, 7, 9, 9, 9};
int i;
for (i = 0;i < 9;i++){
cur = arr[i]; // read the current element
freq[cur] += 1; // increment its count by 1
}
for (i = 0;i < sz;i++) {
count = freq[i]; // read the count of the number i
if(count != 0) {
// a count of 0 means that the number didn't occur in the array
// you can also exclude numbers occurring only once by count > 1
printf("%d instances of %d\n", count, i);
}
}
I didn't test this code but this is the concept, you can find more here.
This implementation uses more space than needed, but it has fast access time, if you move to cpp, you can use stl map or unordered_map for more space-efficient solution.

How to check if two arrays have the same set of digits in C?

I want to check if two integer type arrays have the same set of digits. For example, if array 1 is 5 1 2 3 3 4 6 1, and array 2 is 1 2 3 4 5 6, the program returns 1. If any number from either array isn't in the second one, the program returns a 0.
I tried doing something like this, but I can't get it to work:
#include <stdio.h>
int main()
{
int i, j, a[8]={5, 1, 2, 3, 3, 4, 6, 1}, b[6]={1, 2, 3, 4, 5, 6}, x=0;
for(i=0; i<6; i++)
{
for(j=0; j<8; j++)
{
if(a[j]==b[i])
{
x=1;
continue;
}
else
{
x=0;
break;
}
}
}
return x;
}
EDIT:
Thank you Some programmer dude
#include <stdio.h>
void sort(int arr[], int n)
{
int i, j, a;
for (i=0; i<n; i++)
{
for (j=i+1; j<n; j++)
{
if (arr[i]>arr[j])
{
a=arr[i];
arr[i]=arr[j];
arr[j]=a;
}
}
}
}
int main()
{
int i, j, k;
int a[8]={5, 1, 2, 3, 3, 4, 6, 1};
int b[6]={1, 2, 3, 4, 5, 6};
int na=8, nb=6;
for(i=0; i<na; i++) // removing duplicates from a
{
for(j=i+1; j<na; j++)
{
if(a[i]==a[j])
{
for(k=j; k<na; k++)
{
a[k]=a[k+1];
}
na--;
j--;
}
}
}
for(i=0; i<nb; i++) // removing duplicates from b
{
for(j=i+1; j<nb; j++)
{
if(b[i]==b[j])
{
for(k=j; k<nb; k++)
{
b[k]=b[k+1];
}
nb--;
j--;
}
}
}
sort(a, na);
sort(b, nb);
if(na!=nb)
return 0;
for(i=0; i<na; i++)
{
if(a[i]!=b[i])
return 0;
}
return 1;
}
You have several ways you can approach this, you can use two sets of nested loops swapping the order you loop over the two arrays validating each element is found in the other. Two full sets of nested loops are needed as you have a 50/50 chance any single outlier will be contained in either of the arrays. This is the brute-force method and has the potential worst-case number of iterations.
Since an outlier is what drove the need for looping with one arrays as outer and the other inner and then swapping a repeating, e.g. to catch 5, 1, 2, 3, 3, 4, 6, 1 and 1, 2, 3, 4, 5, 6, 7, if you can catch the outlier with another method that requires fewer iterations you can make your algorithm more efficient.
An outlier would be detected in a comparison of the min and max from each array, and to find min and max only requires a single linear traversal of each array. Much better than the worst-case nested loop over all elements.
The min and max check provide a way to shorten your work, but do not eliminate the need to press forward with a second set of nested loops if the result is inconclusive at that point. Why? Consider the following sets, where the min and max are equal, but one element within the range is not included in both arrays, e.g.:
int a[] = { 5, 1, 2, 3, 3, 4, 6, 112 },
b[] = { 1, 2, 3, 4, 5, 6, 7, 112 };
The only way the 7 will be detected is by nested loop with the array containing 7 being the outer loop.
So you could write a short function to test for the common set as:
#include <stdio.h>
#include <limits.h>
int commonset (int *a, int *b, int sza, int szb)
{
int maxa = INT_MIN, maxb = INT_MIN,
mina = INT_MAX, minb = INT_MAX;
for (int i = 0; i < sza; i++) { /* find max/min of elements of a */
if (a[i] > maxa)
maxa = a[i];
if (a[i] < mina)
mina = a[i];
}
for (int i = 0; i < szb; i++) { /* find max/min of elements of b */
if (b[i] > maxb)
maxb = b[i];
if (b[i] < minb)
minb = b[i];
}
if (maxa != maxb || mina != minb) /* validate max & mins equal or return 0 */
return 0;
for (int i = 0; i < sza; i++) { /* compare of each element between arrays */
int found = 0;
for (int j = 0; j < szb; j++)
if (a[i] == b[j]) {
found = 1;
break;
}
if (!found)
return 0;
}
for (int i = 0; i < szb; i++) { /* compare of each element between arrays */
int found = 0;
for (int j = 0; j < sza; j++)
if (a[j] == b[i]) {
found = 1;
break;
}
if (!found)
return 0;
}
return 1;
}
Adding a short example program:
int main (void) {
int a[] = { 5, 1, 2, 3, 3, 4, 6, 1 },
sza = sizeof a / sizeof *a,
b[] = { 1, 2, 3, 4, 5, 6 },
szb = sizeof b / sizeof *b,
result;
result = commonset (a, b, sza, szb);
if (result)
puts ("arrays have common set of numbers");
else
puts ("arrays have no common set of numbers");
return result;
}
Example Use/Output
$ ./bin/arr_commonset
arrays have common set of numbers
$ echo $?
1
With b[] = { 1, 2, 3, 4, 5, 6, 7 }:
$ ./bin/arr_commonset
arrays have no common set of numbers
$ echo $?
0
With a[] = { 5, 1, 2, 3, 3, 4, 6, 112 } and b[] = { 1, 2, 3, 4, 5, 6, 7, 112 }:
$ ./bin/arr_commonset
arrays have no common set of numbers
$ echo $?
0
There are probably even ways to combine the two and shave off a few iterations, and, if you have a guaranteed range for your input sets, you can use a simple frequency array for each and then two simple linear iterations would be needed to increment the element that corresponds to the index for each value in the array, and then a third linear iteration over both frequency arrays comparing that like indexes either both are non-zero or both are zero to confirm the common set -- that is left to you.
Look things over and let me know if you have any further questions.

Finding mode of a sorted array

I was hoping to get some input on how to correctly find the mode of a sorted array in C. Here's what I'm working with. First, my freqDistrib function:
void freqDistrib(int t[], int num) {
int i, j, x;
static int f[SIZE];
printf("\n\n");
printf("Part C:\n");
printf(" %-5s %-16s\n", "score", "frequency");
printf(" %-5s %-16s\n", "-----", "---------");
for (i = 1; i < num; i++) {
x = t[i];
j = i - 1;
while (j >= 0 && x > t[j]) {
t[j + 1] = t[j];
j = j - 1;
}
t[j + 1] = x;
} // sorts input in descending order
for (i = 0; i < num; i++) {
++f[t[i]];
if (t[i] != t[i + 1])
printf(" %3d %7d\n", t[i], f[t[i]]);
} // finds the frequency of each input and prints
}
and my mode function:
void modeScore(int t[], int num) {
int i, j, max, mode;
int f[SIZE];
for (i = 0; i < num; i++) {
f[t[i]]++;
}
mode = 0;
max = 0;
for (j = 0; j < num; j++) {
if (f[j] > max) {
max = f[j];
mode = j;
}
}
printf("\n\n");
printf("Part F:\n");
printf("%3d is mode\n", mode);
}
Output right now:
0 is mode
I realize that I need to compare the current frequency tally to a max, and if it is higher than set it equal to max. I just can't for the life of my figure out why this isn't working. Any input would be appreciated thanks.
As noted in a comment, the principal problem was that you did not initialize f in the function.
Here's working code which shows that was all the change that was necessary:
#include <stdio.h>
enum { SIZE = 100 };
static void modeScore(int t[], int num)
{
int f[SIZE] = { 0 };
for (int i = 0; i < num; i++)
f[t[i]]++;
int mode = 0;
int max = 0;
for (int j = 0; j < num; j++)
{
if (f[j] > max)
{
max = f[j];
mode = j;
}
}
printf("Part F: %3d is mode (count %d)\n", mode, max);
}
int main(void)
{
int data[] =
{
/* random -n 40 0 9 | commalist -b ' ' -l 38 */
7, 8, 3, 8, 5, 9, 5, 8, 9, 6,
8, 0, 1, 8, 2, 0, 3, 4, 3, 3,
3, 0, 2, 7, 5, 4, 6, 5, 9, 0,
1, 9, 1, 7, 8, 0, 5, 4, 0, 8,
};
enum { DATA_SIZE = sizeof(data) / sizeof(data[0]) };
modeScore(data, DATA_SIZE);
return 0;
}
For the given data, the output is:
Part F: 8 is mode (count 7)
(Funny coincidence: the first time I ran it — with slightly different data — the answer came back as Part F: 0 is mode (count 7). This was actually correct; I changed one of the zeros into an eight to produce the current result.)
Note that I would normally design the function to return the modal value, rather than have it do the printing. As it stands, it can't be reused because the printing is not material to most code that wants to determine the mode.
The code also does not check that the values in t fall in the range 0..SIZE-1 (but it should).
The parameter order you use is traditional, but there is at least nominally some advantage to using:
void modeScore(int num, int t[num])
to express explicitly that the array t has num elements in it. The size must precede its use in the array dimentson, though.
Since you say the array is sorted, you don't need to create a temporary array to count the values. Instead, you just need to traverse the input, keeping count of how many identical values you've seen in the current run. At the end of the run, then compare the length of the run to the previous longest run, and update if the new run is longer.
(Actually, we update whenever the current run is longer, so we don't forget to update if the mode is the very last value).
Notice that we no longer need SIZE to bound our values; we can now work with the full range of int if we wish.
#include <stdio.h>
static void modeScore(const int t[], int num)
{
int start = 0;
int mode = t[0];
int score = 0;
for (int i = 1; i < num; ++i) {
if (i - start > score) {
// a longer run than the previous candidate
score = i - start;
mode = t[start];
}
if (t[start] != t[i])
// we've reached a change in value
start = i;
}
printf("Part F: %3d is mode (count %d)\n", mode, score);
}
You didn't provide a main(), so I adapted Jonathan Leffler's:
int main(void)
{
int data[] =
{
/* random -n 40 0 9 | commalist -b ' ' -l 38 */
0, 0, 0, 0, 0, 0, 1, 1, 1, 2,
2, 3, 3, 3, 3, 3, 4, 4, 4, 5,
5, 5, 5, 5, 6, 6, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
};
modeScore(data, sizeof data / sizeof data[0]);
return 0;
}

Resources