Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
The question is.
There is a set An, and it consists of integers from 1 to n.
An={1, 2, 3, ..., n}
Print all subsets of An with given size K. And it must be generated in order like the example below.
So for example, n=5 k=3
{1, 2, 3} {1, 2, 4} {1, 2, 5} {1, 3, 4} {1, 3, 5} {1, 4, 5} {2, 3, 4} ... {3, 4, 5}
I am not sure about if there is other way not using recursion. I did this with recursion but the problem is all test cases should be done within 1 sec.
When N and K are like 5, 3 and 12, 6 it is okay but
When it comes to like 50, 48 or 100, 95, it takes too long.
All problem should be done within 1 second.
I am having real struggle with this problem.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void subset(int n, int k, int arr[], int pos[], int index, int start){
int i, j;
if(index == k){
for(j=0; j<k; j++){
if(j==k-1)
printf("%d\n", pos[j]);
else{
printf("%d ", pos[j]);
}
}
return;
}
for(i=start; i<n; i++){
pos[index] = arr[i];
subset(n, k, arr, pos, index+1, i+1);
}
}
int main(){
int n, k, arr[100], index=0, start=0;
scanf("%d %d", &n, &k);
// 1<=n<=100 ; 1<=k<=n
if(n>100||n<1 && k>n||k<1)
return 0;
int i;
for(i=0; i<n; i++)
arr[i]=i+1;
int *pos = (int*)malloc(sizeof(int)*k);
time_t clockstart=0, clockend=0;
float gap;
clockstart = clock();
subset(n, k, arr, pos, index, start);
clockend = clock();
gap = (float)(clockend-clockstart)/(CLOCKS_PER_SEC);
printf("%f\n", gap);
return 0;
}
I think i should use something like tail recursion or vector in C++.
But I cant figure out with those.
The only way to increase your "speed algorithm" without touching it is to manually bufferise printf.
printf is a function that will do a system call at some time.
Every system call is costly, that's why each function that do some kind of system call usually do "buffering".
For malloc, in reallity, you allocate much more that you think (malloc(1) will not end up by allocating 1 octet but much more under the hood) and when you free the memory, in reallity it's not really released (that way, if you do another malloc, you will not do a system call but reuse the memory freed). Of course, it's OS dependant AND inmplementation dependend (all is under the hood).
You can see some system call under linux by using "strace".
The same thing apply to "printf" : since it will do a system call, there a buffer that retain what you want to print and do the print only time to time.
So when the printf's buffer is really printed ?
We can't know, it's implementation defined (event the man page of printf doesn't say a word about the printf buffering), but usually, it can be at 3 occasion :
when the buffer is full
when you force the flush by using fflush
when you have the '\n' caracter in what you want to print.
Since you do an "\n" at each subnet, printf may have to do the system call every time : it's time consumming.
By using a buffer and print in the buffer instead of stdout, you can speed up your code :
#define BUF_LEN 2048
typedef struct mybuf {
char buffer[BUF_LEN];
size_t len;
} mybuf;
// For convenience, I use global varaible, but it's BAD
mybuf buf = {.buffer = "", .len = 0};
void MyBuf_PrintOnStdout(void)
{
write(1, buf.buffer, buf.len);
buf.len = 0;
}
void MyBuf_Flush(void)
{
MyBuf_PrintOnStdout();
fflush(stdout);
}
void MyBuf_PrintInteger(int integer)
{
int printedLen;
// An 64bit integer take 20digit + 1 char for potential "-"
// So 21 is the max len for an integer.
// Of course, if your int is bigger than 64bit, this if is false.
if (buf.len + 21 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
printedLen = sprintf(buf.buffer + buf.len, "%d", integer);
// Error check (printedLen < 0 == error)
buf.len += printedLen;
}
void MyBuf_PrintCharacter(char character)
{
if (buf.len + 1 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
buf.buffer[buf.len] = character;
++buf.len;
}
void subset(int n, int k, int arr[], int pos[], int index, int start)
{
if (index == k) {
for (int j = 0; j < k; ++j) {
MyBuf_PrintInteger(pos[j]);
MyBuf_PrintCharacter(j == k-1 ? '\n' : ' ');
}
return;
}
for(int i = start; i<n; i++){
pos[index] = arr[i];
subset(n, k, arr, pos, index+1, i+1);
}
}
Don't forget to call "MyBuf_Flush" at the end, because without it you will probably missing some printing.
Edit : With the complet code, I do some testing.
While it's true there is improvement (N = 30, k = 20 with your code take ~88s and with the write take ~78s), it really too poor to make that work on less than 1s.
Is it possible to resolve your problem without having a supercalculator ?
Another edit : Okay, I have confused the meaning of "should" and "must", sorry. English is not my motherlanguage. (I thinked that you must use recursion).
Since you are free to not use recursion, here something interesting :
I've implemented recursion and not recursion of n=30, k=20.
For each implementation, I have enable and disabled the printing.
The result are clear :
recursion, printing with printf : ~88s
recursion, printing buffered : ~78s
recursion, no printing : ~7s
--
no recursion, printing with printf : ~80s
no recursion, printing buffered : ~70s
no recursion, no printing : ~0,47s
So in conclusion, it's more the printing part that is really taking time than finding the solution itself.
Here the no recursive implementation :
#define BUF_LEN 4096
typedef struct mybuf {
char buffer[BUF_LEN];
size_t len;
} mybuf;
// For convenience, I use global varaible, but it's BAD
mybuf buf = {.buffer = "", .len = 0};
void MyBuf_PrintOnStdout(void)
{
/*buf.buffer[buf.len] = '\0';
printf("%s", buf.buffer);*/
write(1, buf.buffer, buf.len);
buf.len = 0;
}
void MyBuf_Flush(void)
{
MyBuf_PrintOnStdout();
fflush(stdout);
}
void MyBuf_PrintInteger(int integer)
{
int printedLen;
if (buf.len + 21 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
printedLen = sprintf(buf.buffer + buf.len, "%d", integer);
// Error check (printedLen < 0 == error)
buf.len += printedLen;
}
void MyBuf_PrintCharacter(char character)
{
if (buf.len + 1 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
buf.buffer[buf.len] = character;
++buf.len;
}
void subset_no_recursion(int n, int k)
{
int pos[k];
for (int i = 0; i < k; ++i) {
pos[i] = k - i;
}
for (;;) {
// Last digit incrementation
while (pos[0] <= n) {
/* print
for (int i = k - 1; i >= 0; --i) {
MyBuf_PrintInteger(pos[i]);
MyBuf_PrintCharacter(i == 0 ? '\n' : ' ');
}*/
++pos[0];
}
// We find where we can increment the digit without overflow N
int pivot = 1;
while (pos[pivot] == n - pivot) {
++pivot;
}
if (pivot == k) {
return;
}
++pos[pivot];
while (pivot) {
pos[pivot - 1] = pos[pivot] + 1;
--pivot;
}
}
}
void subset_recursion(int n, int k, int pos[], int index, int start)
{
if (index == k) {
for (int i = 0; i < k; ++i) {
MyBuf_PrintInteger(pos[i]);
MyBuf_PrintCharacter(i == k-1 ? '\n' : ' ');
}
return;
}
for (int i = start; i < n; i++) {
pos[index] = i + 1;
subset_recursion(n, k, pos, index + 1, i + 1);
}
}
#define N 30
#define K 20
int main(void)
{
int pos[K];
time_t clockstart;
time_t clockend;
clockstart = clock();
subset3(N, K);
clockend = clock();
printf("%f\n", ((float)(clockend - clockstart)) / CLOCKS_PER_SEC);
return 0;
}
Related
I have a recursive function that I wrote in C that looks like this:
void findSolutions(int** B, int n, int i) {
if (i > n) {
printBoard(B, n);
} else {
for (int x = 1; x <= n; x++) {
if (B[i][x] == 0) {
placeQueen(B, n, i, x);
findSolutions(B, n, i + 1);
removeQueen(B, n, i, x);
}
}
}
}
The initial call is (size is an integer given by user and B is a 2D array):
findSolutions(B, size, 1);
I tried to convert it into a iteration function but there is another function called removeQueen after findSolutions. I got stuck on where to put this function call. How to solve this problem? Stack is also fine but I'm also having trouble doing that.
I'm going to assume that placeQueen(B, n, i, x) makes a change to B and that removeQueen(B, n, i, x) undoes that change.
This answer shows how to approach the problem generically. It doesn't modify the algorithm like Aconcagua has.
Let's start by defining a state structure.
typedef struct {
int **B;
int n;
int i;
} State;
The original code is equivalent to the following:
void _findSolutions(State *state) {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = 1; x <= state->n; ++x) {
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
findSolutions(state2);
}
}
}
State_free(state); // Frees the board too.
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
Now, we're in position to eliminate the recursion.
void _findSolutions(State *state) {
StateStack *S = StateStack_new();
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(&state));
StateStack_free(S);
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
We can eliminate the helper we no longer need.
void findSolutions(int** B, int n, int i) {
StateStack *S = StateStack_new();
State *state = State_new(B, n, i); // Deep clones B.
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(S, &state));
StateStack_free(S);
}
Functions you need to implement:
StateStack *StateStack_new(void)
void StateStack_free(StateStack *S)
void StateStack_push(StateStack *S, State *state)
int StateStack_pop(StateStack *S, State **p)
State *State_new(int **B, int n, int i) (Note: Clones B)
State *State_clone(const State *state) (Note: Clones state->B)
void State_free(State *state) (Note: Frees state->B)
Structures you need to implement:
StateStack
Tip:
It would be best if you replaced
int **B = malloc((n+1)*sizeof(int*));
for (int i=1; i<=n; ++i)
B[i] = calloc(n+1, sizeof(int));
...
for (int x = 1; x <= n; ++x)
...
B[i][x]
with
char *B = calloc(n*n, 1);
...
for (int x = 0; x < n; ++x)
...
B[(i-1)*n+(x-1)]
What you get by the recursive call is that you get stored the location of the queen in current row before you advance to next row. You will have to re-produce this in the non-recursive version of your function.
You might use another array storing these positions:
unsigned int* positions = calloc(n + 1, sizeof(unsigned int));
// need to initialise all positions to 1 yet:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
}
I reserved a dummy element so that we can use the same indices...
You can now count up last position from 1 to n, and when reaching n there, you increment next position, restarting with current from 1 – just the same way as you increment numbers in decimal, hexadecimal or octal system: 1999 + 1 = 2000 (zero based in this case...).
for(;;)
{
for(unsigned int i = 1; i <= n; ++i)
{
placeQueen(B, n, i, positions[i]);
}
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
}
for(unsigned int i = 1; i <= n; ++i)
{
if(++positions[i] <= n)
// break incrementing if we are in between the numbers:
// 1424 will get 1431 (with last position updated already before)
goto CONTINUE;
positions[i] = 1;
}
// we completed the entire positions list, i. e. we reset very
// last position to 1 again (comparable to an overflow: 4444 got 1111)
// so we are done -> exit main loop:
break;
CONTINUE: (void)0;
}
It's untested code, so you might find a bug in, but it should clearly illustrate the idea. It's the naive aproach, always placing the queens and removing them again.
You can do it a bit cleverer, though: place all queens at positions 1 initially and only move the queens if you really need:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
placeQueen(B, n, i, 1);
}
for(;;)
{
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
++positions[i]
if(++positions[i] <= n)
{
placeQueen(B, n, i, positions[i]);
goto CONTINUE;
}
placeQueen(B, n, i, 1);
positions[i] = 1;
}
break;
CONTINUE: (void)0;
}
// cleaning up the board again:
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, 1);
}
Again, untested...
You might discover that now the queens move within first row first, different to your recursive approach before. If that disturbs you, you can count down from n to 1 while incrementing the positions and you get original order back...
At the very end (after exiting the loop), don't forget to free the array again to avoid memory leak:
free(positions);
If n doesn't get too large (eight for a typical chess board?), you might use a VLA to prevent that problem.
Edit:
Above solutions will print any possible combinations to place eight queens on a chess board. For an 8x8 board, you get 88 possible combinations, which are more than 16 millions of combinations. You pretty sure will want to filter out some of these combinations, as you did in your original solution as well (if(B[i][x] == 0)), e. g.:
unsigned char* checks = malloc(n + 1);
for(;;)
{
memset(checks, 0, (n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[positions[i]] != 0)
goto SKIP;
checks[positions[i]] = 1;
}
// place queens and print board
SKIP:
// increment positions
}
(Trivial approach! Including the filter in the more elaborate approach will get more tricky!)
This will even be a bit more strict than your test, which would have allowed
_ Q _
Q _ _
_ Q _
on a 3x3 board, as you only compare against previous column, whereas my filter wouldn't (leaving a bit more than 40 000 boards to be printed for an 8x8 board).
Edit 2: The diagonals
To filter out those boards where the queens attack each other on the diagonals you'll need additional checks. For these, you'll have to find out what the common criterion is for the fields on the same diagonal. At first, we have to distinguish two types of diagonals, those starting at B[1][1], B[1][2], ... as well as B[2][1], B[3][1], ... – all these run from top left to bottom right direction. On the main diagonal, you'll discover that the difference between row and column index does not differ, on next neighbouring diagonals the indices differ by 1 and -1 respectively, and so on. So we'll have differences in the range [-(n-1); n-1].
If we make the checks array twice as large and shift all differences by n, can re-use do exactly the same checks as we did already for the columns:
unsigned char* checks = (unsigned char*)malloc(2*n + 1);
and after we checked the columns:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[n + i - positions[i]] != 0)
goto SKIP;
checks[n + i - positions[i]] = 1;
}
Side note: Even if the array is larger, you still can just memset(checks, 0, n + 1); for the columns as we don't use the additional entries...
Now next we are interested in are the diagonals going from bottom left to top right. Similarly to the other direction, you'll discover that the difference between n - i and positions[i] remains constant for fields on the same diagonal. Again we shift by n and end up in:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[2 * n - i - positions[i]] != 0)
goto SKIP;
checks[2 * n - i - positions[i]] = 1;
}
Et voilà, only boards on which queens cannot attack each other.
You might discover that some boards are symmetries (rotational or reflection) of others. Filtering these, though, is much more complicated...
I need to write a function that subtracts digits.
If user inputs 2345, the output should be 111 (5-4, 4-3, 3-2); another example would be 683, where the output should be 25 (3-8(abs value is taken), 8-6).
I have wrote the following code which works only when the size of the array is declared.
int subtraction(int arr[], int size) {
int sub = 0;
for (int i = 0; i < size-1; i++) {
sub = sub * 10 + abs(arr[i] - arr[i+1]);
}
return sub;
}
However, the number that the user inputs is random and can have various digits, so I don't know what limit to put in the for loop.
For example:
int arr[] = {1, 2, 55, 56, 65, 135}, i;
subtraction(arr, 6);
for (i=0; i<6; i++)
printf("%d ", arr[i]);
expected output: 0 0 0 1 1 22
The function is supposed to subtract the second-to-last digit from the last one, by the way , / from right to left / from a random number that the user inputs ; for example if the input is 5789, the output is supposed to be 211 (9-8, 8-7, 7-5); if user inputs a negative number, the program should take it's absolute value and then do the subtracting. If user input is a one digit number the result should be 0.
The function I wrote only works when the size of the array is declared. I don't know how to make it work when the size is undeclared (pointers and malloc are required I believe, as that's what I managed to find out by googling for ages, but unfortunately, I don't know how to do it).
please help?
You are not actually changing any values, here is the line you need to look at.
sub = sub * 10 + abs(arr[i] - arr[i+1]);
As you are printing the array you actually need to store the calculated value in the array again.
#include <stdio.h>
#include <stdlib.h>
int subtract(int n)
{
int factor = 1;
int total = 0;
int lastPlace = n%10;
n /= 10;
while (n>0)
{
total += (factor * abs((n%10) - lastPlace));
factor *= 10;
lastPlace = n%10;
n /= 10;
}
return total;
}
void subtractArray(int* arr, unsigned int size)
{
for (int i=0; i<size; ++i)
{
if (arr[i] < 0)
arr[i] = abs(arr[i]);
arr[i] = subtract(arr[i]);
}
}
int main()
{
int arr[] = {1, 2, 55, 56, 65, 135};
int size = sizeof(arr)/ sizeof(arr[0]);
subtractArray(arr, size);
for (int i=0; i<size; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}
Here is a simple code that solve your problem :)
#include <stdio.h>
#include <stdlib.h>
int *subtraction(int arr[], int size)
{
int *sub = calloc(sizeof(int*) , size), i = 0, rev; //allocating memory
for (i = 0; i < size; i++)
{
rev = 0;
arr[i] = abs(arr[i]);
for (int a = 0; arr[i] != 0; arr[i] /= 10)
rev = (rev * 10) + (arr[i] % 10);
for (i; (rev / 10) != 0; rev /= 10) //the loop ends when rev = 0
sub[i] = ((sub[i] * 10) + abs( (rev % 10) - ((rev / 10) % 10) )); //easy math => for example rev = 21 > sub[i] = (0 * 10) + ( (21 % 10) - ((21 / 10) %10)) = abs(1 - 2) = 1;
}
return sub;
}
int main()
{
int arr[] = {-9533, 7, -19173}, i;
int len = sizeof(arr)/sizeof(arr[0]); //size of arr
int *sub = subtraction(arr, len);
for(int i = 0; i < len; i++) //for test
printf("%d ", sub[i]);
return 0;
}
output for {1, 2, 55, 56, 65, 135}:
0 0 0 1 1 22
output for {987654321, 123456789, 111111111} :
11111111 11111111 0
output for {38279}:
5652
output for {-9533, 7, -19173}:
420 0 8864
Well as for the array of undefined size. What you probably want is a dynamically allocated array.
Here we get the number of array elements based on user input, within limits, of course.
first we're gonna get the number from the user using fgets() which will give us a string, then we'll use strtol() to convert the number part to scalar (int). you can use scanf("%d", &n) if you want.
Then we can count the digits from that number, and that value will be the number of elements of our array.
#include <stdio.h>
#include <stdlib.h> //for strtol(), malloc() and NULL guaranteed
//you may also want to add
#include <limits.h>
#include <errno.h>
#define MAX_STRLEN 12 // can hold all digits of INT_MAX plus '\0' and a posible, AND very likely, '\n'
#define DEC 10 // for strtol base argument
/*
* I'm lending you my old get_n_dits() function that I used to count decimal digits.
*/
int get_n_dits(int dnum) {
unsigned char stop_flag = 0; //we'll use to signal we're done with the loop.
int num_dits = 1, dpos_mult = 1; //num_dits start initialized as 1, cause we're pretty sure that we're getting a number with at least one digit
//dpos_mult stands for digital position multiplier.
int check_zresult; //we'll check if integer division yields zero.
/**
* Here we'll iterate everytime (dnum / dpost_mult) results in a non-zero value, we don't care for the remainder though, at least for this use.
* every iteration elevates dpost_mult to the next power of ten and every iteration yielding a non-zero result increments n_dits, once we get
* the zero result, we increment stop_flag, thus the loop condition is no longer true and we break from the loop.
*/
while(!stop_flag) {
dpos_mult *= 10;
check_zresult = dnum / dpos_mult;
(check_zresult) ? num_dits++ : stop_flag++;
}
return num_dits;
}
int main(void) {
int num, ndits; //we'll still using int as per your code. you can check against INT_MAX if you want (defined in limits.h)
int *num_array = NULL; //let's not unintentionally play with an unitialized pointer.
char *num_str = malloc(MAX_STRLEN); //or malloc(sizeof(char) * MAX_STRLEN); if there's any indication that (sizeof(char) != 1)
printf("please enter a number... please be reasonable... or ELSE!\n");
printf(">>> ");
if(!fgets(num_str, MAX_STRLEN, stdin)) {
fprintf(stderr, "Error while reading from STDIN stream.\n");
return -1;
}
num = (int)strtol(num_str, NULL, DEC); //convert the string from user input to scalar.
if(!num) {
fprintf(stderr, "Error: no number found on input.\n");
return -1;
}
ndits = get_n_dits(num);
if(ndits <= 0) {
fprintf(stderr, "Aw, crap!\n");
return -1;
}
printf("number of digits: %d\n", ndits);
num_array = malloc(sizeof(int) * ndits); //now we have our dynamically allocated array.
return 0;
}
I am learning how to apply recursion to arrays.
For example, I usually read arrays itiratively, this way:
void read_array(int *a, int n){
int i;
for(i = 0; i < n; ++i)
scanf("%d", &a[i]);
return;
}
I would like to read an array recursively. I wrote the following function:
void read_array(int *a, int n){
int i = n - 1;
if (n < 0)
return;
else{
if(scanf("%d", &a[n - 1 - i]) == 1){
read_array(a, n - 1);
return;
}
}
}
It compiles, but when running it trows a segmentation fault error. It confuses me since the function contemplates a base case 0 that should stop it.
Your calculation of the array index is wrong. This line:
if(scanf("%d", &a[n - 1 - i]) == 1){
assumes the initial value of n, but at the same time, you decrease n with every recursion step. That being said, it shouldn't crash but just repeatedly write the first element of a, because with i = n - 1, n - 1 - i is always zero.
The idiomatic way to write such a recursion would be to recurse on i:
void read_array(int *a, int n, int i)
{
if (i < n)
{
if(scanf("%d", &a[i]) == 1)
{
read_array(a, n, i+1);
}
}
}
and call it with the initial value for i, e.g. read_array(a, 10, 0) for reading a 10-element array.
In practice, recursion in C is to be avoided.*
* Functional languages can typically optimize recursion, C just uses the call stack with a lot of overhead.
In this example, the theoretical purpose of recursion for writing a pure function is somewhat defeated with a function returning void. If this is just about learning the principle, the functions actually should return something. You could for example create a functional "list builder":
#include <stdio.h>
#include <stdlib.h>
// place the side effect in a separate function
int getValue(void)
{
// could have `scanf()` here:
return rand();
}
typedef struct List
{
int a[10];
size_t length;
} List;
// non-functional helper to get around limitations of C:
// (if it could initialize result directly with the new values, it would
// be functional)
List listAppend(List list, int val)
{
List result = list;
result.a[result.length++] = val;
return result;
}
// recursive function without side effects:
List buildList(List list, int (*value)())
{
if (list.length >= 10) return list;
return buildList(listAppend(list, value()), value);
}
int main(void)
{
List myList = buildList((List){0}, &getValue);
for (size_t i = 0; i < myList.length; ++i)
{
printf("myList.a[%zu] is %d\n", i, myList.a[i]);
}
}
There is a bug in the function.
As the variable i is initialized the following way
int i = n - 1;
then the second argument in this call
scanf("%d", &a[n - 1 - i])
is evaluated like
scanf("%d", &a[n - 1 - (n - 1)])
that is it is always equal to zero
scanf("%d", &a[0])
As the recursive function is called with the same value of the pointer a then all entered values are assigned to a[0]. All other elements of the array are still uninitialized.
Though this does not serve as a reason for the abnormal execution of the function.
It is possible that there is used a big array and the stack is too small to call the function recursively.
In any case the function can be defined more simply and correctly the following way
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
Take into account as the input can be interrupted by the user. In this case the function returns the number of initialized elements of the array.
Here is a demonstrative program.
#include <stdio.h>
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
#define N 10
int main(void)
{
int a[N];
size_t n = read_array( a, N );
for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
return 0;
}
If to enter sequence of numbers
0 1 2 3 4 5 6 7 8 9
then the output will be
0 1 2 3 4 5 6 7 8 9
Example:
int read_array_aux(int *i, int *n) {
if (i == n) {
return 0;
}
if (scanf("%d", i) != 1) {
return -1;
}
return read_array_aux(i + 1, n);
}
int read_array_aux2(int *a, size_t i, size_t n) {
if (i == n) {
return 0;
}
if (scanf("%d", a + i) != 1) {
return -1;
}
return read_array_aux2(a, i + 1, n);
}
int read_array(int *a, size_t n) {
return read_array_aux(a, a + n);
// return read_array_aux2(a, 0, n);
}
First, condition n<0 is wrong. Probably this is the cause of segfault.
Also, why even bother about calculating the index? When processing any kind of list recursively it's worth to grasp the concept of head (first element of list) and tail (everything except head) of the list. So, filling an array recursively would be defined as (in pseudo code):
void read_array() {
read_head();
read_tail();
}
What is head? It's the first element of current array. What's the tail? The array starting from next element. So, read_tail is equivalent of read_array, but with the beginning moved forward by one element.
And, finally, to gather everything into one place:
void read_array(int *a, int n) {
if(n<=0) {
return;
} else {
if(scanf("%d", a) == 1) {
read_array(a+1,n-1);
}
}
}
As other answers have mentioned, your handling of n is leading to problems. You can return 0 from the base case of sz == 0, otherwise return the result of the next recursive call, or -1 if scanf() fails. At each recursive call, increment a and decrement sz. The value returned in the calling function should be checked for input errors: 0 on success, -1 on failure.
Note that this is a tail recursion, which should be optimized by most good compilers.
#include <stdio.h>
int read_array(int *a, size_t sz);
int main(void)
{
int arr[5];
puts("Enter array elements:");
if (read_array(arr, 5) != 0) {
fprintf(stderr, "Input error\n");
} else {
for (size_t i = 0; i < 5; i++) {
printf("%8d", arr[i]);
}
putchar('\n');
}
return 0;
}
int read_array(int *a, size_t sz)
{
if (sz == 0 ) {
return 0;
}
if (scanf("%d", a) == 1){
return read_array(a + 1, sz - 1);
} else {
return -1;
}
}
Sample interaction:
Enter array elements:
1 2 3 4 5
1 2 3 4 5
Enter array elements:
1 2 3 x 5
Input error
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);
}
I have the input as array A = [ 2,3,4,1]
The output is simply all possible permutation from elements in A which can be done by single transposition (single flip of two neighbouring elements) operation. So the output is :
[3,2,4,1],[ 2,4,3,1],[2,3,1,4],[1,3,4,2]
Circular transpositioning is allowed. Hence [2,3,4,1] ==> [1,3,4,2] is allowed and a valid output.
How to do it in C?
EDIT
In python, it would be done as follows:
def Transpose(alist):
leveloutput = []
n = len(alist)
for i in range(n):
x=alist[:]
x[i],x[(i+1)%n] = x[(i+1)%n],x[i]
leveloutput.append(x)
return leveloutput
This solution uses dynamic memory allocation, this way you can do it for an array of size size.
int *swapvalues(const int *const array, size_t size, int left, int right)
{
int *output;
int sotred;
output = malloc(size * sizeof(int));
if (output == NULL) /* check for success */
return NULL;
/* copy the original values into the new array */
memcpy(output, array, size * sizeof(int));
/* swap the requested values */
sotred = output[left];
output[left] = output[right];
output[right] = sotred;
return output;
}
int **transpose(const int *const array, size_t size)
{
int **output;
int i;
int j;
/* generate a swapped copy of the array. */
output = malloc(size * sizeof(int *));
if (output == NULL) /* check success */
return NULL;
j = 0;
for (i = 0 ; i < size - 1 ; ++i)
{
/* allocate space for `size` ints */
output[i] = swapvalues(array, size, j, 1 + j);
if (output[i] == NULL)
goto cleanup;
/* in the next iteration swap the next two values */
j += 1;
}
/* do the same to the first and last element now */
output[i] = swapvalues(array, size, 0, size - 1);
if (output[i] == NULL)
goto cleanup;
return output;
cleanup: /* some malloc call returned NULL, clean up and exit. */
if (output == NULL)
return NULL;
for (j = i ; j >= 0 ; j--)
free(output[j]);
free(output);
return NULL;
}
int main()
{
int array[4] = {2, 3, 4, 1};
int i;
int **permutations = transpose(array, sizeof(array) / sizeof(array[0]));
if (permutations != NULL)
{
for (i = 0 ; i < 4 ; ++i)
{
int j;
fprintf(stderr, "[ ");
for (j = 0 ; j < 4 ; ++j)
{
fprintf(stderr, "%d ", permutations[i][j]);
}
fprintf(stderr, "] ");
free(permutations[i]);
}
fprintf(stderr, "\n");
}
free(permutations);
return 0;
}
Although some people think goto is evil, this is a very nice use for it, don't use it to control the flow of your program (for instance to create a loop), that is confusing. But for the exit point of a function that has to do several things before returning, it think it's actually a nice use, it's my opinion, for me it makes the code easier to understand, I might be wrong.
Have a look at this code I have written with an example :
void transpose() {
int arr[] = {3, 5, 8, 1};
int l = sizeof (arr) / sizeof (arr[0]);
int i, j, k;
for (i = 0; i < l; i++) {
j = (i + 1) % l;
int copy[l];
for (k = 0; k < l; k++)
copy[k] = arr[k];
int t = copy[i];
copy[i] = copy[j];
copy[j] = t;
printf("{%d, %d, %d, %d}\n", copy[0], copy[1], copy[2], copy[3]);
}
}
Sample Output :
{5, 3, 8, 1}
{3, 8, 5, 1}
{3, 5, 1, 8}
{1, 5, 8, 3}
A few notes:
a single memory block is preferred to, say, an array of pointers because of better locality and less heap fragmentation;
the cyclic transposition is only one, it can be done separately, thus avoiding the overhead of the modulo operator in each iteration.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *single_transposition(const int *a, unsigned int n) {
// Output size is known, can use a single allocation
int *out = malloc(n * n * sizeof(int));
// Perform the non-cyclic transpositions
int *dst = out;
for (int i = 0; i < n - 1; ++i) {
memcpy(dst, a, n * sizeof (int));
int t = dst[i];
dst[i] = dst[i + 1];
dst[i + 1] = t;
dst += n;
}
// Perform the cyclic transposition, no need to impose the overhead
// of the modulo operation in each of the above iterations.
memcpy(dst, a, n * sizeof (int));
int t = dst[0];
dst[0] = dst[n-1];
dst[n-1] = t;
return out;
}
int main() {include
int a[] = { 2, 3, 4, 1 };
const unsigned int n = sizeof a / sizeof a[0];
int *b = single_transposition(a, n);
for (int i = 0; i < n * n; ++i)
printf("%d%c", b[i], (i % n) == n - 1 ? '\n' : ' ');
free(b);
}
There are many ways to tackle this problem, and most important questions are: how you're going to consume the output and how variable is the size of the array. You've already said the array is going to be very large, therefore I assume memory, not CPU will be the biggest bottleneck here.
If output is going to be used only few times (especially just once), it'll may be best to use functional approach: generate every transposition on the fly, and never have more than one in memory at a time. For this approach many high level languages would work as well as (maybe sometimes even better than) C.
If size of the array is fixed, or semi-fixed (eg few sizes known at compile-time), you can define structures, using C++ templates at best.
If size is dynamic and you still want to have every transposition in memory then you should allocate one huge memory block and treat it as contiguous array of arrays. This is very simple and straightforward on machine level. Unfortunately it's best tackled using pointer arithmetic, one feature of C/C++ that is renowned for being difficult to understand. (It isn't if you learn C from basics, but people jumping down from high level languages have proven track record of getting it completely wrong first time)
Other approach is to have big array of pointers to smaller arrays, which results in double pointer, the ** which is even more terrifying to newcomers.
Sorry for long post which is not a real answer, but IMHO there are too many questions left open for choosing the best solution and I feel you need bit more C basic knowledge to manage them on your own.
/edit:
As other solutions are already posted, here's a solution with minimum memory footprint. This is the most limiting approach, it uses same one buffer over and over, and you must be sure that your code is finished with first transposition before moving on to the next one. On the bright side, it'll still work just fine when other solutions would require terabyte of memory. It's also so undemanding that it might be as well implemented with a high level language. I insisted on using C++ in case you would like to have more than one matrix at a time (eg comparing them OR running several threads concurrently).
#define NO_TRANSPOSITION -1
class Transposable1dMatrix
{
private:
int * m_pMatrix;
int m_iMatrixSize;
int m_iCurrTransposition;
//transposition N means that elements N and N+1 are swapped
//transpostion -1 means no transposition
//transposition (size-1) means cyclic transpostion
//as usual in C (size-1) is the last valid index
public:
Transposable1dMatrix(int MatrixSize)
{
m_iMatrixSize = MatrixSize;
m_pMatrix = new int[m_iMatrixSize];
m_iCurrTransposition = NO_TRANSPOSITION;
}
int* GetCurrentMatrix()
{
return m_pMatrix;
}
bool IsTransposed()
{
return m_iCurrTransposition != NO_TRANSPOSITION;
}
void ReturnToOriginal()
{
if(!IsTransposed())//already in original state, nothing to do here
return;
//apply same transpostion again to go back to original
TransposeInternal(m_iCurrTransposition);
m_iCurrTransposition = NO_TRANSPOSITION;
}
void TransposeTo(int TranspositionIndex)
{
if(IsTransposed())
ReturnToOriginal();
TransposeInternal(TranspositionIndex);
m_iCurrTransposition = TranspositionIndex;
}
private:
void TransposeInternal(int TranspositionIndex)
{
int Swap1 = TranspositionIndex;
int Swap2 = TranspositionIndex+1;
if(Swap2 == m_iMatrixSize)
Swap2 = 0;//this is the cyclic one
int tmp = m_pMatrix[Swap1];
m_pMatrix[Swap1] = m_pMatrix[Swap2];
m_pMatrix[Swap2] = tmp;
}
};
void main(void)
{
int arr[] = {2, 3, 4, 1};
int size = 4;
//allocate
Transposable1dMatrix* test = new Transposable1dMatrix(size);
//fill data
memcpy(test->GetCurrentMatrix(), arr, size * sizeof (int));
//run test
for(int x = 0; x<size;x++)
{
test->TransposeTo(x);
int* copy = test->GetCurrentMatrix();
printf("{%d, %d, %d, %d}\n", copy[0], copy[1], copy[2], copy[3]);
}
}