I need to create a code that compares two in arrays without sorting them. They have to be the same length and contain the same elements in any order.
every integer in a[] is also in b[]
every integer in b[] is also in a[]
all such common values appear exactly the same
number of times in both a[] and b[]
Examples:
a = {1, 2, 3}, b = {2, 3, 4} return 0
a = {1, 2, 3}; b = {2, 3, 1} return 1
a = {1, 2, 2}; b = {2, 2, 1} return 1
a = {1, 2, 2}; b = {2, 1, 1} return 0
a = {1, 1, 2, 2, 2}; b = {2, 1, 2, 1, 2} return 1
I just don't know what to do for this one...
You will end up with a quadratic algorithm if the arrays are not sorted. You can check array lengths at the beginning of your algorithm and if they are equal, say N, you would do something like this
int result = 1;
for (int j=0;j<N;j++) {
bool found = false;
for (int i=0;i<N && !found;i++) {
if (a[j] == b[i]) found = true;
}
if (!found) return 0;
}
I took sometime away and got it within a minute:D
int same_contents(int a[], int b[], int n){
int maxA=0,maxB=0,counterA=0,counterB=0;
int i,k,j,x;
for(i=0; i<n; ++i)
if (a[i]>maxA)maxA=a[i];
for(i=0; i<n; ++i)
if (b[i]>maxB)maxB=b[i];
if (maxA != maxB) return 0;
for(j=0;j<n;++j){
counterA=0;
counterB=0;
for(k=0;k<n;++k){
if(maxA==b[k])counterA++;
if(maxA==a[k])counterB++;
}
if (counterA != counterB) return 0;
else continue;
}
return 1;
}
You can try this!
#include<stdio.h>
int check_same_array(int a[], int b[],int lenA,int lenB)
{
int result = 0;
bool flag = false;
int i = 0,j=0;
if (lenA != lenB)
return 0;
for (i = 0; i < lenA; i++)
{
flag = false;
for (j = 0; j < lenB; j++)
{
if (a[i] == b[j])
flag = true;
}
if (!flag)
{
result = 0;
break;
}
}
if (flag)
result = 1;
return result;
}
int main()
{
int a[5] = { 2, 2, 3, 3 ,5};
int b[5] = { 3, 3, 2, 2 ,5};
int lenA = sizeof(a) / sizeof(int);
int lenB = sizeof(b) / sizeof(int);
printf("%d\n", check_same_array(a, b, lenA, lenB) && check_same_array(b, a, lenB, lenA));
return 0;
}
check_same_array is used to check if each item in array A is in array B.
So if each item in array A is in array B,and each item in array B is in array A.
the item of the two array is same.
Related
Currently I am trying to solve this task: Two arrays of five integers each are given. Find the lowest number in the first array that is not in the second array.
It seems to me that if the user enters such integers in the first array:
0 1 2 3 4
And the integers of the second array:
0 2 3 4 5
The lowest integer, according to the condition of the task, will be 1, because it is not in the second array.
So here is my code:
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "Rus");
int arr1[5]; //initialize arrays
int arr2[5];
printf("Enter integers\n");
for (int i = 0; i < 5; i++) {
int element;
scanf_s("%d", &element);
arr1[i] = element;
}
printf("Enter integers\n");
for (int i = 0; i < 5; i++) {
int element;
scanf_s("%d", &element);
arr2[i] = element;
}
int min1 = arr1[0];
int min2 = arr2[0];
for (int i = 0; i < 5; i++) { // algorithm for finding the minimum number of an array 1
if (min1 > arr1[i]) {
min1 = arr1[i];
}
if (min2 > arr2[i]) {
min2 = arr2[i];
}
}
}
Well, the code is very clear, but here's how to make this check, if the first array input 0 1 2 3 4 and the second 0 2 3 4 5 then how to remove this zero.
There are some issues ...
We don't care about the min value for arr2--only for arr1
We must scan all arr2 values for a match to the current/candidate value of arr1
There are some special cases we must handle
Normally, if we're just looking for the min value in arr1 (e.g. arr2 is not a factor), we can do [as you've done]:
int min1 = arr1[0];
And, we could start indexing into arr1 from 1 in the for loop.
But, this fails if:
arr1[0] is the min value in arr1 and that value is in arr2
arr1 and arr2 have identical values [even if they are in a different order].
So, we need an extra [boolean] value to denote whether the min1 value is valid. And, we must start indexing in the for loop from 0.
Here is the refactored code. It is annotated:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#define A1MAX 5
#define A2MAX 5
int
main(void)
{
setlocale(LC_ALL, "Rus");
// define arrays
int arr1[A1MAX];
int arr2[A2MAX];
printf("Enter integers\n");
for (int i = 0; i < A1MAX; i++) {
if (scanf("%d", &arr1[i]) != 1) {
printf("missing arr1[%d] -- %s\n",i,strerror(errno));
return 2;
}
}
printf("Enter integers\n");
for (int i = 0; i < A2MAX; i++) {
if (scanf("%d", &arr2[i]) != 1) {
printf("missing arr2[%d] -- %s\n",i,strerror(errno));
return 3;
}
}
int nomin = 1;
int min1 = arr1[0];
// check all values in arr1
for (int i = 0; i < A1MAX; i++) {
// current value we're going to test
int val = arr1[i];
// check value if it's a _new_ minimum or we do _not_ yet have a minimum
if ((val < min1) || nomin) {
// scan all elements of arr2, looking for a match to the current
// arr1 value
int match = 0;
for (int j = 0; j < A2MAX; j++) {
match = (val == arr2[j]);
if (match)
break;
}
// if the current value is _not_ in arr2, we have a new minimum
if (! match) {
min1 = val;
nomin = 0;
}
}
}
if (nomin)
printf("there are no elements in arr1 that are not in arr2\n");
else
printf("the minimum element in arr1 not in arr2 is: %d\n",min1);
return nomin;
}
Things get complicated with code tries to maintain multiple indexes into multiple arrays... Things are simplified if you re-use code and break out functions (that can test user input, too)...
#include <stdio.h>
void fill( int arr[], size_t sz ) { // Get user input (with checking)
printf("Enter integers\n");
for( size_t i = 0; i < sz; i++ )
if( scanf( "%d", &arr[i] ) != 1 ) {
fprintf( stderr, "scanf failure\n" );
exit(1);
}
}
// Search for a value in an array. Return index if found, or size if not found
size_t hunt( int val, int arr[], size_t sz ) {
for( size_t i = 0; i < sz; i++ )
if( val == arr[i] )
return i;
return sz;
}
int main() {
#if 0 // Normal with user entry
int arr1[5], arr2[5];
size_t a1sz = sizeof arr1/sizeof arr1[0];
size_t a2sz = sizeof arr2/sizeof arr2[0];
fill( arr1, a1sz );
fill( arr2, a2sz );
#else // less tedious with compile time init of data
int arr1[] = { 0, 1, 2, 3, 4 };
int arr2[] = { 0, 2, 3, 4, 5 };
size_t a1sz = sizeof arr1/sizeof arr1[0];
size_t a2sz = sizeof arr2/sizeof arr2[0];
#endif
size_t gotOne = 0;
for( size_t i = 0; i < a1sz; i++ ) {
// don't bother testing values if got a candidate and value is larger
if( gotOne && arr1[i] >= arr1[ gotOne ] ) continue;
// following is TRUE when not found...
if( hunt( arr1[i], arr2, a2sz ) == a2sz )
gotOne = i + 1;
}
if( gotOne )
printf( "Smallest in arr1 not in arr2 = %u\n", arr1[ gotOne - 1 ] );
else
puts( "No such value matching criteria" );
return 0;
}
Smallest in arr1 not in arr2 = 1
Algorithm
The naive approach to this, and one that works very well for small datasets, is to nest a couple of loops. This approach grows in time complexity very fast. O(m*n) where m is the length of the first array and n is the length of the second array.
Fortunately, we can approach this in a way that does not involve nested loops. This assumes both arrays contain only unique values. If they have duplicates, removing those duplicates would be a necessary step before the below can be performed.
Let's start with a couple of simple arrays:
int foo[] = {1, 4, 7, 9, 2};
int bar[] = {4, 1, 6, 7, 3};
Let's combine them into another array. This is a linear operation.
{1, 4, 7, 9, 2, 4, 1, 6, 7, 3}
Let's then use qsort to sort them. This operation is typically O(n*log n).
{1, 1, 2, 3, 4, 4, 6, 7, 7, 9}
Now, we can do a linear loop over these and find the unique elements. These are the ones present in one but not both of the arrays.
{2, 3, 6, 9}
But this doesn't tell us which is in the first array. That sounds like a nested loop issue. Instead, though, let's combine that with the first array.
{1, 4, 7, 9, 2, 2, 3, 6, 9}
And we'll sort this.
{1, 2, 2, 3, 4, 6, 7, 9, 9}
Now we'll scan for the first repeated number.
2
An implementation
Note: Does not check for malloc errors.
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
int c = *(const int *)a;
int d = *(const int *)b;
if (c == d) return 0;
else if (c < d) return -1;
else return 1;
}
int min_not_in_2nd_array(int *result, int *arr1, size_t m, int *arr2, size_t n) {
int *temp = malloc(sizeof(int) * (m + n));
//if (!temp) return 0;
for (size_t i = 0; i < m; ++i) temp[i] = arr1[i];
for (size_t i = 0; i < n; ++i) temp[m+i] = arr2[i];
qsort(temp, m+n, sizeof(int), cmp);
int *uniques = malloc(sizeof(int) * (m + n));
//if (!uniques) return 0;
size_t n_uniques = 0;
int cur = temp[0] - 1;
size_t cur_count = 0;
for (size_t i = 0; i < m+n; ++i) {
if (i == m+n-1 && temp[i] != temp[i-1]) {
uniques[n_uniques++] = temp[i];
}
else if (temp[i] != cur) {
if (cur_count == 1) uniques[n_uniques++] = cur;
cur = temp[i];
cur_count = 1;
}
else {
cur_count++;
}
}
//for (size_t i = 0; i < n_uniques; ++i) printf("%d ", uniques[i]);
//printf("\n");
int *temp2 = malloc(sizeof(int) * (m + n_uniques));
// if (!temp2) return 0;
for (size_t i = 0; i < m; ++i) temp2[i] = arr1[i];
for (size_t i = 0; i < n_uniques; ++i) temp2[m+i] = uniques[i];
qsort(temp2, m+n_uniques, sizeof(int), cmp);
int found = 0;
for (size_t i = 0; i < m+n_uniques-1; ++i) {
if (temp2[i] == temp2[i+1]) {
*result = temp2[i];
found = 1;
break;
}
}
free(temp);
free(uniques);
free(temp2);
return found;
}
int main(void) {
int foo[] = {1, 4, 7, 9, 2};
int bar[] = {4, 1, 6, 7, 3};
int baz;
if (min_not_in_2nd_array(&baz, foo, sizeof(foo)/sizeof(*foo),
bar, sizeof(bar)/sizeof(*bar))) {
printf("Min not in 2nd array is %d\n", baz);
}
else {
printf("All elements shared.\n");
}
return 0;
}
I have two arrays.
1,3,5,7,9
{3,5} or {1.9}.
(left to right order)
So the second array is a subset of the first array
But not a subset if the second array is {5.3} or, {9.1}
(right to left order.)
My code is
#include <stdio.h>
void subset(int set11[], int set12[])
{
int length1;
int set1[] = {1, 5, 3, 9, 7, 0, 5};
length1 = sizeof(set1) / sizeof(int);
int length2;
int set2[] = {5, 9};
length2 = sizeof(set2) / sizeof(int);
int i = 0;
int j = 0;
int count = 0;
for (i = 0; i < length1; i++)
{
if (set1[i] == set2[j])
{
count = 1;
}
}
printf(" is \n");
if (count == 1)
{
printf("is subset");
}
else
{
printf("not subset");
}
}
int main()
{
int set11[] = {1, 5, 3, 9, 7};
int set12[] = {5, 9};
subset(set11, set12);
printf("");
return 0;
}
I get output in all cases only not subset.
Applied some changes in logic. refer comments.
#include <stdio.h>
#include <stdbool.h>
void subset(int set11[], int set12[])
{
int length1;
int set1[] = {1,3,5,7,9};
length1 = sizeof(set1) / sizeof(int);
int length2;
int set2[] = {3,5};
length2 = sizeof(set2) / sizeof(int);
int i = 0;
bool isSubset = true; //will indicate weather the second array is subset or not
// int j = 0; //
int startPosition = 0; // will decide the starting position for searching in the main array. {set 2}
// int count = 0; //not needed; we will represent it with bool variable 'isSubset'.
for (i = 0; i < length2; i++) //Iterating through the subset array
{
bool isFound = false;
for (int j=startPosition;j<length1;j++){ //Iterating through the original array {set 1}
if (set2[i]==set1[j]){ //if element from second array is found in first array then...
isFound = true; //found the element
startPosition = j+1; //increasing the starting position for next search in the first array.
printf("\t%d found at %d\n",set2[i],j);
break;
}
}
if(isFound==false){ //if not found then this is not subarray.
printf("\t%d not found\n",set2[i]);
isSubset = false;
break;
}
}
// printf(" is \n");
if (isSubset)
{
printf("subset");
}
else
{
printf("not subset");
}
}
int main()
{
int set11[] = {1, 5, 3, 9, 7};
int set12[] = {5, 9};
subset(set11, set12);
printf("");
return 0;
}
You can run a nested loop to get hold of all the matching elements in the subset array
for (i = 0; i < length1; i++)
{
for(k = 0; k < length2; k++)
{
if (set1[i] == set2[k])
{
count == 1;
}
}
}
Outer loop is for the for the First array
Inner loop to check for the element at any position in the subset/second array
set1[] = {1, 5, 3, 9, 7, 0, 5};
set2[] = {5, 9};
If we run a nested loop we will get all the subsets regardless of their positions in the second array(set2)
it wont matter if the set2 is {5,9} or {9,5} in any case the counter variable will increase.
Question
There are two arrays, one contains a large number of numbers (arr1) that may have a few repeating sequences for example 1,2,4 might repeat multiple times in this array. There is another array (arr2) that will be assigned by the user.
I need a way to search arr1 for the exact input the user gave for arr2. For a match to be valid, all the elements have to be in the exact same order as entered by the user.
For example, if the user enters 1,2,4,3 the program has to find 1,2,4,3 in that exact order in arr1, this means that 1,2,3,4 in arr1 should not be counted as a match. Below is what I have been able to come up with so far, but this returns true even if just the first element of the 2 arrays matches.
for (int i=0; i<size1; i++)
{
for (int j = 0; j<size2; j++)
{
if(arr1[i] == arr2[j])
{
printf("found a match %d", j);
break;
}
else if (arr1[i] != arr2[j])
{
printf("not match");
break;
}
Below is the complete code :-
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = {1, 2, 4, 2, 2, 2, 1, 1, 2, 4, 3, 4, 4, 1, 2, 4, 4, 1, 3, 3};
int size1 = (int) (sizeof(arr1)/sizeof(arr1));
int arr2[] = {1, 2, 4};
int size2 = (int) (sizeof(arr2)/sizeof(arr2[0]));
int match = 0;
for (int i=0; i<size1; i++)
{
for (int j = 0; j < size2; j++) {
if (arr1[i] != arr2[j]) {
match = 1;
break;
}
}
}
if(match == 1){
printf("Not a match");
}else if(match == 0){
printf("The lists match");
}
return 0;
}
if you look at the arr1 and arr2, I need a way to return the index 0,7,13 and also this is still rough since arr2 is technically dynamic since it is assigned by the user and has no fixed size, only arr1 will have a fixed size.
Your question is similar to finding substrings in a string. But characters are replaced with integers.
Here is a program that will find the matches. It has some debug print statements to show how it works.
#include <stdio.h>
int g_Arr2_Changed=0; //----Global boolean if arr2 changes.
int main(int argc, const char *argv[])
{ int arr1[] = {1, 2, 4, 2, 2, 2, 1, 1, 2, 4, 3, 4, 4, 1, 2, 4, 4, 1, 3, 3};
int size1 = (int) (sizeof(arr1)/sizeof(int));
int arr2[] = {1, 2, 4};
int size2 = (int) (sizeof(arr2)/sizeof(int));
int patternStart = -1; //----Start pattern in arr1.
int nPatternMatch = 0; //----Number of ints matched so far.
for (int i=0; i<size1; i++)
{ int checkInt = arr1[i];
//printf("[%i](%i)", i, checkInt);
if (nPatternMatch == 0) //----No integers are matched yet.
{ //printf("<None>");
//----Is checkInt the start of arr2?
if (arr2[nPatternMatch] == checkInt)
{ patternStart=i; nPatternMatch++; //printf("<start>");
}
}
else //----At least one integer has been matched already.
{ //printf("<Some>");
//----Is checkInt a continuation?
if (arr2[nPatternMatch] == checkInt)
{ nPatternMatch++; //----Matched another integer.
//printf("<matched>");
}
else
{ //printf("<NotMatched>");
i = patternStart; //---- for() will add one.
patternStart = - 1;
nPatternMatch = 0; //----Not match. Start at next int.
}
}
//----If match found print and reset for next.
if (nPatternMatch == size2)
{ printf("Pattern found at %i\n", patternStart);
i = patternStart + 1;
patternStart = -1; nPatternMatch = 0;
}
//----Just in case the global variable says arr2 changed.
if (g_Arr2_Changed != 0) //----Start over.
{ //printf("<arr2 changed.>");
i=0; patternStart = -1; nPatternMatch = 0;
size2 = (int) (sizeof(arr2)/sizeof(int));
}
//printf("\n");
}
return 0;
}
This code will return a match for every character that is found in the same position in both lists.
So if you you want to verify the whole list, you should set an int, to identify if there is even one character that doesn't match in both lists.
If you want to show the list that match, you just have to print the whole list inside the second if.
int match = 0;
for (int i=0; i<size1; i++)
{
for (int j = 0; j < size2; j++) {
if (arr1[i] != arr2[j]) {
match = 1;
break;
}
}
if(match == 1){
printf("Not a match");
}else if(match == 0){
printf("The lists match");
printf("First character: %c", arr2[0]);
}
match = 0;
}
Would you please try the following:
#include <stdio.h>
int main()
{
int arr1[] = {1, 2, 4, 2, 2, 2, 1, 1, 2, 4, 3, 4, 4, 1, 2, 4, 4, 1, 3, 3};
int size1 = sizeof arr1 / sizeof arr1[0];
int arr2[] = {1, 2, 4};
int size2 = sizeof arr2 / sizeof arr2[0];
int match;
int i, j;
for (i = 0; i < size1 - size2 + 1; i++) {
match = 0;
for (j = 0; j < size2; j++) {
if (arr1[i + j] != arr2[j]) {
match = 1;
break;
}
}
if (! match) {
printf("matched at %d\n", i);
}
}
return 0;
}
It will output:
matched at 0
matched at 7
matched at 13
If you want to assign an array to the list of the matched indices, it will be easy for you to modify the code.
It might seem like long but I over explained it.
So I have my problem is not necessarily finding the palindromes it is just the finding the length of the palindrome I can't figure out and my code doesn't work for single digit palindromes (yes we count them too) so here is the code and the explanation:
#include <stdio.h>
#define LEN 9
int *lastEqual(int *p, int *q) {
int *rightmost;
int *temp;
int *zero = p;
while (p <= q) {
if (*zero == *(p + 1)) {
temp = p + 1;
if (temp < q) {
rightmost = temp;
}
}
p++;
}
return rightmost;
}
What this funtion does or suppose to do:
*For the given array: {3,6,7,8,7,6,5,3,5} If lastEqual is called by the references of the
bold numbers, it returns a pointer to 3.(The one closest to the end of array)*
*For the given array: {3,6,7,8,7,6,5,3,5} If lastEqual is called by the references of the
bold numbers it returns a pointer to 6.*
Here is the second function:
int isPalindromic(int *p, int *q) {
int *left = p;
int *right = q;
int pali;
while (left < right) {
if (*left == *right) {
pali = 1;
} else {
pali = 0;
}
left++;
right--;
}
return pali;
}
Here is what it does or is supposed to do:
For the given array: {3,6,7,8,7,6,5,3,5} If isPalindromic is called by the references of
the bold numbers it returns 0, since the numbers between those addresses do not
represent a palindrome.
For the given array: {3,6,7,8,7,6,5,3,5} If isPalindromic is called by the references of
the bold numbers it returns 1, since the numbers between those addresses represent
a palindrome.
And here is the main function:
int main() {
int *p, *q, *rightmost;
int arr[LEN] = { 3, 6, 7, 8, 7, 6, 5, 3, 5 };
p = arr;
q = p + (LEN - 1);
for (int i = 0; i < LEN; i++) {
if (isPalindromic(p + i, lastEqual(p + i, q)) == 1) {
rightmost = lastEqual(p + i, q);
printf("Palindrome at index %d, length %ld\n", i, &p - &rightmost);
}
}
return 0;
}
And the output should be like these but I cant figure out how to find lenght and why it doesnt count the single digit number as a palindrome like this 8 :
{3,6,7,8,7,6,5,3,5} so 3 to 3 is not a palindrome 6 to 6 is 7 to 7 is and 8 should be counted as well because there is not a pair of 8
The output Should be like these:
Input Array: {1}
Output: “palindrome at index 0, length: 1”
Input Array: {5, 6, 7, 8, 7, 6, 5, 2, 5}
Output: “palindrome at index 0, length: 7”
Input Array: {2, 7, 6, 11, 10, 11, 6, 5, 3}
Output: “palindrome at index 2, length: 5”
Input Array: {7, 8, 9, 8, 7}
Output: “palindrome at index 0, length: 5”
Input Array: {2, 7, 4, 3, 2, 6, 1, 2, 1}
Output: “palindrome at index 6, length: 3”
Here is a simpler version of isPalindromic with the same arguments, and a much simpler version of main() to find all palindromes:
#include <stdio.h>
int isPalindromic(int *p, int *q) {
while (p < q) {
if (*p++ != *q--)
return 0;
}
return 1;
}
int main() {
int arr[] = { 3, 6, 7, 8, 7, 6, 5, 3, 5 };
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; i++) {
for (int j = i; j < len; j++) {
if (isPalindromic(arr + i, arr + j))
printf("Palindrome at index %d, length %d\n", i, j - i + 1);
}
}
return 0;
}
If you just want to output the longest palindrome, change the main function to this:
int main() {
int arr[] = { 3, 6, 7, 8, 7, 6, 5, 3, 5 };
int len = sizeof(arr) / sizeof(arr[0]);
int max_pos = 0, max_len = 1;
for (int i = 0; i < len; i++) {
for (int j = i + max_len; j < len; j++) {
if (isPalindromic(arr + i, arr + j)) {
max_pos = i;
max_len = j - i + 1;
}
}
}
printf("Longest palindrome at index %d, length %d\n", max_pos, max_len);
return 0;
}
Say I have an array:
int {2, 2, 2, 6, 6, 2, 2, 5, 5, 5}
and I want to delete all the adjacent duplicates so that it becomes
int {2, 6, 2, 5}
How can I do this?
Not sure what you have tried. My idea would be like this.
int i, num[] = {2, 2, 2, 6, 6, 2, 2, 5, 5, 5};
// Prepare new array for the result (result never larger than num[])
int *newNum = malloc(sizeof(num));
int used = 0, last = 0;
// Get number of elements in num[], which is 10 in this example
size_t n = sizeof(num) / sizeof(int);
for (i = 0; i < n; i++)
{
if (num[i] != last)
{
newNum[used++] = num[i];
}
last = num[i];
}
printf("new array: \n");
for (i = 0; i < used; i++)
{
printf("%i ", newNum[i]);
}
like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
int size = 10;
int *array = memcpy(malloc(size * sizeof(*array)), (int[]){2, 2, 2, 6, 6, 2, 2, 5, 5, 5}, size * sizeof(*array));
int i, new_size;
for(i = new_size = 1; i < size; ++i){
if(array[new_size-1] != array[i])
array[new_size++] = array[i];
}
if(size > new_size){
size = new_size;
array = realloc(array, size * sizeof(*array));
}
for(i = 0; i < size; ++i)
printf("%d ", array[i]);//2 6 2 5
free(array);
return 0;
}