Problem
Given a sequence of N integer values(possible values of N: 3, 5, 7, 9, 11 ...). Using at most one conditional operator(or conditional ternary operation), the program must determine whether it is true that every three elements the sequence increases and then decreases(sine sequence). Loops in a program can only be used to enumerate elements of a sequence.
Example
* *
* * * *
* * *
What I think
int compare_num(int num1, int num2)
{
return (int)(((num1 + num2) - sqrt((num1 - num2) * (num1 - num2))) / 2);
}
bool_t is_increasing2(int arr[], int size)
{
int tmin = arr[0];
int res = 0;
for (int i = 0; i < size - 1; i++)
{
tmin = compare_num(arr[i + 1], tmin);
res = tmin ^ arr[i + 1];
}
return res;
}
int main(void)
{
int arr[] = {10, 9, 8, 7, 6, 5};
int arr2[] = {1, 2, 3, 4, 5};
int res = is_increasing2(arr2, N);
if (res == 0)
{
printf("Decreasing\n");
}
else
{
printf("Increasing\n");
}
return 0;
}
I use this code to check, that sequence is increasing or not. But now I need to use it to check, that my sine sequence is sine and I can't use more ternary or if/else operators
There is what I have to real problem
bool_t is_increasingSine2(int arr[], int size){
int tmax = 0;
int res = 0;
for(int i = 0; i < size; i += 3){
for(int j = i; j < i + 2 && j < size - 1; j++){
tmax = compare_num(arr[j], arr[j + 1]);
res = tmax ^ arr[j + 1];
}
//There if res == 0 part of sine is increasing otherwise not, but what to do next???
}
return 0;
}
You do not need any conditional operators for this problem, but we will use one in the printf since it is suggested.
Rephrasing the problem as a requirement that each of the first two elements must be less than the one that follows it and each of the next two must be greater than the one that follows it makes it fairly simple to test:
#include <stdio.h>
#include <stdlib.h>
/* Given array Array with N elements, return true iff each of the first two
elements is less than the one following it, each of the next two is greater
than the one following it, and then repeating in a cycle until the end of
the array.
*/
static _Bool TestCriterion(int Array[], size_t N)
{
/* Iterate through each element of the array except the last (the one
with index N-1), since there is no element following the last element
to compare it to.
*/
for (size_t i = 0; i < N-1; ++i)
{
/* Set phase to 0 for the first two elements, 1 for the next two,
then 0, 1, 0, 1… Note that while "i & 2" has the value 0 or 2,
assigning it to a Boolean produces a value of 0 or 1.
*/
_Bool Phase = i & 2;
/* For phase 0, test whether the element with index i is less than
the element with index i+1, and return false (0) if it is not. For
phase 1, compare element i+1 with element i.
*/
if (! (Array[i+Phase] < Array[i+1-Phase]))
return 0;
}
// All elements passed the test, so return true (1).
return 1;
}
/* Compute the number of elements in an array by dividing the size of the
array by the size of an element.
*/
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int main(void)
{
int Array[] = { 1, 2, 3, 2, 1, 2, 3, 2, 1 };
printf("%s.\n", TestCriterion(Array, NumberOf(Array)) ? "Passes" : "Fails");
}
Related
I came across a problem:
Given an array, find the max count of this array, where count for an element in the array is defined as the no. of elements from this array which can divide this element.
Example: max count from the array [2,2,2,5,6,8,9,9] is 4 as 6 or 8 can be divided by 2,2,2 and by themselves.
My approach is:
Sort the array.
Make a set from this array (in a way such that even this set is sorted in non-descending order).
Take another array in which the array indices are initialized to the no. of times an element appears in the original array. Example: in above example element '2' comes three times, hence index '2-1' in this new array will be initialized to 3, index '9-1' will be initialized to 2 as '9' comes 2 times in this array.
Using two loops I am checking the divisibility of largest (moving largest to smallest) element in the set with smallest (moving smallest to largest) element of the set.
Conditions
1 <= arr[i] <= 10000
1 <= i <= 10000
#include <stdio.h>
#include <stdlib.h>
#include<limits.h>
int cmp(const void *a, const void *b)
{
return (*(int*)a - *(int*)b);
}
void arr_2_set(int *arr, int arr_size,int *set, int *len)
{
int index = 0;
int set_len = 0;
int ele = INT_MIN;
qsort(arr,arr_size,sizeof(int),cmp);
while(index < arr_size)
{
if(ele != arr[index])
{
ele = arr[index];
set[set_len] = ele;
set_len++;
}
index++;
}
*len = set_len;
}
int main(void)
{
int arr[]={2,2,2,5,6,8,9,9}; //array is already sorted in this case
int size = sizeof(arr)/sizeof(arr[0]);
int set[size];
int index = 0;
int set_len = 0;
arr_2_set(arr, size, set, &set_len); //convert array to set - "set_len" is actual length of set
int rev = set_len-1; //this will point to the largest element of set and move towards smaller element
int a[100000] = {[0 ... 99999] = 0}; //new array for keeping the count
while(index<size)
{
a[arr[index] -1]++;
index++;
}
int half;
int max=INT_MIN;
printf("set len =%d\n\n",set_len);
for(;rev>=0;rev--)
{
index = 0;
half = set[rev]/2;
while(set[index] <= half)
{
if(set[rev]%set[index] == 0)
{
a[set[rev] -1] += a[set[index]-1]; //if there are 3 twos, then 3 should be added to count of 8
//printf("index =%d rev =%d set[index] =%d set[rev] =%d count = %d\n",index,rev,set[index],set[rev],a[set[rev] -1]);
}
if(max < a[set[rev]-1])
max = a[set[rev]-1];
index++;
}
}
printf("%d",max);
return 0;
}
Now my question is how can I speed up this program? I was able to pass 9/10 test cases - for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
For creating a set and finding the count - use a single while loop, when the size of array is big then using a single loop will matter a lot.
In the later half section where two nested loops are there - don't go from largest to smallest element. Go from smallest to largest element while checking which largest element with index lower than the current element can divide this element, add the count of that element to the current element's count (using set[i]/2 logic will still hold here). This way you'll avoid a lot of divisions. Example: if set is {2,3,4,8} in this case, lets say your current position is 8 then you go down till largest element smaller than or equal to 8 which can divide 8 and add it's count to current element's (8) count.
for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
That may suggest a more time efficient algorithm is expected.
The posted one, first sorts the array (using qsort) and then copies only the unique values into another array, set.
Given the constraints on the possible values, it may be cheaper to implement a counting sort algorithm.
The last part, which searches the maximum number of dividends, can then be implemented as a sieve, using an additional array.
#include <stdio.h>
enum constraints {
MAX_VALUE = 10000
};
int count_dividends(size_t n, int const *arr)
{
// The actual maximum value in the array will be used as a limit.
int maxv = 0;
int counts[MAX_VALUE + 1] = {0};
for (size_t i = 0; i < n; ++i)
{
if ( counts[arr[i]] == 0 && arr[i] > maxv )
{
maxv = arr[i];
}
++counts[arr[i]];
}
// Now, instead of searching for the dividends of an element, it
// adds the number of factors to each multiple.
// So, say there are two elements of value 3, it adds 2 to all
// the multiples of 3 in the total array.
int totals[MAX_VALUE + 1] = {0};
int count = 0;
// It starts from 2, it will add the numbers of 1's once, at the end.
for (int i = 2; i <= maxv; ++i)
{
// It always skips the values that weren't in the original array.
if ( counts[i] != 0 )
{
for ( int j = 2 * i; j <= maxv; j += i)
{
if ( counts[j] != 0 )
totals[j] += counts[i];
}
if ( counts[i] + totals[i] > count )
{
count = counts[i] + totals[i];
}
}
}
return count + counts[1];
}
int main(void)
{
{
int a[] = {2, 4, 5, 1, 1, 6, 14, 8, 2, 12, 1, 13, 10, 2, 8, 5, 9, 1};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 10, because of 1 1 1 1 2 2 2 4 8 8
printf("%d\n", count_dividends(n, a));
}
{
int a[] = {2, 4, 5, 2, 7, 10, 9, 8, 2, 4, 4, 6, 5, 8, 4, 7, 6};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 9, because of 2 2 2 4 4 4 4 8 8
printf("%d\n", count_dividends(n, a));
}
}
I'm trying to jump from an element to another element with a specified number for jumping and how many times it jumps, for example, k=4, and if it reaches the end it goes back from where it started. For example, as in the code, the array for a[Max] will be like {1,4,7,1}
#define Max 100
int main() {
int i=0,n,k,counter,j=0;
char v[Max]={1,2,3,4,5,6,7,8};
int a[Max];
k=4;
counter=k+1;
int size=strlen(v);
while(counter!=0) {
for(i=0;i<size;i=i+k-1){
a[j]=(int)v[i];
j++;
counter--;
}
}
}
You shouldn't be using a string or strlen() for this. Use an int array and you can get the size of your int array by using sizeof. Here, sizeof(v) will tell you the number of bytes allocated for your array, which in this case is 36 (Assuming ints are 4 bytes). Then you can divide by the number of bytes of an integer with sizeof(int) to get the number of elements in your array, 9.
You're segfaulting because you're writing outside the bounds of your array. You don't need that outer loop and should remove it entirely.
To get the wrapping around of your array, use the modulus operation (%) with the size of your array. Understanding The Modulus Operator %
#include <stdio.h>
#define MAX 100
int main() {
int i = 0, ii = 0, k = 4, counter = k - 1, j = 0;
int v[]= {1, 2, 3, 4, 5, 6, 7, 8, 9};
int a[MAX];
int size = sizeof(v) / sizeof(int);
for (i=0; counter >= 0; i += k - 1) {
a[ii++] = v[j];
counter--;
j = (j += 3) % size;
}
for (int i = 0; i < k; i++) {
printf("%d\n", a[i]);
}
}
Output:
1
4
7
1
I'm in a beginner programming course and our assignment is make a program of a game that starts with 10 people. You start with the first person and count people till 3, then drop that person. You keep doing this until there is only one person left.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, i = 0;
int * ptrN = &n[i];
for( i = 0; n[i]; n[i+3]){
if (n[i+3] = 1){
*ptrN = 0;
}
else if (n[i] = 0)
continue;
else
printf("Wrong");
}
printf("The value of n0 %d\tn1 %d\tn2 %d\tn3 %d\tn4 %d\tn5 %d\tn6 %d\tn7 %d\tn8 %d\tn9 %d", n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9]);
return 0;
}
I'm far off from my answer right now but I'm already encountering problems. When I run the above code, it will only change the value of n[0] and then will exit program. Would appreciate any guidance. Thank you
As mentioned in the comments:
Use == to compare, = is for assignment.
You don't need to use a pointer. You can use n[i]
You need to increment i.
You need to skip over the 0's.
As you mentioned, you also need to stop when there is only one 1 left.
There are more than one way to solve that but you could do it by having a counter for how many 1's there are and have a while-loop that ends when the counter is down to 1:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, count = 10;
/* `i` needs to start at -1 so that we start counting:
* "0, 1, 2. n[2] is out!"
* instead of counting:
* "1, 2, 3. n[3] is out!"
*/
int i = -1;
while (count > 1) {
/* We need to count three of those persons that are not out.
* That means we have to search for the next person that is not
* out (by skipping over `0`) and repeat that three times.
*
* If we just increase `i` by 3 ( `(i + 3) % 10` ) then we are
* not checking how many of those persons between `n[i]` and
* `n[(i + 3) % 10]` needed to be skipped over.
*
* So repeat three times:
*/
for (int j = 0; j < 3; j++) {
/* This will search for the next person that is not out by
* increasing `i` by one until `n[i]` is not `0`:
*/
do {
i = (i + 1) % 10;
} while (n[i] == 0); // Check next person if this one is out.
} // I forgot to close this bracket in my first version of the answer
n[i] = 0;
count--;
}
printf("The value of n0 %d\tn1 %d\tn2 %d\tn3 %d\tn4 %d\tn5 %d\tn6 %d\tn7 %d\tn8 %d\tn9 %d", n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9]);
return 0;
}
I'm trying to write a recursive function that gets an array by pointer and its size, and returns the length of the longest series of identical adjacent numbers in the array (assume that there is a series),
For example:
array: {1 2 3 3 4 5 6 6 6 6 7 8}
returns-->: 4
but I don't know what's wrong with my function; I think I got it all wrong.
Any ideas on how to fix it?
#include <stdio.h>
#include <stdlib.h>
int LongestSeries(int* arr, int size, int* count, int* maxcount);
int main()
{
int i, size, *arr, count=0, maxcount=0;
// allocation an array (unknow size)
{
printf("Enter Size of the Array-->:");
scanf("%d", &size);
arr = (int*)malloc(size * sizeof(int));
if (arr == NULL)
{
printf("Error!!");
exit(1);
}
printf("Enter Numbers for the Array:\n");
for (i = 0; i < size; i++)
{
printf("Enter a Number-->:");
scanf("%d", &arr[i]);
}
}
for (i = 0; i < size; i++)
printf(" %d ", arr[i]);
printf("\n");
printf(" %d \n", LongestSeries(arr, size, count, maxcount));
free(arr);
return 0;
}
int LongestSeries(int* arr, int size, int* count, int* maxcount)
{
if (arr[size-1] == arr[size-2])
count++;
if (maxcount<count)
maxcount = count;
LongestSeries(arr, size - 1, count, maxcount);
if (*arr==arr[0])
return maxcount;
}
There're some problems in your code:
1 - The function LongestSeries expects a pointer on count and maxcount arguments but you passed the variable's values instead. You need to change the function call to send the address reference, like this: printf(" %d \n", LongestSeries(arr, size, &count, &maxcount));
2 - Your recursion termination condition is placed below the recursion call, causing the recursion never ending. You need to place it above the recursion call, preferably be the first statement in your recursive function.
3 - Since your count and maxcount arguments are pointers, you must use the dereference operator to work with the values instead its addresses:
from this:
if (arr[size-1] == arr[size-2])
count++;
if (maxcount<count)
maxcount = count;
to this:
if (arr[size-1] == arr[size-2])
++*count;
if (*maxcount < *count)
*maxcount = *count;
4 - The same applies in your return statement: you're returing the pointer, but your function expects an int to be returned, so:
from this:
if (*arr==arr[0])
return maxcount;
to this:
if (*arr==arr[0])
return *maxcount;
5 - Since you need the longest series, your count variable needs to start at 1, not 0, since the lowest possible series in a number sequence is 1, and not 0.
Hope it helps.
There are many problems with the posted code, as pointed out by #MarcLaurent. But fundamentally, the approach seems flawed. The point of writing recursive functions is not to make things difficult, but to make things simple. Problems that lend themselves to recursion can be broken down into smaller subproblems.
For the problem at hand, finding the length of the longest sequence of repeated numbers in an array, one recursive approach would acknowledge that this length is either the length of the initial sequence of repeated numbers, or the length of the longest sequence of repeated numbers in the remainder of the array. In code, this might look like:
size_t longest_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
size_t count = init_seq(sz, a);
return MAX(count, longest_seq(sz - count, a + count));
}
Here, if the array contains no elements (the base case), 0 is returned. Otherwise, the larger of the length of the initial sequence, or the longest sequence in the remainder of the array is returned. MAX is a macro here, easily defined, and we have only to write a function that finds the length of the initial sequence. This can also be recursive, though it need not be.
A recursive function that finds the length of the initial sequence could look like:
size_t init_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
return 1 + ((sz > 1 && a[0] == a[1]) ? init_seq(sz - 1, a + 1) : 0);
}
Here, if the array contains no elements (the base case), then the length is obviously 0, otherwise the return value is 1 added to the length of the initial sequence of the remainder of the array (if there is a next element, and that element is the same as the first element), or 0.
By breaking the problem down in this way, the solution is simple and easy to understand. Here is a full program implementing the above ideas:
#include <stdio.h>
#define MAX(X, Y) (X) > (Y) ? (X) : (Y)
size_t longest_seq(size_t, int *);
size_t init_seq(size_t, int *);
int main(void)
{
size_t arr_sz;
printf("Enter number of elements: ");
scanf("%zu", &arr_sz);
int arr[arr_sz];
printf("Enter array values:\n");
for (size_t i = 0; i < arr_sz; i++) {
scanf("%d", &arr[i]);
}
printf("Longest sequence of repeats: %zu\n", longest_seq(arr_sz, arr));
return 0;
}
size_t longest_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
size_t count = init_seq(sz, a);
return MAX(count, longest_seq(sz - count, a + count));
}
size_t init_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
return 1 + ((sz > 1 && a[0] == a[1]) ? init_seq(sz - 1, a + 1) : 0);
}
Sample program interaction:
Enter number of elements: 12
Enter array values:
1 2 3 3 4 5 6 6 6 6 7 8
Longest sequence of repeats: 4
int LongestSeries(int* arr, int size, int count, int maxcount){
if(size == 0)
return maxcount < count ? count : maxcount;
if(count == 0){
return LongestSeries(arr + 1, size - 1, 1, maxcount);
} else {
if(arr[-1] == *arr){
return LongestSeries(arr + 1, size - 1, count + 1, maxcount);
} else {
if(count > maxcount)
maxcount = count;
return LongestSeries(arr + 1, size - 1, 1, maxcount);
}
}
}
int main(void){
int arr[] = {1, 2, 3, 3, 4, 5, 6, 6, 6, 6, 7, 8};
int size = sizeof(arr)/sizeof(*arr);
printf("%d\n", LongestSeries(arr, size, 0, 0));
}
reduce code:
int LongestSeries(int* arr, int size, int count, int maxcount){
if(size == 0)
return maxcount < count ? count : maxcount;
if(count == 0 || arr[-1] != *arr){
if(count > maxcount)
maxcount = count;
return LongestSeries(arr + 1, size - 1, 1, maxcount);
}
return LongestSeries(arr + 1, size - 1, count + 1, maxcount);
}
How would you write something that selects all possible combinations of triples from an array {1, 2, 3, ..., N-1, N} without duplicates? This is from a recently-held programming competition. N is a multiple of 3.
Example using array {1,2,3,4,5,6}:
C_1 = { {1,2,3}, {4,5,6} }
C_2 = { {1,2,4}, {3,5,6} }
C_3 = { {1,2,5}, {3,4,6} }
are all valid, but
C_bad1 = { {1,2,3}, {3, 4, 5} }
C_bad2 = { {1,2,4}, {3, 5, 6}, {1, 2, 5} }
are not.
you have (N!) / ( ((3!)^(N/3)) * ((N/3)!)) position (prove) . you can just use recursive algorithm for provide all possible combinations of triples from an array {1, 2, 3, ..., N-1, N} without duplicates.
but for produce one of them you can use any idea such as user1952500 idea(though This algorithm also generates (N/3)! position duplicate) or every, for example you invariant last-(N-6)-member and put your solution for first-6-member in start of your result.(this algorithm do not generate duplicate position)
recursive solution:
void combtriples(int begin)
{
for(int i=1;i<=(n/3);i++)
for(int j=1;j<=(n/3);j++)
for(int k=1;k<=(n/3);k++)
{
if ((mark[i]<3) && (mark[j]<3) && (mark[k]<3))
{
count-position++;
c[count][3]=begin;
c[count][4]=begin+1;
c[count][5]=begin+2;
mark[i]++;
mark[j]++;
mark[k]++;
count-member-flase=count-member-flase+3;
if (count-member-flase > 0)
{
combtriples(begin+3);
}
}
}
}
int main()
{
int mark[];
int c[][];
count-position=0;
count-member-flase=0;
combtriples(1);
return 0;
}
Since N is a multiple of 3 we can solve it using a trick:
Generate all permutations of the numbers in ascending order
For each permutation,
partition the numbers into sets of 3 directly (0-2, 3-6,..., N-2..N)
That should give you your result without much fancy work.
EDIT: I was waiting for someone to spot the issue with the above and it was indeed spotted. The way to fix repetitions is to have an additional step:
Step 3: If any triple is lexicographically unsorted form discard the set. Else continue.
#include <stdio.h>
#define SEL_NUM 3
#define LIST_SIZE 6
void printset(int *list, int *map, int size);
void select(int *list, int *map, int n, int size, int start);
int main(int argc, const char **argv) {
int list[LIST_SIZE] = {1, 2, 3, 4, 5, 6};
int map[LIST_SIZE] = {0};
select(list, map, SEL_NUM, LIST_SIZE, 0);
return 0;
}
void select(int *list, int *map, int n, int size, int start) {
if (n == 0) {
printset(list, map, size);
return;
}
for (int i = start; i < size; i++) {
map[i] = 1;
select(list, map, n - 1, size, i + 1);
map[i] = 0;
}
}
void printset(int *list, int *map, int size) {
int list1[SEL_NUM], list2[SEL_NUM], list1cnt = 0, list2cnt = 0;
for (int i = 0; i < size; i++)
if (map[i])
list1[list1cnt++] = list[i];
else
list2[list2cnt++] = list[i];
for (int i = 0; i < list1cnt; i++)
printf(" %d ", list1[i]);
printf(" -- ");
for (int i = 0; i < list2cnt; i++)
printf(" %d ", list2[i]);
printf("\n");
}
Let's consider how many such distinct triplet-sets exist for N. First define T = floor(N/3) as the number of triplets in each set supported by N elements. Then note that since duplicate triplets are not desired, the triplets in each triplet set can be sorted ascending by first element without loss of generality. Then the total number of triplet-sets for N is:
product as t: 0 -> T-1 of ( (N - 3*t - 1) * (N - 3*t - 2) / 2 )
From this formula it is straightforward to see how to build the (brute-force) algorithm to generate the triplets.
Update: The above works only for N % 3 == 0. I am working on a generalization now. Forced; see comment by OP
Cases:
N<3 yields 0
N=3 yields 1
N=6 yields (5 * 4 / 2) * (2 * 1 / 2) = 10
N=9 yields (8 * 7 / 2) * (5 * 4 / 2) * (2 * 1 / 2) = 28 * 10 = 280
As you are in a programming competition, I assume you dont need any code.
Update #2:
Note that to automatically eliminate duplicates, the first element of each triplet must be forced to the lowest numbered unselected element .