Use binary search to find interleaving sequence in C - c

I have two arrays, A and X, where A >= X. I want to find the max interleaving factor i for X^i such that X^i is a subsequence of A. For example, if A = [4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1], and X = [1,2,3], then i = 1, because X^1 = [1,2,3] and that sequence is in A. My program should use a binary search to find this max interleaving factor i and trace whether or not each iteration is a sequence of A. So using binary search for the above example, i would start = 3 (as max possible for A/X = 6), and X^3 = [1,1,1,2,2,2,3,3,3] and that is not a sequence in A.
Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
void create_initial_arrays(int size_a, int *A, int size_x, int *X);
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i);
int main(){
int size_a, size_x;
scanf("%d", &size_a);
scanf("%d", &size_x);
int max_i = size_a / size_x;
int min_i = 0;
printf("Max: %d\n", max_i);
int *A = (int*) malloc(size_a *sizeof(int));
int *X = (int*) malloc(size_x *sizeof(int));
create_initial_arrays(size_a, A, size_x, X);
printf("Old X: ");
for(int i = 0; i < size_x; i++){
printf("%d ", X[i]);
}
printf("\n");
binary_search(size_a, A, size_x, X, max_i, min_i); //practice reallocating size of array
//for(int i = 0; i < size_x; i++){
// printf("%d ", A[i]);
//}
}
void create_initial_arrays(int size_a, int *A, int size_x, int *X){
int i, throwaway;
for(i = 0; i < size_a; i++){
scanf("%d", &A[i]);
}
scanf("%d", &throwaway);
for(i = 0; i < size_x; i++){
scanf("%d", &X[i]);
}
scanf("%d", &throwaway);
}
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i){
int i, j, k, count = 0, max_repeat = 0;
while(min_i <= max_i){
int repeats = (max_i + min_i)/2;
printf("\n");
int * temp = realloc(X, size_x * sizeof(int) * repeats);
X = temp;
for(k = 0; k < size_x; ++k){
int idx = size_x - k -1;
temp = &X[idx];
for(j = 0; j < repeats; ++j){
X[idx * repeats + j] = *temp;
}
}
printf("New X: ");
for(i = 0; i < size_x * repeats; i++){
printf("%d ", X[i]);
}
for(i = 0; i < size_x * repeats; i++){
for(j = 0; j < size_a; j++){
if(A[j] == X[i]){
count++;
i++;
}
}
}
if (count == size_x * repeats){
printf("Low: %d Mid %d High % d Passes\n", min_i, repeats, max_i);
min_i = repeats + 1;
max_repeat++;
}
else
printf("Low: %d Mid %d High % d Fails\n", min_i, repeats, max_i);
max_i = repeats - 1;
}
printf("Max repeat: %d", max_repeat);
}
Here is my current output:
New X: 1 1 1 2 2 2 3 3 3 Low: 0 Mid 3 High 6 Fails
New X: 1 1 1 Low: 0 Mid 1 High 2 Fails
New X: Low: 0 Mid 0 High 0 Fails
I am expecting this:
New X: 1 1 1 2 2 2 3 3 3 Low: 0 Mid 3 High 6 Fails
New X: 1 2 3 Low: 0 Mid 1 High 2 Passes
New X: Low: 2 Mid 2 High 2 Fails
Max i = 1.
Meaning, that my code is not creating the correct array on the second iteration. X^1 should equal [1,2,3] not [1,1,1]. Why is it not creating the array properly on the second iteration but it does on the first?

Why is it not creating the array properly on the second iteration but it does on the first?
In the first loop you take X which is {1, 2, 3} and change it into {1, 1, 1, 2, 2, 2, 3, 3, 3} by repeating the first number 3 times, repeating the second number 3 times and repeating the third number 3 times.
In the second loop you start with X being {1, 1, 1, 2, 2, 2, 3, 3, 3}. Now you construct a new X by repeating the first number 1 time, repeating the second number 1 time and repeating the third number 1 time.
As the first, the second and the third numbers are all 1 you end up with {1, 1, 1}
In other words: Your first loop changed X and therefore you second loop use another value for X than the first loop. Consequently, the second loop produce an unexpected value for X

Related

Array size changed after sorting

