I have tried to solve this problem with pointers, but I couldn’t.
The requirement was writing a function in which you see if the array is
sorted increase (return 1)
sorted decrease (return -1)
not sorted at all (return 0)
Here is what I wrote:
int *test(int l,int *T)
{
int i,A[l],sign;
int *t=&A[0];
for (i=0; i<l; i++)
{
if(A[i]>A[i+1]){
t++;
sign =-1;
}
if (A[i]<A[i+1]){
t++;
sign =1;
}
if (A[i]!=A[i+1]){
t++;
sign =0;
}
}
return sign;
}
The compiler is giving
returning ‘int’ from a function with return type ‘int *’ makes pointer from integer without a cast [-Wint-conversion]
61 | return sign;
error: ld returned 1 exit status
A few things to notice,
The 'T' parameter wasn't used, so removed.
The 't' variable wasn't used, so removed.
The function return type shouldn't be a pointer to integer, it should be just an integer, from your requirements.
Your code is testing against an array declared in the function scope, and since it is an automatic variable, it is not initialized and may contain garbage values.
Your code is testing against an out of bounds index when using 'i < len' as the loop condition (ex.: considering that the array length is 3, when i == 2, comparing a[i] with a[i + 1] would access a[3], which is not within array boundaries that goes from index 0 to index 2.
With that in mind, a possible implementation with some tests is provided below, from what I can see from the requirements list, but bear in mind that I made some assumptions, since there was no restriction about them.
#include <assert.h>
#define SORTED_ASC 1
#define SORTED_DES -1
#define UNSORTED 0
int is_sorted(int *arr, int len)
{
int sorted = 0;
// I am assuming that this approach is reasonable, check your requirements.
if (len <= 1)
return UNSORTED;
for (int i = 0; i < len - 1; i++)
{
// Previous iteration detected order as 'descending', but current
// is 'ascending'.
if (sorted == SORTED_DES && arr[i] < arr[i + 1])
return UNSORTED;
// Previous iteration detected order as 'ascending', but current
// is 'descending'.
if (sorted == SORTED_ASC && arr[i] > arr[i + 1])
return UNSORTED;
// I am assuming that arrays with repeated values should remain classified
// as 'unsorted' until a different value appears, check your requirements.
if (arr[i] > arr[i + 1])
sorted = SORTED_DES;
else if (arr[i] < arr[i + 1])
sorted = SORTED_ASC;
}
return sorted;
}
void test_unsorted()
{
int arr[4][3] = {
{ 1, 3, 2 },
{ 2, 1, 3 },
{ 2, 3, 1 },
{ 3, 1, 2 }
};
for (int row = 0 ; row < 4 ; row++)
{
int res = is_sorted(arr[row], 3);
assert(res == UNSORTED);
}
}
void test_sorted_ascending()
{
int arr[] = { 1, 2, 3 };
int res = is_sorted(arr, 3);
assert(res == SORTED_ASC);
}
void test_sorted_descending()
{
int arr[] = { 3, 2, 1 };
int res = is_sorted(arr, 3);
assert(res == SORTED_DES);
}
void test_with_repeated_values()
{
int sorted_asc[] = { 1, 1, 2 };
int sorted_asc_res = is_sorted(sorted_asc, 3);
assert(sorted_asc_res == SORTED_ASC);
int sorted_des[] = { 3, 3, 2 };
int sorted_des_res = is_sorted(sorted_des, 3);
assert(sorted_des_res == SORTED_DES);
int unsorted[] = { 1, 1, 1 };
int unsorted_res = is_sorted(unsorted, 3);
assert(unsorted_res == UNSORTED);
}
int main(void)
{
test_unsorted();
test_sorted_ascending();
test_sorted_descending();
test_with_repeated_values();
}
Related
I understand there are a lot of questions around even recursion here, but I don't know in C wether its my logic or my syntax that's wrong (or presumably both) because from what I know I may need pointers. Especially when I'm using function in C, so I can harldy find any question that I can understand as a freshman in cs undergrads.
So my assignment was to simply create an array with even numbers in range determined in input, if input n = 10, then the array needs to contain [0, 2, 4, 6, 8, 10], if n = 9 then the array would simply be [0, 2, 4, 6, 8]. But I have to do it with recursion and I don't know what's wrong with my code since the output is somewhat weird.
#include <stdio.h>
int even(int x, int arrEven[]) {
if (x == 0) {
arrEven[0] = 0;
return 0;
}
else if (x > 0) {
arrEven[x - 1] = even(x - 2, arrEven) + 1;
return arrEven[x - 1];
}
}
int main(void) {
printf("n = ");
int n;
scanf("%d", &n);
n = (n / 2) + 1;
int arrEven[n];
even(n, arrEven);
for (int i = 0; i < (n - 1); i++) {
printf("%d, ", arrEven[i]);
}
printf("%d", arrEven[n - 1]);
}
When I input 10 the output was
0, 1, -731908444, 2, 781232032, 3
instead of
0, 2, 4, 6, 8, 10
Your recursive function only initializes half the destination array because in arrEven[x - 1] = even(x - 2, arrEven) + 1; you decrement x by 2 instead of incrementing the value by 2. You can fix your code this way:
int even(int x, int arrEven[]) {
if (x == 0) {
arrEven[0] = 0;
return 0;
} else
if (x > 0) {
arrEven[x - 1] = even(x - 1, arrEven) + 2;
return arrEven[x - 1];
}
}
Note however that the above code does not use tail recursion and will require a stack depth proportional to x. Here is an alternative where the recursion only happens just before returning from the function:
void even(int n, int arrEven[]) {
if (n > 0) {
errEven[n - 1] = 2 * (n - 1);
even(n - 1, arrEven);
}
}
The above function should compile to similar executable code as the equivalent iterative version:
void even(int n, int arrEven[]) {
while (n > 0) {
n = n - 1;
errEven[n] = 2 * n;
}
}
You mix the usage of one variable for two purposes.
In your code, n is used as index in the array and as value to be put into the array at the same time.
There are tons of options to do this. One could looke like this:
#include <stdio.h>
void even(int *arrEven, int value, int limit) {
*arrEven = value;
if (value < limit) {
even(arrEven+1, value+2, limit);
}
}
int main (void) {
int limit;
int count;
printf("n = ");
scanf("%d", &limit);
// TODO: Check return value.
if (limit < 0)
{
fprintf(stderr, "Only non-negative limits are allowed.\n");
exit(-1);
}
count = (limit / 2) + 1;
int arrEven[count];
even(arrEven, 0, limit);
for (int i = 0; i < count-1; i++){
printf("%d, ", arrEven[i]);
}
printf("%d\n", arrEven[count-1]);
}
I think what you want is something like this:
int even(int x, int arrEven[])
{
if (x == 0)
return 0;
arrEven[x - 1] = even(x - 1, arrEven);
return arrEven[x - 1] + 2;
}
Here x is purely the array index, and the fact that only even values go into the array is handled by the fact that 2 is added to the value returned by even along with the terminal condition returning 0.
Currently I am trying to practise my c skills on some demo test tasks. I encountered following task and I implemented a solution, which does not pass the test. Can you review my solution and point out what corner cases have I missed alternatively how could I make the solution more efficient? Basically any input is appreciated!
Task:
Write a function:
int solution(int A[], int N);
that, given an array A of N integers, returns the smallest positive
integer (greater than 0) that does not occur in A. For example, given
A = [1, 3, 6, 4, 1, 2], the function should return 5. Given A = [1, 2,
3], the function should return 4. Given A = [−1, −3], the function
should return 1.
Write an efficient algorithm for the following assumptions: N is an
integer within the range [1..100,000]; each element of array A is an
integer within the range [−1,000,000..1,000,000].
My solution:
int solution(int A[], int N) {
int B[N];
unsigned int Bidx=0;
unsigned int i = 0;
int smallest = 1000000;
// ged rid of negative elements and find smallest positive element
for(i=0; i<N; i++)
{
if(A[i]>0)
{
B[Bidx]=A[i];
Bidx++;
if(A[i] < smallest)
smallest = A[i];
}
}
// if no positive elements found, solution is 1
if(Bidx == 0)
return 1;
// iterate through the positive values to find the smallest not present value
int condition = 1;
int candidate = smallest+1;
while(condition)
{
condition = 0;
for(i=0; i < Bidx; i++)
{
if(B[i] == candidate)
{
candidate++;
condition = 1;
}
}
}
return candidate;
}
As your integers are limited to 1e6 then a naive lookup table will be most efficient.
int solution(int A[], int N)
{
char num[1000*1000] = {0,};
while(N--)
{
if(*A > 0) num[*A - 1] = 1;
A++;
}
char *res = memchr(num, 0, 1000*1000);
return res ? 1 + res - num : -1;
}
Instead of char as an element of the array, you can use bits which will reduce the lookup table size 8 times.
Use an array of flags exists. For each positive number n in A, set exists[n] to 1. Then find the first 0 value in exists.
#define MAXNUM 1000000
int solution(int A[], unsigned N) {
int exists[MAXNUM + 1] = {0};
found_positive = 0;
for (int i = 0; i < N; i++) {
if (A[i] > 0) {
found_positive = 1;
exists[i] = 1;
}
}
if (!found_positive) {
return 1;
}
for (int i = 1; i <= MAXNUM; i++) {
if (!exists[i]) {
return i;
}
}
return MAXNUM + 1;
}
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 5 years ago.
Improve this question
i have to build a program that scans "size", then array in the size of "size".
returns 1 if ascending, -1 if descending, and 0 if neither.
so for I've came up with this, and its not working.
int UpOrDown(int *arr,int size)
{
int i,j,flag;
if(arr[0]<arr[1])// ascending or random
{
flag=1;
{
for(i=1;i<size;i++)
if(arr[i]>arr[i+1])
flag=0;
}
if (flag=0) return 0;
else return 1;
}
else //descending or random
{
flag=-1;
if(arr[0]>arr[1])
{
for(i=1;i<size;i++)
if(arr[i]<arr[i+1])
flag=0;
}
if (flag=0) return 0;
else return -1;
}
i'd appreciate some guidance.
Your code has some errors:
Breaking the array bounds
Incorrect use of = instead of ==
and seems over-complicated. Here is my solution.
#include <stdio.h>
int UpOrDown(int *arr, int size)
// return -1 (falling), 0 (unknown), +1 (rising)
{
int rising = 0, falling = 0;
for(int i = 1; i < size; i++) {
if(arr[i] > arr[i-1]) {
rising = 1;
}
else if(arr[i] < arr[i-1]) {
falling = 1;
}
}
return rising - falling;
}
int main(void)
{
int arr1[1] = { 1 };
int arr2[2] = { 1, 2 };
int arr3[2] = { 2, 1 };
int arr4[3] = { 1, 2, 1 };
int arr5[3] = { 2, 1, 2 };
printf("%d\n", UpOrDown(arr1, 1));
printf("%d\n", UpOrDown(arr2, 2));
printf("%d\n", UpOrDown(arr3, 2));
printf("%d\n", UpOrDown(arr4, 3));
printf("%d\n", UpOrDown(arr5, 3));
return 0;
}
Program output:
0
1
-1
0
0
I find some mistake in your program . please try using
if (flag == 0) return 0;
instead of
if (flag=0) return 0;
For starters in the presented function implementation there is absent the closing brace.
In general the value of the parameter size can be equal to 0 or 1. In this case the function has undefined behavior due to the first statement
if(arr[0]<arr[1])
Moreover as the parameter has the type int then the user can supply a negative value. So it is better to declare the parameter as having type size_t.
Also in the loops like this
for(i=1;i<size;i++)
if(arr[i]>arr[i+1])
flag=0;
there is an attempt to access beyond the array when the variable i is equal to size - 1.
In this code snippet that corresponds to the else statement
else //descending or random
{
flag=-1;
if(arr[0]>arr[1])
{
for(i=1;i<size;i++)
if(arr[i]<arr[i+1])
flag=0;
}
if (flag=0) return 0;
else return -1;
}
the function can return -1 even if the array has only two elements that are equal each other.
I can suggest the following function implementation. At least it works.:)
#include <stdio.h>
int UpOrDown(const int a[], size_t n)
{
int ordered = !(n < 2 || a[0] == a[1]);
if (ordered)
{
ordered = a[0] < a[1];
size_t i = 2;
while (i < n && ordered == a[i - 1] < a[i]) i++;
if (i != n)
{
ordered = 0;
}
else
{
ordered = ordered == 0 ? -1 : 1;
}
}
return ordered;
}
int main( void )
{
int a[] = { 1 };
int b[] = { 1, 1 };
int c[] = { 1, 2 };
int d[] = { 2, 1 };
int e[] = { 1, 2, 2 };
printf("a: %d\n", UpOrDown(a, sizeof(a) / sizeof(*a)));
printf("b: %d\n", UpOrDown(b, sizeof(b) / sizeof(*b)));
printf("c: %d\n", UpOrDown(c, sizeof(c) / sizeof(*c)));
printf("d: %d\n", UpOrDown(d, sizeof(d) / sizeof(*d)));
printf("e: %d\n", UpOrDown(e, sizeof(e) / sizeof(*e)));
}
The program output is
a: 0
b: 0
c: 1
d: -1
e: 0
Well, how about you try this( although it is long )
you keep the data of the original array to another temporary array like this:
for(int i=0;i<size;i++)
{
//assuming arr is your array and size is the no. of data//
arr[i]=temp[i]; //here we store each data of the original to a temporary
}
and then ascend the temp array:
//Selection sorting the temp array in ascending
for(int i=0;i<size;i++)
{
for(int j=i+1;j<size;j++ )
{
if(temp[i]<temp[j])
{
swap = temp[i];
temp[i] = temp[j];
temp[j] = swap;
}
}
}
then compare your original array and the ascended temp array, if they are equal, the original array is ascending, if not move to doing the same way with descending(i.e. descend the temp array then then again compare, if they are equal ur original array is descending )
if neither, your array is random
int UpOrDown(int *arr,int size)
{
int i = 0 ; //try to intialize the elements its good habbit also put spaces like i had done .its just good coding guidance
int j = 0 ;
int flag = 0;
if ( arr[0] < arr[1] )// ascending or random
{
for(i = 1 ; i < size ;i++)
{
if(arr[i]>arr[i+1])
flag = 1;
else
{
flag = 0 ;
break ;
}
}
}
else //descending or random
{
for(i=1;i< size;i++)
{
if(arr[i]<arr[i+1])
flag = -1;
else
{
flag = 0 ;
break ;
}
}
}
return flag;
}
i am considering there is no repeated elements in your code
Given two arrays containing integers, figure out whether or not three consecutive integers are present in both arrays.
For example: A = [1, 4, 5, 7, 2] and B = [3, 1, 4, 5, 9] will result in "true" / 1 because [1, 4, 5] is present in both arrays.
My solution to this task is present below, but I feel like there must be a more optimized solution than this.
int consecutiveInts(int *a, int sizeA, int *b, int sizeB){
int i, j;
// Iterate over every integer in array b for every integer in array a.
for (i = 0 ; i < sizeA - 2 ; i++){
for (j = 0 ; j < sizeB - 2 ; j++){
if (a[i] == b[j] && a[i + 1] == b[j + 1] && a[i + 2] == b[j + 2])
return 1;
}
}
return 0;
}
For small arrays, OP approach is OK. For array lengths m,n it has O(m*n) run time.
An alternate makes 2 value arrays, sorts them and then looks for a common element. It has O(m*log2(m) + n*log2(n)) run time. Certainly faster with large arrays than OP's code.
typedef struct {
int i[3];
} int3;
void Init3(int3 *i3, const int *i, size_t n) {
while (n--) {
i3[n].i[0] = i[n];
i3[n].i[1] = i[n + 1];
i3[n].i[2] = i[n + 2];
}
}
int fcmp(const void *a, const void *b) {
return memcmp(a, b, sizeof (int3));
}
bool Pattern3(const int *a, size_t size_a, const int *b, size_t size_b) {
if (size_a < 3 || size_b < 3) return false;
int3 a3[size_a - 2];
Init3(a3, a, size_a - 2);
qsort(a3, size_a - 2, sizeof *a3, fcmp);
int3 b3[size_b - 2];
Init3(b3, b, size_b - 2);
qsort(b3, size_b - 2, sizeof *b3, fcmp);
while (size_a && size_b) {
int cmp = fcmp(&a[size_a - 1], &b[size_b - 1]);
if (cmp == 0) return true;
if (cmp > 0) size_a--;
else size_b--;
}
return false;
}
int main() {
int A[] = { 1, 4, 5, 7, 2 };
int B[] = { 3, 1, 4, 5, 9 };
printf("%d\n", Pattern3(A, sizeof A / sizeof *A, B, sizeof B / sizeof *B));
}
An alternative would use a bsearch() rather than form the 2nd int3 b3[]/qsort().
I think I cannot be wrong by sayin that declaring i and j outside of the loop is useless and not optimized.
Something like :
for (unsigned i = 0; i < sizeA - 2; i++) // i will only exist inside the loop
Would be a little better.
I use unsigned type because it is a habit I have taken when using an iterating variable. I think this is a matter which, if you are interested and not already informed, you could learn from by reading this topic.
Not sure it optimizes running speed, but I notice that in case there are repeated numbers you don't need to check them over and over again.
For example three sequential elements in the first array are all 1. After checking a[i] and seeing it's a mismatch you can skip directly to a[i + 3] without comparing a[i + 1] or a[i + 2] (they are also a mismatch).
The management of this condition, particularly if it's a short sequence of repeats, may not improve running time. You have to measure.
With code changes that do not affect the order of complexity, any candidate improvements need profiling (tests that measure the performance) to verify.
The following is still a O(n*m), yet with reduced coefficient as it can step through b[] faster if a[] has repeated values that also exist in b[]. This speeds the inner b[] loop where the majority of time is consumed.
Look at the a[] pattern for distinct values to so j may be advanced faster.
Example:
#define x 0
bool Pattern3(const int *a, size_t size_a, const int *b, size_t size_b) {
static const unsigned char deltas[2][2][2][2] = { //
// What type of pattern is a[0], a[1], a[2]?
{ { { 1, 1 }, // X Y Z
{ 1, 1 } }, // X Y Y
{ { 1, 2 }, // X Y X
{ x, x } } }, // not possible
{ { { 2, 1 }, // X X Y
{ x, x } }, // not possible
{ { x, x }, // not possible
{ 2, 3 } } } }; // X X X
for (unsigned i = 0; i + 2 < size_a; i++) {
const unsigned char *delta23 = deltas[a[0] == a[1]][a[0] == a[2]][a[1] == a[2]];
for (unsigned j = 0; j + 2 < size_b;) {
if (a[0] != b[j]) {
j++;
} else if (a[0 + 1] != b[j + 1]) {
j += delta23[0];
} else if (a[0 + 2] != b[j + 2]) {
j += delta23[1];
} else {
return true;
}
}
a++;
}
return false;
}
Other minor changes which may help.
In the above, swap a,b when size_a > size_b.
Use const as lesser compilers can optimized on that.
// int consecutiveInts(int *a, int sizeA, int *b, int sizeB){
int consecutiveInts(const int *a, int sizeA, const int *b, int sizeB){
Iterate from 2. Adjust indexing accordingly.
for (i = 2 ; i < sizeA ; i++){
...
try using the following loop
for(int i=0;i<A.length;i++)
{
for(int j=0;j<A.length;j++)
{
if(A[i]==B[j])
{
count=count+1; //It checks how many times equal elements have been found
//ensure to declare and initialize int count=0;
}
}
}
if(count>=3)
System.out.println("true");
I have an array with 5 elements (1024,1025,1026,1027,1028).How can I check these elements are in sequential or not.I could do the same if array has even number of elements.
Loop through the array and ensure the previous member (if it exists) is equal to the current minus 1.
for (int i = 1; i < 5; i++) {
if (arr[i - 1] != arr[i] - 1) {
// It's not sequential.
break;
}
}
Simply iterate through the array:
bool is_sequence(int *arr, int size)
{
int i;
for(i = 0; i < (size - 1); i++)
{
if((arr[i] + 1) != arr[i])
/* array is not sequential */
return false;
}
/* array is sequential */
return true;
}
<...>
if(is_sequence(my_array, 5))
printf("sequential!"
else
printf("not sequential");
You should compare the two neighboring numbers and you have to do the same thing for many times. So, a loop is necessary. An easy programme is as followed.
#include<stdio.h>
int main()
{
int a[5]={1024,1025,1026,1027,1028};
int i,s;
for(i=0;i<4;i=i+1)
{
if(a[i]+1 != a[i+1])
{ s=-1; break; }
else
{ s=0; }
}
if(s=0)
{ printf("sequential."); }
else
{ printf("not sequential."); }
}
I hope that my answer could help you. Thank you.
I would suggest this solution (if by saying sequential you mean just ordered):
#include <stdio.h>
int isArraySequential(int * array, int size) {
int isAscendingFirst;
int isAscendingCurrent;
int isChangeFound = 0;
int i;
// arrays of length 0/1/2 are assumed to be sequential
if (size < 3)
return 1;
for (i=1; i < size; i++) {
// in case there is a change
if (array[i] != array[i-1]) {
isAscendingCurrent = (array[i] > array[i-1]);
// on first change
if (!isChangeFound) {
isChangeFound = 1;
isAscendingFirst = isAscendingCurrent;
}
// on subsequent changes
else {
if (isAscendingFirst != isAscendingCurrent)
return 0;
}
}
}
return 1;
}
int main(){
int array1[4] = {1, 1, 0, -1};
int array2[4] = {2, 2, 2, 2};
int array3[4] = {1, 2, 4, 3};
printf("Is array1 sequential ? %d\n", isArraySequential(array1, 4));
printf("Is array2 sequential ? %d\n", isArraySequential(array2, 4));
printf("Is array3 sequential ? %d\n", isArraySequential(array3, 4));
return 0;
}
because in general sequential array can be in ascending OR descending order and this must be taken into account. Also there are corner cases - arrays of length 0/1/2 are always sequential (i am not sure about length 0).
EDIT: I've fixed code for situation when first array elements are with same values. Now it should work OK.