I have a problem question and a snippet code below. The snippet is filled already because I found out the solution but I do not understand why it is like that. Could you help me explain how the codes work?
Problem: Ten tiles each have strings of in between 1 and 4 letters on them (hardcoded in the code below). The goal of this problem is to complete the code below so it counts the number of different orders in which all of the tiles can be placed such that the string they form creates a palindrome (a word that reads the same forwards and backwards). All of main, as well as the function eval which determines if a particular ordering of the tiles forms a palindrome. You may call this function in the function go. Complete the recursive function (named go) to complete the solution.
Snippet code:
#include <stdio.h>
#include <string.h>
#define N 10
#define MAXLEN 5
int go(int perm[], int used[], int k, char tiles[N][MAXLEN]);
int eval(int perm[], char tiles[N][MAXLEN]);
char MYTILES[N][MAXLEN] = {
"at", "ta", "g", "cc", "ccac", "ca", "cc", "gag", "cga", "gc"
};
int
main(void)
{
int perm[N];
int used[N];
for (int i = 0; i < N; i++)
used[i] = 0;
int res = go(perm, used, 0, MYTILES);
printf("Number of tile orderings that create palindromes is %d\n", res);
return 0;
}
int
go(int perm[], int used[], int k, char tiles[N][MAXLEN])
{
if (k == N)
return eval(perm, tiles);
int res = 0;
for (int i = 0; i < N; i++) {
if (used[i])
continue;
used[i] = 1;
perm[k] = i;
res += go(perm, used, k + 1, tiles);
used[i] = 0;
}
return res;
}
int
eval(int perm[], char tiles[N][MAXLEN])
{
char tmp[N * MAXLEN];
int idx = 0;
for (int i = 0; i < N; i++) {
int len = strlen(tiles[perm[i]]);
for (int j = 0; j < len; j++)
tmp[idx++] = tiles[perm[i]][j];
}
tmp[idx] = '\0';
for (int i = 0; i < idx / 2; i++)
if (tmp[i] != tmp[idx - 1 - i])
return 0;
return 1;
}
Thank you. I appreciate all help!!
To understand this code, add the following line to the start of eval():
for( int j = 0; j < N; j++ ) printf( "%d ", perm[j] ); putchar('\n');
The for() loop in go() causes a recursion that is 10 levels deep, ultimately generating 10! (~3.6 million) permutations of the 10 indices from 0 to 9. In sequence, each of those permutations is used to concatenate the 'tokens' (the short ACTG variations) into a single string that is then tested for being palindromic by `eval()'
This is called a "brute force" search through the possibility space.
Below I've revised the code to be slightly more compact, adding two "printf debugging" lines (marked "/**/") that report what the program is doing. You'll need some patience if you wish to watch millions of permutations of 0 to 9 scroll by, or simply comment out that line and recompile. I also shuffled things around and made the two interesting arrays global instead of "whacking the stack" by passing them up/down the recursion. Less code is better. This program is "single purpose". The clarity gained justifies using global variables in this instance, imho.
More interesting is the additional puts() line that reports the palindromic sequences.
#include <stdio.h>
#include <string.h>
#define N 10
#define MAXLEN 5
char MYTILES[N][MAXLEN] = { "AT","TA","G","CC","CCAC","CA","CC","GAG","CGA","GC" };
int perm[N], used[N] = { 0 };
int go( int k ) {
if (k == N) {
// At extent of recursion here.
/**/ for( int j = 0; j < k; j++ ) printf( "%d ", perm[j] ); putchar('\n');
// Make a string in this sequence
char tmp[N*MAXLEN] = {0};
for( int i = 0; i < N; i++ )
strcat( tmp, MYTILES[ perm[ i ] ] );
// Test string for being palidromic
for( int l = 0, r = strlen( tmp ) - 1; l <= r; l++, r-- )
if( tmp[l] != tmp[r] )
return 0; // Not palidrome
/**/ puts( tmp );
return 1; // Is palidrome
}
// recursively generate permutations here
int res = 0;
for( int i = 0; i < N; i++ )
if( !used[i] ) {
used[i] = 1;
perm[k] = i;
res += go( k+1 );
used[i] = 0;
}
return res;
}
int main( void ) {
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
return 0;
}
An immediate 'speed-up' would be to test that the first letter of the 0th string to be permuted matches the last letter of the 9th string... Don't bother concatenating if a palindrome is impossible from the get-go. Other optimisations are left as an exercise for the reader...
BTW: It's okay to make a copy of code and add your own print statements so that the program reports what it is doing when... Or, you could single-step through a debugger...
UPDATE
Having added a preliminary generation of a 10x10 matrix to 'gate' the workload of generating strings to be checked as palindromic, with the 10 OP supplied strings, it turns out that 72% of those operations were doomed to fail from the start. Of the 3.6 million "brute force" attempts, a quick reference to this pre-generated matrix prevented about 2.6 million of them.
It's worthwhile trying to make code efficient.
UPDATE #2:
Bothered that there was still a lot of 'fat' in the execution after trying to improve on the "brute force" in a simple way, I've redone some of the code.
Using a few extra global variables (the state of processing), the following now does some "preparation" in main(), then enters the recursion. In this version, once the string being assembled from fragments is over half complete (in length), it is checked from the "middle out" if it qualifies as being palindromic. If so, each appended fragment causes a re-test. If the string would never become a palindrome, the recursion 'backs-up' and tries another 'flavour' of permutation. This trims the possibility space immensely (and really speeds up the execution.)
char *Tiles[] = { "AT","TA","G","CC","CCAC","CA","CC","GAG","CGA","GC" };
const int nTiles = sizeof Tiles/sizeof Tiles[0];
int used[ nTiles ];
char buildBuf[ 1024 ], *cntrL, *cntrR; // A big buffer and 2 pointers.
int fullLen;
int cntTested, goCalls; // some counters to report iterations
uint32_t factorial( uint32_t n ) { // calc n! (max 12! to fit uint32_t)
uint32_t f = 1;
while( n ) f *= n--;
return f;
}
int hope() { // center outward testing for palindromic characteristics
int i;
for( i = 0; cntrL[ 0 - i ] == cntrR[ 0 + i ]; i++ ) ; // looping
return cntrR[ 0 + i ] == '\0';
}
int go( int k ) {
goCalls++;
if( k == nTiles ) { // at full extent of recursion here
// test string being palindromic (from ends toward middle for fun)
cntTested++;
for( int l = 0, r = fullLen - 1; l <= r; l++, r-- )
if( buildBuf[l] != buildBuf[r] )
return 0; // Not palindrome
/**/ puts( buildBuf );
return 1; // Is palindrome
}
// recursively generate permutations here
// instead of building from sequence of indices
// this builds the (global) sequence string right here
int res = 0;
char *at = buildBuf + strlen( buildBuf );
for( int i = 0; i < nTiles; i++ )
if( !used[i] ) {
strcpy( at, Tiles[ i ] );
// keep recursing until > half assembled and hope persists
if( at < cntrL || hope() ) {
used[i] = 1;
res += go( k+1 ); // go 'deeper' in the recursion
used[i] = 0;
}
}
return res;
}
int main( void ) {
for( int i = 0; i < nTiles; i++ )
fullLen += strlen( Tiles[i] );
if( fullLen % 2 == 0 ) // even count
cntrR = (cntrL = buildBuf + fullLen/2 - 1) + 1; // 24 ==> 0-11 & 12->23
else
cntrR = cntrL = buildBuf + fullLen/2; // 25 ==> 0-12 & 12->24
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
printf( "Potential: %d\n", factorial( nTiles ) );
printf( "Calls to go(): %d\n", goCalls );
printf( "Actual: %d\n", cntTested );
return 0;
}
ATCCACGAGCCGCCGAGCACCTA
ATCCACGAGCCGCCGAGCACCTA
ATCCACGCCGAGAGCCGCACCTA
ATCCACGCCGAGAGCCGCACCTA
ATCACCGAGCCGCCGAGCCACTA
ATCACCGCCGAGAGCCGCCACTA
ATCACCGAGCCGCCGAGCCACTA
ATCACCGCCGAGAGCCGCCACTA
TACCACGAGCCGCCGAGCACCAT
TACCACGAGCCGCCGAGCACCAT
TACCACGCCGAGAGCCGCACCAT
TACCACGCCGAGAGCCGCACCAT
TACACCGAGCCGCCGAGCCACAT
TACACCGCCGAGAGCCGCCACAT
TACACCGAGCCGCCGAGCCACAT
TACACCGCCGAGAGCCGCCACAT
CCACATGAGCCGCCGAGTACACC
CCACATGAGCCGCCGAGTACACC
CCACATGCCGAGAGCCGTACACC
CCACATGCCGAGAGCCGTACACC
CCACTAGAGCCGCCGAGATCACC
CCACTAGAGCCGCCGAGATCACC
CCACTAGCCGAGAGCCGATCACC
CCACTAGCCGAGAGCCGATCACC
CACCATGAGCCGCCGAGTACCAC
CACCATGCCGAGAGCCGTACCAC
CACCTAGAGCCGCCGAGATCCAC
CACCTAGCCGAGAGCCGATCCAC
CACCATGAGCCGCCGAGTACCAC
CACCATGCCGAGAGCCGTACCAC
CACCTAGAGCCGCCGAGATCCAC
CACCTAGCCGAGAGCCGATCCAC
Palindromic tile orderings: 32
Potential: 3628800
Calls to go(): 96712
Actual: 32
UPDATE #3 (having fun)
When there's too much code, and an inefficient algorithm, it's easy to get lost and struggle to work out what is happening.
Below produces exactly the same results as above, but shaves a few more operations from the execution. In short, go() is called recursively until at least 1/2 of the candidate string has been built-up. At that point, hope() is asked to evaluate the string "from the middle, out." As long as the conditions of being palindromic (from the centre, outward) are being met, that evaluation is repeated as the string grows (via recursion) toward its fullest extent. It is the "bailing-out early" that makes this version far more efficient than the OP version.
One further 'refinement' is that the bottom of the recursion is found without an extra call to \0. Once one has the concepts of recursion and permutation, this should all be straight forward...
char *Tiles[] = { "AT", "TA", "G", "CC", "CCAC", "CA", "CC", "GAG", "CGA", "GC" };
const int nTiles = sizeof Tiles/sizeof Tiles[0];
int used[ nTiles ];
char out[ 1024 ], *cntrL, *cntrR;
int hope() { // center outward testing for palidromic characteristics
char *pL = cntrL, *pR = cntrR;
while( *pL == *pR ) pL--, pR++;
return *pR == '\0';
}
int go( int k ) {
int res = 0;
char *at = out + strlen( out );
for( size_t i = 0; i < nTiles; i++ )
if( !used[i] ) {
strcpy( at, Tiles[ i ] );
if( at >= cntrL && !hope() ) // abandon this string?
continue;
if( k+1 == nTiles ) { // At extent of recursion here.
puts( out );
return 1;
}
used[i] = 1, res += go( k+1 ), used[i] = 0;
}
return res;
}
int main( void ) {
int need = 0;
for( size_t i = 0; i < nTiles; i++ )
need += strlen( Tiles[ i ] );
cntrL = cntrR = out + need/2; // odd eg: 25 ==> 0-12 & 12->24
cntrL -= (need % 2 == 0 ); // but, if even eg: 24 ==> 0-11 & 12->23
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
return 0;
}
I'm trying to solve some problems. but there is something wrong with my code.
The problem is : Given a number n, output n*n in the following format.
Input:
n=3
Output:
7 8 1
6 9 2
5 4 3
Here is my code: (I know there are some bugs in it, but I can't fix it. If you have better ideas, help me.)
Thank in advance.
#include<stdio.h>
#include<stdlib.h>
void oput(int **matrix,int n);
int main()
{ int x=0,y=0,n,k=1;
scanf("%d",&n);
int **matrix = malloc(sizeof(int)*n*n);
if(matrix==NULL)
{
perror("can't allocate");
return 1;
}
//Input values to x*y matrix
while(n>=1)
{
for(x=0,y=n-1;x<n;x++)
{
matrix[x][y]=k++;
}
for(x=n-1,y=n-1;y>=0;y--)
{
matrix[x][y]=k++;
}
for(x=n-1,y=0;x>=0;x--)
{
matrix[x][y]=k++;
}
n--;
}
oput(matrix,n);
free(matrix);
return 0;
}
//output values by row.
void oput(int **matrix,int n)
{
int i=0,j=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ",matrix[i][j]);
}
printf("\n");
}
}
Error arises at running time.
Just for fun I worked on a solution for this problem.
I'm not allowed to write comments under the question, yet, so I assumed that starting the "spiral numbering" from the upper right corner of the matrix was a requirement of the problem.
My solution consists in adding numbers all over the perimeter, using four different loops. And then starting again adding an indentation level.
#include <stdio.h>
#include <string.h>
void printMatrix( int *nMatrix, int n, char *title )
{
int i, j;
if( title )
printf( "%s\n", title );
for( i=0; i<n; i++ )
{
for( j=0; j<n; j++ )
{
printf( "%d\t", *(nMatrix+n*i+j) );
}
printf( "\n" );
}
}
void main( int argc, char *argv[] )
{
if( argc == 2 )
{
int n = atoi ( argv[1] );
int i, j;
printf( "Input value: %d\n", n );
if( n > 0 && n <= 10 )
{
int spiral[n][n];
int indentNr, x, y, lastNr=0;
memset( spiral, 0, n*n*sizeof( int ));
/* As indentNr is incremented, inner frames are filled */
for( indentNr=0; n-2*indentNr>0; indentNr++ )
{
/* Go South */
for( x=indentNr, y=n-1-indentNr; x<n-indentNr; x++ )
{
spiral[x][y] = ++lastNr;
}
/* Go West (Village People, 1979) */
for( y=n-2-indentNr, x=n-1-indentNr; y>=indentNr; y-- )
{
spiral[x][y] = ++lastNr;
}
/* Go North */
for( x=n-2-indentNr, y=indentNr; x>=indentNr; x-- )
{
spiral[x][y] = ++lastNr;
}
/* Go East */
for( y=1+indentNr, x=indentNr; y<n-1-indentNr; y++ )
{
spiral[x][y] = ++lastNr;
}
}
/* Print results */
printMatrix( &(spiral[0][0]), n, "Final spiral:" );
}
else
{
printf( "ERROR: 'n' too big!\n" );
}
}
else
{
printf( "USAGE: spiral n\n" );
}
}
Please note that:
Input of 'n' is inserted with main argument (no scanf)
I limited 'n' to 10
This solution is iterative. I did not analyse recursive solutions
There is probably a more elegant solution for skipping all 4 loops for inner frames with n=1 and n=2. I did not spent much time in figuring it out
I tested both odd and even scenarios and both seem to work fine. I tested up to n=10. I don't expect troubles for bigger numbers (except for presentation issues in case of big numbers), but feel free to report me any bug.
I don't know what is the matter.. it works great when I run on my pc but when I submit in uva OJ it says time limit exceeded please help
Here is my solution:
#include <stdio.h>
int main()
{
long int i,j,c,t,k,u,r;
scanf("%d %d",&i,&j);
printf("%d %d",i,j);
r = 0;
if(i>j){
t = i;
i = j;
j = t;
}
for(k = i; k<=j;k++){
c = 1;
u = k;
while(u>1){
if(u%2 == 0)
u = u/2;
else
u = 3*u+1;
c++;
if(c>=r)
r = c;
}
}
printf (" %d",r);
return 0;
}
The following code, on my ubuntu Linux 14.04 takes about 1 second to run, when invoked via:
./untitled > outfile.txt
so perhaps this could be useful.
Note: this will have to be modified significantly for the euler problem
Note: the problem says "UNDER" 1 million, but this code starts at 1 million rather than starting at 999999
// Longest Collatz sequence
// Problem 14
/*
* criteria
* The following iterative sequence is defined for the set of positive integers:
* n → n/2 (n is even)
* n → 3n + 1 (n is odd)
*
* example:
* Using the rule above and starting with 13, we generate the following sequence:
* 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
* It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms.
* Although it has not been proved yet (Collatz Problem),
* it is thought that all starting numbers finish at 1.
*
* the question:
* Which starting number, under one million, produces the longest chain?
*
* Note:
* Once the chain starts the terms are allowed to go above one million.
*/
#include <stdio.h>
// prototypes
void fastWrite( size_t a );
int main( void )
{
#define MAX_START_VALUE (1000000)
size_t LongestChain = 0;
size_t LongestStartValue = 0;
for( size_t i=MAX_START_VALUE; i; i--)
{
size_t chainLength = 0;
size_t result = i;
// for debug
char buffer[] = "current start value:";
for( size_t j=0; buffer[j]; j++) putchar_unlocked( buffer[j] );
putchar_unlocked( ' ');
fastWrite( i );
// end debug
while( result != 1 )
{
chainLength++;
if( result&1 )
{ // then odd
result = 3*result +1;
}
else
{ // else even
result >>= 1;
}
// for debug
//./fastWrite( result );
// end debug
}
chainLength++;
// for debug
char buffer2[] = "chain length: ";
for( size_t k=0; buffer2[k]; k++) putchar_unlocked( buffer2[k] );
fastWrite( chainLength );
putchar_unlocked( '\n' );
// end debug
if ( chainLength > LongestChain )
{
LongestChain = chainLength;
LongestStartValue = i;
}
}
fastWrite( LongestStartValue );
putchar_unlocked('\n');
//putchar_unlocked('\n');
} // end function: main
inline void fastWrite(size_t a)
{
char snum[20];
//printf( "%s, %lu\n", __func__, a );
int i=0;
do
{
// 48 is numeric character 0
snum[i++] = (char)((a%10)+(size_t)48);
a=a/10;
}while(a>0);
i=i-1; // correction for overincrement from prior 'while' loop
while(i>=0)
{
putchar_unlocked(snum[i--]);
}
putchar_unlocked('\n');
} // end function: fastWrite
Just to be helpful with the time taken:
the following are good ways to speed up the I/O
#include <stdio.h>
void fastRead( size_t *a );
void fastWrite( size_t a );
inline void fastRead(size_t *a)
{
int c=0;
// note: 32 is space character
while (c<33) c=getchar_unlocked();
// initialize result value
*a=0;
// punctuation parens, etc are show stoppers
while (c>47 && c<58)
{
*a = (*a)*10 + (size_t)(c-48);
c=getchar_unlocked();
}
//printf( "%s, value: %lu\n", __func__, *a );
} // end function: fastRead
inline void fastWrite(size_t a)
{
char snum[20];
//printf( "%s, %lu\n", __func__, a );
int i=0;
do
{
// 48 is numeric character 0
snum[i++] = (char)((a%10)+(size_t)48);
a=a/10;
}while(a>0);
i=i-1; // correction for overincrement from prior 'while' loop
while(i>=0)
{
putchar_unlocked(snum[i--]);
}
putchar_unlocked('\n');
} // end function: fastWrite
and output characters via:
putchar_unlocked( char );
and always have a final, at end of each test case, the following line:
putchar_unlocked( '\n' );
to input a string of characters, call the following in a loop until a space or newline is encountered
char = getchar_unlocked()
and a final hint: most such problems are easily solved using size_t numeric values, which allows values to 4gig or more. (same as a unsigned long int)
For the current problem. as soon as a chain is calculated, save the chain, perhaps in an array, so you do not have to calculate it again.
Your could pre-calculate the first 'x' chains, say the first 10 for instance, to help with shortening the execution time.
Disclaimer: it is an exercise, but it's not homework.
Now, here we go. The exercise asks for the rotation of a generic array to the left, putting the first element in the last position, and doing it so with recursion. My thoughts:
Here's the right rotation one I've written:
void moveArrayRight (int array[], int dim){
if(dim!=1){
int holder;
holder = array[dim-1];
array[dim-1]=array[dim-2];
array[dim-2]=holder;
moveArrayRight(array, dim-1);
}
}
The thing is: I cannot (I think) use the same technique for the left one. I could add another parameter (technically, I could use whatever I want to), but I deeply dislike it. If possible, I would like to retain only two parameters. I also thought of doing something like using the last element of the array to store what is going to be in the next cell, but I don't know how to implement it mainly for a reason: I have no idea how to retain the original dimension of the array.
Any thoughts, hints or something like that?
void rotate_left( int a[], size_t n )
{
if ( n > 1 )
{
int tmp = a[0];
a[0] = a[1];
a[1] = tmp;
rotate_left( a + 1, n - 1 );
}
}
Here is an example of the function usage
#include <stdio.h>
void rotate_left( int a[], size_t n )
{
if ( n > 1 )
{
int tmp = a[0];
a[0] = a[1];
a[1] = tmp;
rotate_left( a + 1, n - 1 );
}
}
int main( void )
{
int a[] = { 1, 2, 3, 4, 5 };
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ ) printf( "%d ", a[i] );
puts( "" );
rotate_left( a, 5 );
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ ) printf( "%d ", a[i] );
puts( "" );
return 0;
}
The output is
1 2 3 4 5
2 3 4 5 1
To use recursion effectively you would split the work, for example in the middle, instead of just slicing off one item at a time. Something like:
function shiftLeft(arr, start, len, in) {
var result;
if (len == 1) {
result = arr[start];
arr[start] = in;
} else {
var half = Math.floor(len / 2);
in = shiftLeft(arr, start + half, len - half, in);
result = shiftLeft(arr, start, half, in);
}
return result;
}
Usage:
shiftLeft(arr, 0, arr.length, arr[0]);
(Disclaimer: The code is not tested and might have bugs, I wrote this on my phone.)
For this array, trying something like this:
void rollover(int val,int count) {
if(count==0) {
return;
}
printf("%d ",val);
count--;
rollover(val,count);
}
int main() {
int arr[]={0,1};
for(int i=0;i<=1;i++) {
rollover(arr[i],4);
}
printf("\n");
return 0;
}
Expected output using recursion method:
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Can't understand how to write that rec function. I have spent several hours to solve it.
Can someone assist to write that function?
I am/was trying to do something like G_G posted below.
How can i write such recursion function?
Do i have to use one for loop to call that recursion function or two for loop with recursion or should i call the recursion function twice? For example:
void rollover(int val,int count) {
if(count==0) {
return;
}
printf("%d ",val);
count--;
rollover(val,count);
//.. do something if necessary ..
rollover(val,count);
//.. do something if necessary ..
}
Simplest solution : binary conversion, no recursion
for(int i = 0; i < 16: ++i) {
printf("%u%u%u%u", i/8%2, i/4%2, i/2%2, i%2);
}
See MOHAMED's answer for a recursive version of this loop
Binary recursion used by the following solutions
_ 000
_ 00 _/
/ \_ 001
0 _ 010
\_ 01 _/
\_ 011
_ 100
_ 10 _/
/ \_ 101
1 _ 110
\_ 11 _/
\_ 111
Recursive solution using char* buffer, no binary conversion
void char_buffer_rec(char number[4], int n) {
if(n > 0) {
number[4-n] = '0';
char_buffer_rec(number, n - 1);
number[4-n] = '1';
char_buffer_rec(number, n - 1);
}
else {
printf("%s\n", number);
}
}
usage :
char number[5] = {0};
char_buffer_rec(number, 4);
Recursive solution using only int, no buffer, no binary conversion
void int_ten_rec(int number, int tenpower) {
if(tenpower > 0) {
int_ten_rec(number, tenpower/10);
int_ten_rec(number + tenpower, tenpower/10);
}
else {
printf("%04u\n", number);
}
}
usage :
int_ten_rec(0, 1000);
Another version of this solution replacing tenpower width bitwidth, replacing the printf width with a variable padding depending on the length variable. length could be defined as a new parameter, a program constant, etc.
void int_rec(int number, int bitwidth) {
static int length = bitwidth;
int i, n;
if(bitwidth > 0) {
int_rec(number, bitwidth-1);
/* n := 10^(bitwidth-2) */
for(i=0,n=1;i<bitwidth-1;++i,n*=10);
int_rec(number + n, bitwidth-1);
}
else {
/* i := number of digit in 'number' */
for(i=1,n=number;n>=10;++i,n/=10);
/* print (length-i) zeros */
for(n=i; n<length; ++n) printf("0");
printf("%u\n", number);
}
}
usage :
int_rec(0, 4);
Tree Solution, recursive using char* buffer, no binary conversion
struct Node {
int val;
struct Node *left, *right;
};
void build_tree(struct Node* tree, int n) {
if(n > 0) {
tree->left = (Node*)malloc(sizeof(Node));
tree->right= (Node*)malloc(sizeof(Node));
tree->left->val = 0;
build_tree(tree->left, n - 1);
tree->right->val = 1;
build_tree(tree->right, n - 1);
}
else {
tree->left = tree->right = NULL;
}
}
void print_tree(struct Node* tree, char* buffer, int index) {
if(tree->left != NULL && tree->right != NULL) {
sprintf(buffer+index, "%u", tree->val);
print_tree(tree->left, buffer, index+1);
sprintf(buffer+index, "%u", tree->val);
print_tree(tree->right, buffer, index+1);
}
else {
printf("%s%u\n", buffer, tree->val);
}
}
usage :
char buffer[5] = {0};
Node* tree = (Node*)malloc(sizeof(Node));
tree->val = 0;
build_tree(tree, 4);
print_tree(tree, buffer, 0);
But this would print an additional 0 at the begining of each line, to avoid this, build two smaller trees :
Node* tree0 = (Node*)malloc(sizeof(Node));
Node* tree1 = (Node*)malloc(sizeof(Node));
tree0->val = 0;
tree1->val = 1;
build_tree(tree0, 3);
build_tree(tree1, 3);
print_tree(tree0, buffer, 0);
print_tree(tree1, buffer, 0);
Recursive solution using int* array
#define MAX_LENGTH 32
int number[MAX_LENGTH];
void int_buffer_rec(int n, int length) {
if(n > 0) {
number[length - n] = 0;
int_buffer_rec(n - 1, length);
number[length - n] = 1;
int_buffer_rec(n - 1, length);
}
else {
for(int i = 0; i < length; ++i) {
printf("%u", number[i]);
}
printf("\n");
}
}
usage :
int_buffer_rec(4, 4);
the recursion could be done with +1
void f(unsigned int x)
{
printf("%u%u%u%u\n",
(x>>3)&0x1,
(x>>2)&0x1,
(x>>1)&0x1,
x&0x1);
if(x==0xF) return;
else f(x+1);
}
int main(void)
{
f(0);
}
Execution:
$ ./test
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
just traverse DFS a binary tree of depth 4, going left is 0, going right is 1.
tr(int dep, int val)
{
if(dep == 4)
{
printf("\n");
}
else
{
printf("%d", val);
tr(dep+1, 0); // going left
tr(dep+1, 1); // going right
}
return;
}
int main()
{
tr(0,0);
}
I tried to limit my solution using to the same arguments but I would definitively add an extra argument to know the initial value of count.
void rec(int val, int count) {
if (count <= 1) {
int i;
int f = 0;
for (i = sizeof(int) * 8; i >= 0; i--) {
f |= (val >> i) & 1;
if (f) {
printf("%d", (val >> i) & 1);
}
}
printf("\n");
} else {
rec(val * 2, count - 1);
rec(val * 2 + 1, count - 1);
}
}
Output:
1
10
11
100
101
110
111
1000
1001
1010
1011
1100
1101
1110
1111
In order to add the leading 0, I added an argument :
#include <stdio.h>
void rec2(int val, int count, int b) {
if (count <= 1) {
int i;
for (i = b - 1; i >= 0; i--) {
printf("%d", (val >> i) & 1);
}
printf("\n");
} else {
rec2(val * 2, count - 1, b);
rec2(val * 2 + 1, count - 1, b);
}
}
void rec(int val, int count) {
rec2(val, count, count);
}
int main() {
rec(0, 4);
rec(1, 4);
return 0;
}
Output:
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Let us start by designing the prototype of the recursive function. Hopefully, it'll make sense from there. Take a look at a non-recursive version of this code, and you'll need the same variables. You don't need to pass any of them as arguments, but I'd prefer to pass them all, and make the solution as flexible and modular as possible. Consider the return value, too. That should probably indicate some sort of success, in order to mimic consistency with the C standard library.
int count_r(char *destination, /* The storage for the function to store *
* the 0s and 1s as we count. */
size_t length, /* The number of digits in the number. */
char *digit); /* The set of digits */
Now let us focus on designing the first iteration. Like in primary school, we start by defining our count_r to iterate only single digits at a time. Once we can prove that it knows how to count from 0 to 9, we introduce it to double digits... but for now, one step at a time.
Let us assume destination is initialised to contain length bytes of digits[0], prior to the first call. This initialisation is done by the caller, and the caller would presumably output that pre-initialised array before calling. The first iteration should modify only one byte: The one indicated by length, and then return to the caller.
int count_r(char *destination, size_t length, char *digit) {
/* The position of the right-most digit is before the '\0' in destination, *
* so we need to decrement length */
length--;
/* Find the digit at the very end of destination, within our "digit" parameter */
char *d = strchr(digit, destination[length]);
/* d[1] points to the next digit (or '\0') */
destination[length] = d[1];
return 0;
}
The caller then presumably prints the array, and calls count_r again with the same buffer to increment the counter. This works with different bases, and by reversing the digit string we can decrement instead of incrementing. However, as we'll soon see, it fails after it reaches the highest number it can count to: 'F' in the example below.
int main(void) {
char num[] = "0";
do {
puts(num);
} while (count_r(num, strlen(num), "0123456789ABCDEF") == 0);
}
When the time comes for counting higher, d[1] will be '\0' as it will have iterated beyond the set of digits and into the null terminator for the string. Let us consider adding code to handle our second iteration.
A bit of code is needed to set destination[length] back to the first digit and recursively move left onto the next digit. This occurs when d[1] == '\0', so we can write an if (...) { ... } branch to handle that.
There is a problem when length is passed in as 0, which we would discover after implementing the change mentioned just now. Here is where the function should return 1 to indicating that counting has finished, because it has moved as far left as possible and reached the highest number possible.
void count_r(char *destination, size_t length, char *digit) {
/* The position of the right-most digit is before the '\0' in destination, *
* so we need to decrement length */
if (length-- == 0) { return 1; }
/* Find the digit at the very end of destination, within our "digit" parameter */
char *d = strchr(digit, destination[length]);
/* d[1] points to the next digit (or '\0') */
if (d[1] == '\0') {
/* Set destination[length] to the first digit */
destination[length] = digit[0];
/* Recurse onto the next digit. We've already decremented length */
return count_r(destination, length, digit);
}
destination[length] = d[1];
return 0;
}
After adding a few assertions (eg. assert(strlen(digit) > 1);) and writing some testcases, we might then decide that this function is ready for production. I hope I was able to help. :)
Recursion is a programming technique that allows the programmer to express operations in terms of themselves. In C and C++ , this takes the form of a function that calls itself.
#include<iostream>
#include<cstdio>
using namespace std;
void rec(int val)
{
if(val<16)
{
printf("%u%u%u%u", val>>3, (val&4)>>2, (val&2)>>1, val&1);
printf("\n");
rec(++val); //calling val+1 here
}
return;
}
int main()
{
rec(0); //calling recursion for 0
}
This gives you exact output you want..!
If you don't want to use bit shift operators ..
#include<iostream>
#include<cstdio>
using namespace std;
void rec(int val)
{
if(val<16)
{
for(int b=val,a=8,i=0;i<4;b%=a,a/=2,i++)
printf("%u",(b/a));
printf("\n");
rec(++val);// calling val+1 here
}
return;
}
int main()
{
rec(0);//calling recursion for 0
}
This problem can be generalized to obtain binary combination of any length by using recursion. For example, if you want to get all binary combinations of length=4, just call printBinaryCombination("????", 0) (i.e. four ?s need to replaced with 0 or 1).
The corresponding code is as follows:
void printBinaryCombination(string str, int current)
{
int length = str.length();
if (length == 0)
return;
if (current == length)
printf("%s\n", str.c_str());
else
{
if (str[current] == '?')
{
str[current] = '0';
printBinaryCombination(str, current+1);
str[current] = '1';
printBinaryCombination(str, current+1);
// change back for next time
str[current] = '?';
}
else
printBinaryCombination(str, current+1);
}
}
EDIT: Actually, the above function is also powerful to handle all binary combinations that contains random number of ?s, each of which can be 0 or 1. For example, if you call printBinaryCombination("1??0", 0), it will print:
1000
1010
1100
1110
To generate n bit combination you asked for(you asked for n=4)
general recursive implementation for any n would be:
Main function:
vector<string> ve,ve1;
int main(int argc, char const *argv[])
{
/* code */
int n;
cin>>n;
generate("0",n,true);
generate("1",n,false);
for(int i=0;i<ve.size();i++){
cout<<ve[i]<<endl;
}
for(int i=0;i<ve1.size();i++){
cout<<ve1[i]<<endl;
}
return 0;
}
Generate function which recursively generates the binary strings:
void generate(string s,int n,bool b){
if(n==1){
if(b==true){
ve.push_back(s);
}
else{
ve1.push_back(s);
}
return;
}else{
generate(s+"0",n-1,b);
generate(s+"1",n-1,b);
}
}
Hope this helps..
SOLN 1: a more generalized answer(compilable under c90, c99). booleans being output as int.
Limitations :
1) uses math library.(its heavier so).
#include<stdio.h>
#include<math.h>
#define MAXBITS 4
//#define MAXVALUES (((int)pow(2,maxb))-1)
const int MAXVALUES = (((int)pow(2,maxb))-1) //if this gives warning then use #define version.
void bin(int val,int total)
{
int i = 0;
if(val <= MAXVALUES) //can write pow(2,total-1)-1 but anyways..
{
for(i =0 ; i < total;i++)
{
printf("%d",!!(val&(int)pow(2,total-i-1)));
}
printf("\n");
}
else return;
bin(val+1,total);
}
int main()
{
setbuf(stdout,NULL);
bin(0,MAXBITS);//4 bits
return 0;
}
Soln 2 :This can be done by char printing. no shift operator.
limitation(s) :
1) it can print(correctly) only upto 15(dec) or 0x0F(hex) values.
2) a total of
(5 * sizeof(char) * total) + (( total + 2) * (sizeof(int) + sizeof(int))) created on stack(so wasteful).
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAXVALUES 15
#define MAXBITS 4
void bin(int val,int total) //#prototype void bin(int val);remove redundant total.
{
char *s = malloc(sizeof(char)*(total+1)); //cant declare variable array(atleast pre c99)
int i = 0;
if(val <= MAXVALUES )
{
for(i =0 ; i < total;i++)
{
s[total - i-1] = !!(val&(int)pow(2,i)) + '0';
}
s[total] = '\0';
printf("%s\n",s);
}
else return;
bin(val+1,total);
}
int main()
{
bin(0,MAXBITS);//4 bits
return 0;
}
This general purpose c++ code works for any number of bits. just change const int num to any number of bits you want to generate binary code of...
const int num=3;
string code="";
void GenerateBinaryCode(string str,unsigned int n){
if(n==0){
cout<<str<<endl;
}
else{
str[num-n]='0';
GenerateBinaryCode(str, n-1);
str[num-n]='1';
GenerateBinaryCode(str, n-1);
}
}
int main(){
for(int i=0; i<num; i++)
code+="x";
GenerateBinaryCode(code,num);
}
Here's a recursive implementation in C using only an int 2D array (no strings, chars or bitshifting) for arbitrary bit lengths.
static void btable(int* a, int i, int n, int k, size_t len) {
if (k >= len)
return;
for (int j = (i+n)/2; j < n; j++)
*(a+j*len+k) = 1;
btable(a,i,(i+n)/2,k+1,len);
btable(a,(i+n)/2,n,k+1,len);
}
Then you can call the function with
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main(void) {
int n = 4;
int (*a)[n] = malloc(sizeof(int[(int)pow(2,n)][n]));
btable(*a,0,pow(2,n),0,n);
for (int i = 0; i < pow(2,n); i++) { // verify output
for (int j = 0; j < n; j++)
printf("%d",a[i][j]);
printf("\n");
}
return 0;
}
Before to present the final solution, I'll show two functions that we can use for our goal.
The main idea of the next function is to add the elements of the l1 list to each list that is contained in l2. For example:
l1 = [0]
l2 = [ [1,1] , [1,0] ]
then
f1(l1,l2) = [ [0,1,1] ,[0,1,0]]
def f1(l1:List[Int],l2:List[List[Int]]): List[List[Int]] = l2.map{ r=> l1:::r}
The first parameter is a list that contains a list of integers that will be added to each list of numbers contained in the l2 list. For example:
l1 = [ [0] , [1]]
l2 = [ [1,0], [1,1] ]
f(l1,l2) = [ [0,1,0],[0,1,1], [1,1,0],[1,1,1] ]
def f(l1:List[List[Int]],l2:List[List[Int]]): List[List[Int]] = l1.map{ r=> f1(r,l2)} flatten
Now, that we have the auxiliary methods, we create the function that will solve the requirement
/**
n : The max number of digits that the binary number can contain
*/
def binaryNumbers(n:Int):List[List[Int]] = n match {
case 1 => List(List(0),List(1))
case _ => f( List(List(0),List(1)) , binaryNumbers(n-1) )
}
Example: binaryNumbers(2) = List( List(0,0), List(0,1), List(1,0), List(1,1) )