I'm currently working on an assignment which tells me to get the largest count number on a sequence in a array (ex: arr[] = {1,2,3,4,5}, valid sequence is {1,2},{2,3},{5}, or {2,3,4,5}. I've used an algorithm that finds the largest value of an array without sorting it, but, the online judge considers it wrong because it ran for too long (Time Limit Error). So I've changed my code to use a sorting algorithm.
I'm trying to find the largest value in an array by sorting it first, then printing the last value (biggest) of the array, which worked if I input this:
Input:
1 // cases
3 2
2 2 2
Output:
SIZE of Array is: 3
UNSORTED countArr:
0. 1
1. 1
2. 1
(after sorting) SORTED countArr:
0. 1
1. 1
2. 1
However, if I try to have to input multiple "cases" I would get:
Input:
2 // cases
4 11
2 9 1 1
3 2
2 2 2
Output:
SIZE of Array is: 4
UNSORTED countArr:
0. 2
1. 3
2. 2
3. 1
(after sorting) SORTED countArr:
0. 1
1. 2
2. 2
3. 3
SIZE of Array is: 4 //why did the array size become 4, instead of 3
UNSORTED countArr:
0. 1
1. 1
2. 1
3. 3 // and what is this 3 doing here? it should have ended at number 2.
(after sorting) SORTED countArr:
0. 1
1. 1
2. 1
3. 3 // same as above
If anyone could help, could you tell me where I'm wrong?
Source code:
#include <stdio.h>
// all function is for quicksort
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
int partition (int arr [], int low, int high) {
int pivot = arr [high];
int i = (low - 1);
for (int j = low; j <= high- 1; j++) {
if (arr [j] < pivot) {
i++;
swap (&arr [i], &arr [j]);
}
}
swap (&arr [i + 1], &arr [high]);
return (i + 1);
}
void quickSort (int arr[], int low, int high) {
if (low < high) {
int pi = partition (arr, low, high);
quickSort (arr, low, pi - 1);
quickSort (arr, pi + 1, high);
}
}
int main () {
int cases, numofElement;
int limit, set [5001], sum = 0, count = 0, countArr [100001], size = 0, largest;
int i, j, k, l, m;
scanf ("%d", &cases);
for (i = 0; i < cases; i++) {
scanf ("%d %d", &numofElement, &limit);
for (j = 0; j < numofElement; j++) {
scanf ("%d", &set [j]);
}
// so the program knows if the array 'set []' is reaching its last digit
set [numofElement] = -2;
for (k = 0; k < numofElement; k++) {
if (set [k] > limit) {
// to skip over or (if all sequence is invalid) to print "-1"
countArr [k] = -1;
continue;
}
for (l = k; l < numofElement; l++) {
sum += set [l];
count += 1;
if ((sum <= limit) && (sum + set [l + 1] > limit || set [l + 1] == -2)) {
countArr [k] = count;
sum = 0;
count = 0;
break;
}
}
}
// count how many number there are in 'countArr []', so we can find its largest value
size = 0;
l = 0;
while (countArr [l] != 0) {
size += 1;
l++;
}
printf ("SIZE of Array is: %d\n", size);
printf ("UNSORTED countArr:\n");
for (j = 0; j < size; j++) {
printf ("%d. %d\n", j, countArr [j]);
}
// sort the 'temp []' array, and output its largest value
quickSort (countArr, 0, size - 1);
printf ("(after sorting) SORTED countArr:\n");
for (j = 0; j < size; j++) {
printf ("%d. %d\n", j, countArr [j]);
}
}
return 0;
}
Is a simple error, you don't reset the element of countArr array to 0 at the beginning of the first for cycle.
If you fix this your program should work.
After this istruction you need to add the reset to zero :
for (i = 0; i < cases; i++){
... reset to zero countArr
... rest of the programm
}

counter to check if array X is subsequence of A not working (C)

I've tried following this program by hand, but I still can't get it to work.
I have an array A = [4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1] and array X = [1,2,3].
I need to find the max number i for X^i that is a subsequence of A, and do this by binary search.
Since size of A is 20, and size of X is 3, the max possible i = 20/3 = 6. So my search will start at i = 3, which means that X^3 = [1,1,1,2,2,2,3,3,3].
This is not a subsequence of A, so binary search repeats for i = 1, X^1 = [1,2,3].
This is a subsequence of A, meaning it should pass and binary search should try again for i = 2.
However, my condition to see if the iteration passes or not is not working properly.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
void create_initial_arrays(int size_a, int *A, int size_x, int *X);
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i);
int main(){
int size_a, size_x;
scanf("%d", &size_a);
scanf("%d", &size_x);
int max_i = size_a / size_x;
int min_i = 0;
printf("Max: %d\n", max_i);
int *A = (int*) malloc(size_a *sizeof(int));
int *X = (int*) malloc(size_x *sizeof(int));
create_initial_arrays(size_a, A, size_x, X);
printf("Old X: ");
for(int i = 0; i < size_x; i++){
printf("%d ", X[i]);
}
printf("\n");
binary_search(size_a, A, size_x, X, max_i, min_i);
free(X);
free(A);
}
void create_initial_arrays(int size_a, int *A, int size_x, int *X){
int i, throwaway;
for(i = 0; i < size_a; i++){
scanf("%d", &A[i]);
}
scanf("%d", &throwaway);
for(i = 0; i < size_x; i++){
scanf("%d", &X[i]);
}
scanf("%d", &throwaway);
}
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i){
int j, k, max_repeat = 0;
while(min_i <= max_i){
int i = 0, count = 0, repeats = (max_i + min_i)/2;
printf("\n");
int * temp = (int*) malloc(size_x * sizeof(int) * repeats);
for(k = 0; k < size_x; ++k){
for(j = 0; j < repeats; ++j){
temp[k * repeats + j] = X[k];
}
}
printf("New X: ");
for(i = 0; i < size_x * repeats; i++){
printf("%d ", temp[i]);
}
printf("A: ");
for (i = 0; i < size_a; i++){
printf("%d ", A[i]);
}
for(j = 0; j < size_a; j++){
if(A[j] == temp[i]){
count++;
i++;
}
}
printf("Count: %d", count);
if (count >= size_x * repeats){
printf("Low: %d Mid %d High % d Passes\n", min_i, repeats, max_i);
min_i = repeats + 1;
max_repeat++;
}
else{
printf("Low: %d Mid %d High % d Fails\n", min_i, repeats, max_i);
max_i = repeats - 1;
}
free(temp);
}
printf("Max repeat: %d", max_repeat);
}
And this is the section that I think must be problematic:
for(j = 0; j < size_a; j++){
if(A[j] == temp[i]){
count++;
i++;
}
}
I've output both Arrays to make sure they are populated correctly (they are) and the counter after each iteration. Here is my code output:
Old X: 1 2 3
New X: 1 1 1 2 2 2 3 3 3 A: 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 Count: 0Low: 0 Mid 3 High 6 Fails
New X: 1 2 3 A: 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 Count: 0Low: 0 Mid 1 High 2 Fails
New X: A: 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 4 3 2 1 Count: 0Low: 0 Mid 0 High 0 Passes
Max repeat: 1
Notice that count remains 0 throughout. On the first iteration for X^3 = [1,1,1,2,2,2,3,3,3], the condition is true 5 times ([1,1,1,2,2] is a subsequence of A, so count should be 5, but 5 is not >= size_x * repeats(3 * 3), so it fails as expected. Binary search reduces to Low 0 Mid 1 High 2, so i = repeats = 1.
X^1 = [1,2,3] is a subsequence of A, and count should be 5 on this iteration ([1,2,3] plus two extra counts of 3) which is >= size_x * repeats (3*1), so it should pass, and redo the search for i = 2. However, count remains zero and fails.
Why is count not updating? I know I need to keep it in the loop because I need it reset to 0 for each iteration, but I don't really understand why A[j] == temp[i] is not ever passing.

binary search counter not updating

I have two arrays, a fixed Array A and a dynamically updating array X. I am trying to find the max interleaving factor i for X^i, such that X^i is a subsequence of A.
My X and A arrays are populating correctly, as I've tested them on each iteration through the binary search. However, my counter is not.
Here is my code:
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i){
int j, k, max_repeat = 0;
while(min_i <= max_i){
int i = 0, count = 0, repeats = (max_i + min_i)/2;
printf("\n");
int * temp = malloc(size_x * sizeof(int) * repeats);
for(k = 0; k < size_x; ++k){
for(j = 0; j < repeats; ++j){
temp[k * repeats + j] = X[k];
}
}
printf("New X: ");
for(i = 0; i < size_x * repeats; i++){
printf("%d ", temp[i]);
}
printf("A: ");
for (i = 0; i < size_a; i++){
printf("%d ", A[i]);
}
for(j = 0; j < size_a; j++){
if(A[j] == temp[i]){
count++;
i++;
}
}
printf("Count: %d", count);
if (count >= size_x * repeats){
printf("Low: %d Mid %d High % d Passes\n", min_i, repeats, max_i);
min_i = repeats + 1;
max_repeat++;
}
else{
printf("Low: %d Mid %d High % d Fails\n", min_i, repeats, max_i);
max_i = repeats - 1;
}
free(temp);
}
printf("Max repeat: %d", max_repeat);
}
Array A = [4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1] and X = [1,2,3] initially. So X^3 = [1,1,1,2,2,2,3,3,3]. This should fail, because count is not > = size_x * repeats (count should be 5 on this iteration), and it does, but count = 0 throughout each iteration when it should clearly update. What am I missing? I have been staring at this for way to long, so I'm sure it's something simple.
EDIT Expected value:
Low 0 Mid 3 High 6 Fails
Low 0 Mid 1 High 2 Passes
Low 2 Mid 2 High 2 Fails
Actual value:
Low 0 Mid 3 High 6 Fails
Low 0 Mid 1 High 2 Fails
Low 0 Mid 0 High 0 Passes

Interleaving array in C

I posted earlier, but I did not properly format or add my code. Say I have an int array x = [1,2,3]. Given a value i, I want to create an array x^i, such that, if i = 3, array x^i = [1,1,1,2,2,2,3,3,3]. If i = 5, array x^i = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5]. I am dynamically allocating memory for this.
However, my code for i = 3 is creating an array = [1,2,3,1,2,3,1,2,3]. I've tried many different things, and I got something like [1,1,1,1,1,1,1,1,1] or [3,3,3,3,3,3,3,3,3] but never the correct answer.
Here is my code:
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i){
int i, j, k, count = 0, max_repeat = 0;
while(min_i <= max_i){
int repeats = (max_i + min_i)/2;
int * temp = realloc(X, size_x * sizeof(int) * repeats);
X = temp;
for(k = 0; k < size_x; ++k){
int idx = size_x - k -1;
temp = &X[idx];
for(j = 0; j < repeats; ++j){
X[idx * repeats + j] = *temp;
}
}
printf("New X: ");
for(i = 0; i < size_x * repeats; i++){
printf("%d ", X[i]);
}
int count = 0;
for(i = 0; i < size_x * repeats; i++){
for(j = 0; j < size_a; j++){
if(A[j] == X[i]){
count++;
i++;
}
}
}
if (count == size_x * repeats){
printf("Low: %d Mid %d High % d Passes\n", min_i, repeats, max_i);
min_i = repeats + 1;
}
else
printf("Low: %d Mid %d High % d Fails\n", min_i, repeats, max_i);
max_i = repeats - 1;
}
}
the variable repeats represents the value i in x^i.
The output is this:
Old X: 1 2 3
New X: 1 1 1 2 2 2 3 3 3 Low: 0 Mid 3 High 6 Fails
New X: 1 1 1 Low: 0 Mid 1 High 2 Fails
New X: Low: 0 Mid 0 High 0 Fails
The first iteration is correct, however, the second iteration should not be [1,1,1], it should be [1,2,3].
Where am I going wrong?
Here you go:
int misleading_function_names_is_bad_practice(size_t xsize, int x[xsize], size_t i)
{
void * const tmp = realloc(x, xsize * sizeof(*x) * i);
if (tmp == NULL) {
return -__LINE__;
}
x = tmp;
for (size_t k = 0; k < xsize; ++k) {
// index of the last original digit counting down
const size_t idx = xsize - k - 1;
const int tmp = x[idx];
for (size_t l = 0; l < i; ++l) {
// fill from the back
x[idx * i + l] = tmp;
}
}
return 0;
}
Live example available at onlinegdb.

How can I calculate the moving average of the array?

In Question, When an array X of size n and a degree k are input,
Write a program that calculates the k-th moving average of array X.
The kth-order moving average of the array X consisting of primitive data values is the average of the last k elements up to the i-th point of X.
That is, A [i] = (X [i-k + 1] + X [i-k + 2] + ... + X [i]) / k.
If the number of the preceding element (including itself) is smaller than k,
Calculate as an average.
For example, if array X is as follows and k is 3, X = 1 3 2 10 6 8
The third moving average is as follows.
A = 1 2 2 5 6 8 A [1] = (1 + 3) / 2, A [2] = (1 + 3 + 2) / 3
However, the program must have the execution time of O (n), not O (nk).
Round off the decimal point in the average calculation and obtain it as an integer.
For exact rounding, do not use% .f, but round it using the int property.
int main()
{
int i, n1, k;
int *array1;
scanf("%d", &n1);
array1 = (int *)malloc(sizeof(int)*n1);
scanf("%d", &k);
for (i = 0; i < n1; i++)
{
scanf("%d", &array1[i]);
}
double tmp = 0;
for (int i = 0; i < n1; i++)
{
tmp += array1[i];
if (i >= k)
{
tmp -= array1[i - k];
}
if (i >= k - 1)
{
double average = tmp / k;
printf("%2lld ", llrint(average));
}
return 0;
}
The program does not work because the problem is not understood.
I would like to know how to solve it.
add) Thank you for answer but the output required by the problem is as follows.
Input : 9 4 (n = 9, k = 3)
2 7 4 5 6 8 2 8 13
Output : 2 5 4 5 6 6 5 6 8
After Modifying your code
int main()
{
int i, n1, k;
int *array1, *array2;
scanf("%d", &n1);
array1 = (int *)malloc(sizeof(int)*n1);
scanf("%d", &k);
for (i = 0; i < n1; i++)
{
scanf("%d", &array1[i]);
}
double tmp = 0;
for (int i = 0; i < n1; i++)
{
tmp += array1[i];
// now tmp contains exactly k + 1 elements sum
// so subtract elements outside of k sized window(leftmost element)
if(i >= k) {
tmp -= array1[i - k];
}
if(i >= k - 1) {
double average = tmp / k;
printf("%lf\n", average);
}
}
return 0;
}

Resources