Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Building on <a href="https://stackoverflow.com/questions/2936205/number-algorithm/2936248#2936248">@Mark Byers's</a> and <a href="https://stackoverflow.com/questions/2936205/number-algorithm/2936367#2936367">Moron's</a> answers your task can be reformulated as follows:</p> <p>Enumerate all ways to put <code>K</code> zeros into <code>N</code> places (see <a href="http://en.wikipedia.org/wiki/Combination" rel="nofollow noreferrer">combinations with repetition</a> and <a href="http://en.wikipedia.org/wiki/Stars_and_bars_%28probability%29" rel="nofollow noreferrer">Stars and bars</a>).</p> <p>Example: For 15 bits and 1 2 6 1 pattern there are N=5 places (before/after the number and between <code>1</code>s) to put K=2 zeros (number of leading zeros for a flush-right number). Number of ways is <a href="http://en.wikipedia.org/wiki/Binomial_coefficient" rel="nofollow noreferrer">binomial</a>(N + K - 1, K) i.e., binomial(5+2-1, 2) = 15.</p> <p>The key functions in the code below are <a href="http://photon.poly.edu/~hbr/boost/combinations.html#next_combin_counts_desc" rel="nofollow noreferrer"><code>next_combination_counts()</code></a> and <code>comb2number()</code>.</p> <h3>Full program in C</h3> <pre><code>#include &lt;assert.h&gt; #include &lt;stdbool.h&gt; #include &lt;stdio.h&gt; #define SIZE(arr) (sizeof(arr)/sizeof(*(arr))) #define PRInumber "u" typedef unsigned number_t; // swap values pointed to by the pointer static void iter_swap(int* ia, int* ib) { int t = *ia; *ia = *ib; *ib = t; } // see boost::next_combinations_counts() // http://photon.poly.edu/~hbr/boost/combinations.html // http://photon.poly.edu/~hbr/boost/combination.hpp static bool next_combination_counts(int* first, int* last) { /* 0 0 2 0 1 1 0 2 0 1 0 1 1 1 0 2 0 0 */ int* current = last; while (current != first &amp;&amp; *(--current) == 0) { } if (current == first) { if (first != last &amp;&amp; *first != 0) iter_swap(--last, first); return false; } --(*current); iter_swap(--last, current); ++(*(--current)); return true; } // convert combination and pattern to corresponding number // example: comb=[2, 0, 0] pattern=[1,1] =&gt; num=5 (101 binary) static number_t comb2number(int comb[], int comb_size, int pattern[], int pattern_size) { if (pattern_size == 0) return 0; assert(pattern_size &gt; 0); assert(comb_size &gt; pattern_size); // 111 -&gt; 1000 - 1 -&gt; 2**3 - 1 -&gt; (1 &lt;&lt; 3) - 1 // 111 &lt;&lt; 2 -&gt; 11100 number_t num = ((1 &lt;&lt; pattern[pattern_size-1]) - 1) &lt;&lt; comb[pattern_size]; int len = pattern[pattern_size-1] + comb[pattern_size]; for (int i = pattern_size - 1; i--&gt; 0; ) { num += ((1 &lt;&lt; pattern[i]) - 1) &lt;&lt; (comb[i+1] + 1 + len); len += pattern[i] + comb[i+1] + 1; } return num; } // print binary representation of number static void print_binary(number_t number) { if (number &gt; 0) { print_binary(number &gt;&gt; 1); printf("%d", number &amp; 1); } } // print array static void printa(int arr[], int size, const char* suffix) { printf("%s", "{"); for (int i = 0; i &lt; (size - 1); ++i) printf("%d, ", arr[i]); if (size &gt; 0) printf("%d", arr[size - 1]); printf("}%s", suffix); } static void fill0(int* first, int* last) { for ( ; first != last; ++first) *first = 0; } // generate {0,0,...,0,nzeros} combination static void init_comb(int comb[], int comb_size, int nzeros) { fill0(comb, comb + comb_size); comb[comb_size-1] = nzeros; } static int sum(int* first, int* last) { int s = 0; for ( ; first != last; ++first) s += *first; return s; } // calculated max width required to print number (in PRInumber format) static int maxwidth(int comb[], int comb_size, int pattern[], int pattern_size) { int initial_comb[comb_size]; int nzeros = sum(comb, comb + comb_size); init_comb(initial_comb, comb_size, nzeros); return snprintf(NULL, 0, "%" PRInumber, comb2number(initial_comb, comb_size, pattern, pattern_size)); } static void process(int comb[], int comb_size, int pattern[], int pattern_size) { // print combination and pattern printa(comb, comb_size, " "); printa(pattern, pattern_size, " "); // print corresponding number for (int i = 0; i &lt; comb[0]; ++i) printf("%s", "0"); number_t number = comb2number(comb, comb_size, pattern, pattern_size); print_binary(number); const int width = maxwidth(comb, comb_size, pattern, pattern_size); printf(" %*" PRInumber "\n", width, number); } // reverse the array static void reverse(int a[], int n) { for (int i = 0, j = n - 1; i &lt; j; ++i, --j) iter_swap(a + i, a + j); } // convert number to pattern // 101101111110100 -&gt; 1, 2, 6, 1 static int number2pattern(number_t num, int pattern[], int nbits, int comb[]) { // SIZE(pattern) &gt;= nbits // SIZE(comb) &gt;= nbits + 1 fill0(pattern, pattern + nbits); fill0(comb, comb + nbits + 1); int i = 0; int pos = 0; for (; i &lt; nbits &amp;&amp; num; ++i) { // skip trailing zeros for ( ; num &amp;&amp; !(num &amp; 1); num &gt;&gt;= 1, ++pos) ++comb[i]; // count number of 1s for ( ; num &amp; 1; num &gt;&gt;=1, ++pos) ++pattern[i]; } assert(i == nbits || pattern[i] == 0); const int pattern_size = i; // skip comb[0] for (int j = 1; j &lt; pattern_size; ++j) --comb[j]; comb[pattern_size] = nbits - pos; reverse(pattern, pattern_size); reverse(comb, pattern_size+1); return pattern_size; } int main(void) { number_t num = 11769; const int nbits = 15; // clear hi bits (required for `comb2number() != num` relation) if (nbits &lt; 8*sizeof(number_t)) num &amp;= ((number_t)1 &lt;&lt; nbits) - 1; else assert(nbits == 8*sizeof(number_t)); // `pattern` defines how 1s are distributed in the number int pattern[nbits]; // `comb` defines how zeros are distributed int comb[nbits+1]; const int pattern_size = number2pattern(num, pattern, nbits, comb); const int comb_size = pattern_size + 1; // check consistency // . find number of leading zeros in a flush-right version int nzeros = nbits; for (int i = 0; i &lt; (pattern_size - 1); ++i) nzeros -= pattern[i] + 1; assert(pattern_size &gt; 0); nzeros -= pattern[pattern_size - 1]; assert(nzeros&gt;=0); // . the same but using combination int nzeros_comb = sum(comb, comb + comb_size); assert(nzeros_comb == nzeros); // enumerate all combinations printf("Combination Pattern Binary Decimal\n"); assert(comb2number(comb, comb_size, pattern, pattern_size) == num); process(comb, comb_size, pattern, pattern_size); // process `num` // . until flush-left number while(next_combination_counts(comb, comb + comb_size)) process(comb, comb_size, pattern, pattern_size); // . until `num` number is encounterd while (comb2number(comb, comb_size, pattern, pattern_size) != num) { process(comb, comb_size, pattern, pattern_size); (void)next_combination_counts(comb, comb + comb_size); } return 0; } </code></pre> <p>Output:</p> <pre><code>Combination Pattern Binary Decimal {1, 0, 0, 1, 0} {1, 2, 6, 1} 010110111111001 11769 {1, 0, 1, 0, 0} {1, 2, 6, 1} 010110011111101 11517 {1, 1, 0, 0, 0} {1, 2, 6, 1} 010011011111101 9981 {2, 0, 0, 0, 0} {1, 2, 6, 1} 001011011111101 5885 {0, 0, 0, 0, 2} {1, 2, 6, 1} 101101111110100 23540 {0, 0, 0, 1, 1} {1, 2, 6, 1} 101101111110010 23538 {0, 0, 0, 2, 0} {1, 2, 6, 1} 101101111110001 23537 {0, 0, 1, 0, 1} {1, 2, 6, 1} 101100111111010 23034 {0, 0, 1, 1, 0} {1, 2, 6, 1} 101100111111001 23033 {0, 0, 2, 0, 0} {1, 2, 6, 1} 101100011111101 22781 {0, 1, 0, 0, 1} {1, 2, 6, 1} 100110111111010 19962 {0, 1, 0, 1, 0} {1, 2, 6, 1} 100110111111001 19961 {0, 1, 1, 0, 0} {1, 2, 6, 1} 100110011111101 19709 {0, 2, 0, 0, 0} {1, 2, 6, 1} 100011011111101 18173 {1, 0, 0, 0, 1} {1, 2, 6, 1} 010110111111010 11770 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload