I would like to loop through two arrays in a semi-zipped fashion, such that for as many entries as possible, the following pattern is observed:
arr1[i] arr2[j]
arr1[i] arr2[j+1]
arr1[i+1] arr2[j+2]
arr1[i+1] arr2[j+3]
....
For example, if len arr1 is 96 and len arr2 is 3, I would like to see
0 0
0 1
1 2
1 0
2 1
2 2
3 0
3 1
4 2
4 0
5 1
5 2
I'm having a little trouble getting the logic exactly right; any help would be greatly appreciated
Pseudocode:
i = 0;
for (x = 0; i < arr1.len; ++x) {
i = x / 2; // integer division
j = x % arr2.len;
// use arr1[i] and arr2[j]
}
Use integer division to repeat a value multiple times before moving on to the next value (e.g. 0 0 1 1 2 2 3 3 ...), where the number of times you want to repeat a value is equal to the denominator.
Use modulo division to repeat a sequence of values indefinitely (e.g. 0 1 2 0 1 2 0 1 2 ...), where the number of items in the sequence is equal to the denominator.
If I have understood you correctly you need a loop like the one shown in the demonstrative program below.
#include <stdio.h>
#define N 10
#define M 3
int main( void )
{
int a[N];
int b[N];
for ( int i = 0; i < N; i++ ) a[i] = i;
for ( int i = 0; i < M; i++ ) b[i] = i;
for (int i = 0, j = 0, k = 1; i < N; i += k ^= 1, j = ( j + 1 ) % M)
{
printf( "%d %d\n", a[i] , b[j] );
}
}
The program output is
0 0
0 1
1 2
1 0
2 1
2 2
3 0
3 1
4 2
4 0
5 1
5 2
6 0
6 1
7 2
7 0
8 1
8 2
9 0
9 1
Related
I need to print all possible series that their sum is equal to N;
for example is n == 4 the output should be:
[1, 1, 1, 1]
[1, 1, 2]
[1, 2, 1]
[1, 3]
[2, 1, 1]
[2, 2]
[3, 1]
[4]
My way of thinking to solve this problem was:
print the series that the number i is not in the series
print the series that the number i is in the series, now need to find the sum of N-i.
my code:
#include <stdio.h>
#include <stdlib.h>
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
printf(" %d ", arr[i]);
}
printf("\n");
}
void printAllHelper(int* a,int size, int sum, int used,int index) {
if (sum == 0) {
a -= used;
printArr(a, used);
}
else if (sum < 0 || index == size)
{
return;
}
else {
for(int i = 1 ; i <= size ; i ++)
{
printAllHelper(a, size, sum, used, index + 1);
if (i <= sum)
{
*a = i;
}
printAllHelper(a+1, size, sum -i, used +1, index + 1);
}
}
}
void printAll(int num) {
int* myArray = (int*)malloc(num * sizeof(int));
printAllHelper(myArray,num,num,0,0);
}
void main() {
printAll(4);
}
my output:
3 1
3 1
3 1
3 1
3 1
3 1
3 1
3 1
3 1
4
1 3
4
2 2
4
3 1
4
4
1 3
1 1 2
1 3
1 2 1
1 3
1 3
1 3
4
1 3
4
2 2
4
3 1
4
4
2 2
2 1 1
2 2
2 2
2 2
2 2
4
1 3
4
2 2
4
3 1
4
4
3 1
3 1
3 1
3 1
3 1
4
1 3
4
2 2
4
3 1
4
4
4
4
Please try to explain to me your way of thinking, and how you approach this kind of problem, I want to be the very best like no one ever was :(.....
Your reasoning is not quite correct, but your code is almost right. The loop in your else part should be
for(int i = 1 ; i <= sum ; i ++) {
*a = i;
printAllHelper(a+1, size, sum-i, used+1, index+1);
}
With this, I get the output
1 1 1 1
1 1 2
1 2 1
1 3
2 1 1
2 2
3 1
4
The idea is basically: "The numbers sum to sum if the first number i is any number from 1 to sum and the rest of the numbers sum to sum - i."
Also, note that your code shows some room for improvement, e.g. the used and index variables seem a bit redundant. And with not adding numbers larger than sum or smaller than 1, the check whether sum < 0 || index == size is not necessary, either. Thus you also do not need the size parameter. Your printAllHelper could be simplified to something like this:
void printAllHelper(int* a, int sum, int index) {
if (sum == 0) {
printArr(a, index);
} else {
for(int i = 1 ; i <= sum ; i++) {
a[index] = i;
printAllHelper(a, sum-i, index+1);
}
}
}
(Note: C is not my native language, if you see more things to improve, please comment.)
I have an array called int arr[10] = {1,2,3,4,5}
From my understanding the rest of the array is filled with 0's.
My questions is if its a fixed array length how can I put the first index behind the last index that is not a 0. For example
I believe the 0 is not shown in real printf but I am including it for illustration purposes
for (int i = 0 ; i < 10 ; i++)
{
print("%i" , arr[i]);
}
The output
1 2 3 4 5 0 0 0 0 0
If i move the first index to the back of the 5 like so
for (int i = -1 ; i < 10 ; i++)
{
arr[i] = arr[i + 1];
print("%i" , arr[i]);
}
Will the output put the 1 behind the 5 or at the back of the whole array?
2 3 4 5 1 0 0 0 0 0
or because there is 0s then
2 3 4 5 0 0 0 0 0 1
If my question is unclear please tell me and I will try explain it.
The output
1 2 3 4 5 0 0 0 0 0
No, the actual output is
1234500000
Your code has undefined behavior. The first iteration of the loop (with i = -1) tries to assign to arr[-1], which does not exist:
arr[i] = arr[i + 1];
Similarly, the last iteration (with i = 9) tries to read from arr[10], which also does not exist.
I'm not sure why you think your code will move the first element back.
From my understanding the rest of the array is filled with 0's
You are right.:)
If i move the first index to the back of the 5 like so
for (int i = -1 ; i < 10 ; i++)
{
arr[i] = arr[i + 1];
print("%i" , arr[i]);
}
then you will get undefined behavior because the indices -1 and 10 are not valid indices.
It seems what you are trying to do is the following
#include <stdio.h>
#include <string.h>
int main(void)
{
enum { N = 10 };
int a[N] = { 1, 2, 3, 4, 5 };
size_t pos = 0;
while ( pos < N && a[pos] != 0 ) ++pos;
if ( pos != N && !( pos < 3 ) )
{
int tmp = a[0];
pos -= 2;
memmove( a, a + 1, pos * sizeof( int ) );
a[pos] = tmp;
}
for ( size_t i = 0; i < N; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
return 0;
}
The program output is
2 3 4 1 5 0 0 0 0 0
Hello a beginner here who needs some of your help. My C program is good and does what it is supposed to do only that it is not supposed to use any kind of if statements. I wrote it that way as I saw it would be easier so that I can then replace the if statements. I have been trying to replace the if statements but am now stuck. What can I use instead of the if statement to still produce the same output.
The program is supposed to generate a sequence of thirty random integers between 0 and 9 and then print out the sequence both forward and backwards. Then print out a count of how many times each number between 0 and 9 appeared in the sequence.
This is the output
Here is a sequence of 30 random numbers between 0 and 9:
3 6 7 5 3 5 6 2 9 1 2 7 0 9 3 6 0 6 2 6 1 8 7 9 2 0 2 3 7 5
Printing them backwards, that's:
5 7 3 2 0 2 9 7 8 1 6 2 6 0 6 3 9 0 7 2 1 9 2 6 5 3 5 7 6 3
There were 3 0's
There were 2 1's
There were 5 2's
There were 4 3's
There were no 4's
There were 3 5's
There were 5 6's
There were 4 7's
There was only 1 8
There were 3 9's
This is my C program
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, array[30]={0}, count=0,check;
srand(time(NULL));
for(i=0;i<30;i++)
array[i]=rand()%10;
for(i=0;i<30;i++)
printf("%d ",array[i]);
printf("\n\n");
for(i=29;i>=0;i--)
printf("%d ",array[i]);
printf("\n\n");
for(i=0;i<30;i++){
check=array[i];
if(array[i]!=-1)
array[i]=-1;
if(check == -1)
continue;
count =1;
for(j=0;j<30;j++){
if((i==j) || (array[j]==-1))
continue;
if(check==array[j]){
count++;
array[j]=-1;
}
}
printf("There were %d %d's\n",count,check);
}
return 0;
}
You'll understand the algorithm from comments:
#include <stdio.h>
#include <stdlib.h>
//time.h is needed for time()
#include <time.h>
int main()
{
int i, array[30] = {0};
srand(time(NULL));
//generate and print 30 random numbers
for(i = 0; i < 30; i++){
array[i] = rand() % 10;
printf("%d ", array[i]);
}
puts("\n\n");
//print these numbers backwards
for(i = 29; i >= 0; i--)
printf("%d ",array[i]);
puts("\n\n");
// print out a count of how many times each number
// between 0 and 9 appeared in the sequence.
int count[10] = {0};
for(i = 0; i < 30; i++)
count[array[i]]++;
//output the count for each number
for(i = 0; i < 10; i++)
printf("There were %d %d's\n",count[i], i);
return 0;
}
Output:
9 2 3 9 8 4 3 8 1 3 6 4 3 2 5 3 2 3 0 1 9 0 3 5 1 3 3 8 2 0
0 2 8 3 3 1 5 3 0 9 1 0 3 2 3 5 2 3 4 6 3 1 8 3 4 8 9 3 2 9
There were 3 0's
There were 3 1's
There were 4 2's
There were 9 3's
There were 2 4's
There were 2 5's
There were 1 6's
There were 0 7's
There were 3 8's
There were 3 9's
The following is a simplification of your original source while removing the if statements. There are implied if statements in several places where a logical expression is used as part of a source code statement.
For instance for(j = 0; j < 30 && match >= 0; j++) has several logical expressions but no if appears in this statement. The logical expressions are j < 30 and match >= 0 and the complete expression of j < 30 && match >= 0.
This example uses a logical expression and the evaluation short circuit behavior of the C compiler (see Short-circuit evaluation in Wikipedia) in the statement array[j] == match && ++count && (array[j] = -1); so that if the logical expression array[j] == match evaluates to false then the rest of the statement will not be executed.
We also depend on the preincrement operator with the ++count to increment count and then take the resulting value to check if it is false (zero) or true (non-zero). Since the variable count is initialized to zero and when incremented will always be non-zero then the next logical expression in the statement is evaluated the (array[j] = -1). We put the assignment statement within parenthesis to enforce the order of evaluation. We want the variable array[j] to be assigned the value of -1 and for the result to then be used in the logical statement. Since this is the last logical expression of the entire logical statement, whether it evaluates to false (zero) or true (non-zero) doesn't matter as what we want is the side effect of assigning the value of -1 to the array element.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i, array[30] = {0};
srand(time(NULL));
for(i = 0; i < 30; i++)
array[i] = rand() % 10;
for(i = 0; i < 30; i++)
printf("%d ", array[i]);
printf("\n\n");
for(i = 29; i >= 0; i--)
printf("%d ",array[i]);
printf("\n\n");
for(i = 0; i < 30; i++){
int j;
int count = 0;
int match = array[i];
for(j = 0; j < 30 && match >= 0; j++){
array[j] == match && ++count && (array[j] = -1);
// replaces the following if as value of count is
// tested after it is incremented so will always be nonzero.
// if (array[j] == match) {
// count++; array[j] = -1;
// }
}
// if this is a valid array element value we are trying to match
// then print the count and the value being matched. printf()
// is a function that returns an int indicating number of character written.
match >= 0 && printf("There were %d %d's\n", count, match);
}
return 0;
}
An example output.
8 2 4 0 8 0 8 1 1 4 6 9 3 9 7 6 3 9 0 1 0 7 1 2 4 0 3 0 2 3
3 2 0 3 0 4 2 1 7 0 1 0 9 3 6 7 9 3 9 6 4 1 1 8 0 8 0 4 2 8
There were 3 8's
There were 3 2's
There were 3 4's
There were 6 0's
There were 4 1's
There were 2 6's
There were 3 9's
There were 4 3's
There were 2 7's
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am having trouble with implementing the sort function on pset3. I have used the GDB and found that my sort function does not sort anything. I am not sure if there is a syntax issue, or if the logic is a bit screwed up.
void sort(int values[], int n)
{
for (int k = 0; k < n; k++)
{
for (int j = 0; j < n; j++)
{
if (values[k] >= values[j])
{
int temp = values[k];
values[k] = values[j];
values[j] = temp;
}
}
}
}
You are close, but your loops are not quite right - change:
for (int k = 0; k < n; k++)
{
for (int j = 0; j < n; j++)
{
to:
for (int k = 0; k < n - 1; k++)
{
for (int j = k + 1; j < n; j++)
{
To understand why you need to make this change, consider that the inner loop (j) need only compare elements above index k with the current element at index k. So the outer loop (k) needs to iterate from 0 to n - 2 (one less than the last element), and for each outer loop iteration the inner loop needs to iterate from k + 1 (first element above k) to n - 1 (the last element).
NOTE: by pure chance it seems that the original code does appear to work correctly, even though it appears at first glance that it shouldn't. I have tested it with various edge cases and even though it performs many redundant swaps, the final result always seems to be sorted (suprisingly though the output is in descending order whereas the fixed code generates results in ascending order, as expected). Credit to Jonathan Leffler for spotting this - see his answer and demo program.
One other minor point -- this test:
if (values[k] >= values[j])
should really just be:
if (values[k] > values[j])
It's not incorrect as it stands (the code will still work), but there is no point in swapping elements that are equal, so it's somewhat inefficient as written.
I took your code and converted into a complete program. It's larger than an MCVE because it has support code for shuffling arrays, and for printing results, as well as a main() that exercises these, of course.
#include <stdio.h>
#include <stdlib.h>
static int rand_int(int n)
{
int limit = RAND_MAX - RAND_MAX % n;
int rnd;
while ((rnd = rand()) >= limit)
;
return rnd % n;
}
static void shuffle(int *array, int n)
{
for (int i = n - 1; i > 0; i--)
{
int j = rand_int(i + 1);
int tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
static void print_array(int n, int a[n])
{
for (int i = 0; i < n; i++)
printf(" %d", a[i]);
putchar('\n');
}
static void sort(int values[], int n)
{
for (int k = 0; k < n; k++)
{
for (int j = 0; j < n; j++)
{
if (values[k] >= values[j])
{
int temp = values[k];
values[k] = values[j];
values[j] = temp;
}
}
}
}
int main(int argc, char **argv)
{
if (argc > 1)
{
long l = strtol(argv[1], 0, 0);
unsigned u = (unsigned)l;
printf("Seed: %u\n", u);
srand(u);
}
int data3[3] = { 3, 1, 2 };
print_array(3, data3);
sort(data3, 3);
print_array(3, data3);
int data5[5] = { 0, 2, 6, 1, 5, };
for (int i = 0; i < 5; i++)
{
shuffle(data5, 5);
print_array(5, data5);
sort(data5, 5);
print_array(5, data5);
}
int data9[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 9; i++)
{
shuffle(data9, 9);
print_array(9, data9);
sort(data9, 9);
print_array(9, data9);
}
return 0;
}
The shuffle code implements a Fisher-Yates shuffle, and is
based on code from an answer by Roland Illig. If invoked without a seed argument, it generates the same output each time.
Code compiled and tested on macOS Sierra 10.12.1 with GCC 6.2.0.
An example output:
Seed: 123456789
3 1 2
3 2 1
6 0 1 5 2
6 5 2 1 0
0 6 1 2 5
6 5 2 1 0
0 1 2 6 5
6 5 2 1 0
5 0 6 1 2
6 5 2 1 0
1 6 5 2 0
6 5 2 1 0
0 4 8 3 7 5 1 6 2
8 7 6 5 4 3 2 1 0
7 4 0 5 6 8 3 2 1
8 7 6 5 4 3 2 1 0
1 2 7 5 0 8 3 6 4
8 7 6 5 4 3 2 1 0
3 8 7 5 2 1 0 6 4
8 7 6 5 4 3 2 1 0
1 4 2 6 3 0 7 5 8
8 7 6 5 4 3 2 1 0
2 3 7 4 8 0 5 6 1
8 7 6 5 4 3 2 1 0
3 4 5 8 6 2 0 7 1
8 7 6 5 4 3 2 1 0
3 6 7 4 8 2 5 1 0
8 7 6 5 4 3 2 1 0
0 8 7 3 4 6 5 1 2
8 7 6 5 4 3 2 1 0
This shows the data being sorted in descending order every time, despite different randomized inputs.
In the hottest part of my program (90% of time according to gprof), I need to sum one array A into another B. Both arrays are 2^n (n is 18..24) sized and holds an integer (for simplicity, actually the element stored is mpz_t or small int array). The rule of summing: for each i in 0..2^n-1, set B[i] = sum (A[j]), where j is bit vector, and j & ~ i == 0 (in other words, k-th bit of any j can't be set to 1 if k-th bit of i is not 1).
My current code (this is a body of innermost loop) does this in the time of 2^(1.5 * n) sums, because I will iterate for each i on (in average) 2^(n/2) elements of A.
int A[1<<n]; // have some data
int B[1<<n]; // empty
for (int i = 0; i < (1<<n); i++ ) {
/* Iterate over subsets */
for (int j = i; ; j=(j-1) & i ) {
B[i] += A[j]; /* it is an `sum`, actually it can be a mpz_add here */
if(j==0) break;
}
}
My I mentioned, that almost any sum is recomputed from the values, summed earlier. I suggest, there can be code, doing the same task in the time of n* 2^n sums.
My first idea is that B[i] = B[i_without_the_most_significant_bit] + A[j_new]; where j_new is only j's having the most_significant bit from i in '1' state. This halves my time, but this is not enough (still hours and days on real problem size):
int A[1<<n];
int B[1<<n];
B[0] = A[0]; // the i==0 will not work with my idea and clz()
for (int i = 1; i < (1<<n); i++ ) {
int msb_of_i = 1<< ((sizeof(int)*8)-__builtin_clz(i)-1);
int i_wo_msb = i & ~ msb;
B[i] = B[i_wo_msb];
/* Iterate over subsets */
for (int j_new = i; ; j_new=(j_new-1) & i ) {
B[i] += A[j_new];
if(j_new==msb) break; // stop, when we will try to unset msb
}
}
Can you suggest better algorithm?
Additional image, list of i and j summed for each i for n=4:
i j`s summed
0 0
1 0 1
2 0 2
3 0 1 2 3
4 0 4
5 0 1 4 5
6 0 2 4 6
7 0 1 2 3 4 5 6 7
8 0 8
9 0 1 8 9
a 0 2 8 a
b 0 1 2 3 8 9 a b
c 0 4 8 c
d 0 1 4 5 8 9 c d
e 0 2 4 6 8 a c e
f 0 1 2 3 4 5 6 7 8 9 a b c d e f
Note the similarity of figures
PS the msb magic is from here: Unset the most significant bit in a word (int32) [C]
Divide and conquer anyone? Now not in-place.
void sums(int *a, int n, int *b) {
if (n <= 0) {
*b = *a;
return;
}
int m = 1 << (n - 1);
sums(a, n - 1, b);
sums(a + m, n - 1, b + m);
for (int i = 0; i < m; i++) {
b[m + i] += b[i];
}
}