Every nth image with remainder offset for next loop - javascript

I have two values that indicate how many results to parse from some data and which nth item I want to target. In this case, it's making every nth item a large image where as the rest are normal size. Here's what I need the loop to do:
First image must be large, or have the option to turn on
Get the remainder of normal size images at the end
Use this remainder so that the next iteration over the data has the correct starting point before the next large image appears.
I got very close but my modulus is wrong or how i'm doing the checking.
var i = 0,
len = productsObj.products.length;
for (i; i < len; i++) {
if ((i + this.nthProductImageOffset) % NTH_PRODUCT_IS_LARGE_TILE === 0) {
productsObj.products[i].PhotoSize = 'large';
} else {
productsObj.products[i].PhotoSize = 'medium';
}
}
// Store the remainder of medium tiles, if any, to be calculated
// against the next set of products to be appended.
this.nthProductImageOffset = i % NTH_PRODUCT_IS_LARGE_TILE;
So, if my two initial values were:
NTH_PRODUCT_IS_LARGE_TILE = 7
productsObj.products.length = 30
First image is large, then every 7th image is large. If we are left with a remainder of 2 medium images at the end of the loop, that needs to be accounted for the next time we run the loop before another large image appears. This way, regardless of the nth number or the number of iterations, we will always have the correct number of medium tiles in between the large ones.

The problem with the code above appears to be your use of the offset. You need to update the offset to the modulus of i + your previous offset. Not just i.
For example:
this.nthProductImageOffset = (i + this.nthProductImageOffset) % NTH_PRODUCT_IS_LARGE_TILE;
Here's a visual jsFiddle example though: https://jsfiddle.net/kwandrews7/6jxsu91y/1/
Every time you click the run button 5 elements will be added to the list. The 7th element will always be LARGE while others will be MEDIUM. Best of luck.
html:
<button id="run">Run</button>
<ol id="list">
</ol>
javascript:
var btnAdd = document.getElementById('run');
btnAdd.addEventListener("click", addElement, false);
var offset = 0
function addElement() {
var olList = document.getElementById('list');
var newListItem = document.createElement('li');
newListItem.innerText = 'New Item';
var len = 5;
var mod = 7;
for (var i=0; i<len; i++) {
var iOffset = i + offset;
if ( iOffset % mod === 0) {
var newListItem = document.createElement('li');
newListItem.innerText = "LARGE: i(" + i + "), offset(" + offset + "), iOffset(" + iOffset + ")";
olList.appendChild(newListItem);
} else {
var newListItem = document.createElement('li');
newListItem.innerText = "MEDIUM: i(" + i + "), offset(" + offset + "), iOffset(" + iOffset + ")";
olList.appendChild(newListItem);
}
}
offset = (i+offset) % mod
}

Try this:
var j = 0;
function run(list) {
for(var i = 0; i < list.length; i++) {
if(j % 7 === 0) {
console.log(list[i] + ' large');
}
else {
console.log(list[i] + ' medium');
}
j += 1;
}
}
run([1, 2, 3]);
run([4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
run([16, 17, 18]);
You use j to track the whole number of items in all of your lists and check that against NTH_PRODUCT_IS_LARGE_TILE so that you don't have to care about list.length.
http://jsfiddle.net/nx3jswyk/
Output:
1 large
2 medium
3 medium
4 medium
5 medium
6 medium
7 medium
8 large
9 medium
10 medium
11 medium
12 medium
13 medium
14 medium
15 large
16 medium
17 medium
18 medium

Ok so I tried your Code and it works only if you initialize nthProductImageOffset. Just add
nthProductImageOffset = 0;
to the beginning of your Code and you should be good to go

Related

Printing 2d array in javascript

Like the picture above, how would it be possible to create four separate lines of text, given the word defendtheeastwallofthecastle while using Javascript?
Math solution
Take a closer look at your output:
a.....g.....m.....s.
.b...f.h...l.n...r.t
..c.e...i.k...o.q...
...d.....j.....p....
Note that it can be splitted into similiar repeating blocks:
a..... g..... m..... s.
.b...f .h...l .n...r .t
..c.e. ..i.k. ..o.q. ..
...d.. ...j.. ...p.. ..
The length of this blocks is calculable: every row, except for the first one and the last one, has 2 letters. The total length will be: rows * 2 - 2. Let's call it blockLength. By the way, x * 2 - 2 is always even - it is important.
Now, you can see that in every block the letters are "sinking" in the left half, and arising in the second one. So, if you make some observations and analysis, you will understand that for blockLength == 6 you need to output letters at i:
row | i % blockLength
----------------------------
0 | 0
1 | 1, blockLength - 1
2 | 2, blockLength - 2
3 | 3
After i exceeds blockLength, it will repeat again and again, until the end of the string. This regularity can be easily converted to a JavaScript loop, if you know its basics.
Lazy solution
Within a loop set values in zig-zag order:
var str = 'abcdefghijklmopqrst';
var rows = 4, letterRows = [], currentRow = 0, direction = 1;
for (var i = 0; i < str.length; i++)
{
letterRows.push(currentRow);
currentRow += direction;
if ((direction === 1 && currentRow == rows - 1) // bottom limit
|| (direction === -1 && currentRow == 0)) // top limit
{
direction = direction * -1; // invert direction
}
}
Then, within nested loops simply output your letters according to letterRows:
for (var row = 0; row < rows; row++)
{
for (var i = 0; i < str.length; i++)
{
output(letterRows[i] == row ? str[i] : '.'); // output is any possible output in your case
}
output('\n');
}

When number reaches every nth value inside nested loop

Purpose: A user can choose a Product Type and variation of that Product Type. I need to track every Product Type added and how many variations were added. For Example,
item 1: Shirt > Long Sleeve (1)
item 2: Shirt > V neck (3)
item 3: Pants > Jeans (1)
The total amount pertains to the variation of the product. I'd like to have something happen whenever a user selects 4th variation of the same type. For this example, I want something to happen to the Product type Shirt, as currently long sleeve + v neck = 4
I have two nested loops. First one is looping through each product type, and inner loop should loop through each variation and get the sum.
This is a good starting point but I can't seem to get passed the for loop to check for every nth value of the total # of variations.
jQuery('.product').each(function(i, objP){
var sum = 0,
min = 4,
max = 5;
jQuery(objP).find('.product-variation-quantity').each(function(ii, objC){
sum += parseInt(jQuery(objC).text());
return sum;
for ( var x = 0; x < min * max; x += min) {
if ( sum == x ) {
var sum_id = jQuery(objP).attr('id');
console.log(sum_id);
//product quantity has reached min to pass
}
else {
//has not reached min
}
}
});
});
Any help?
note: objP and objC are used to track the contextual this
note2: to clarify: on every 4th, 8th, 12th etc value, something will happen, not every 4th, 5th, 6th
First of all, you have a bug in your code, it's where you return sum; in the nested loop. The for loop after this will never execute.
I suggest this code:
jQuery('.product').each(function(i, objP){
var sum = 0,
min = 4,
max = 5;
var ind = 1;
jQuery(objP).find('.product-variation-quantity').each(function(ii, objC){
sum = parseInt(jQuery(objC).text());
if (sum > 0 && sum % 4 == 0) {
// Do something
}
});
});
Here's codepen sample.
What about this: in case 8 items of the same variation are selected, the console will read
[id] has crossed 2x4 items
Code:
jQuery('.product').each(function(i, objP){
var min = 4,
max = 5,
sum_id;
jQuery(objP).find('.product-variation-quantity').each(function(ii, objC){
var count = parseInt(jQuery(objC).text());
if ( count < min ) {
//product quantity has not reached min
}
else {
// product quantity has reached min to pass
sum_id = jQuery(objP).attr('id');
console.log(sum_id + ' has crossed ' + min + 'x'
+ Math.floor(count/min) + ' items');
}
});
});

find all possible combinations of N non-repeating numbers within a certain range that add up to X

i have been trying to find a solution to this for several months now. it is for an art project of mine. so far i could find partial python and c solutions, but they are of no use for my case... i need a working solution either in PHP or Javascript.
this is the question:
find all possible combinations of N numbers, the following should be satisfied:
numbers are not repeated within a combination
numbers are not repeated in other solutions in different order
only whole numbers are being used
within a certain range of whole numbers
that add up to X
for example:
find all combinations of 3 numbers
within all numbers from 1-12
that add up to 15
the computed solution should spit out:
[1,2,12]
[1,3,11]
[1,4,10]
[1,5,9]
[1,6,8]
[1,7,7] = EXAMPLE OF WRONG OUTPUT, NO REPEATING NUMBERS WITHIN COMBINATION
[1,8,6] = EXAMPLE OF WRONG OUTPUT, NO REPEATING NUMBERS IN OTHER SOLUTIONS (see [1,6,8])
[2,3,10]
[2,4,9]
[2,5,8]
[2,6,7]
[3,4,8]
[3,5,7]
[4,5,6]
obviously that was easy to do in a couple of minutes by hand, but i need to calculate a much bigger range and much more numbers, so i need a short script to do this for me...
any help would be appreciated!
I feel like the most elegant way to handle this challenge is via recursion.
function getCombos(target, min, max, n) {
var arrs = [];
if (n === 1 && target <= max) {
arrs.push([target]);
} else {
for (var i = min; i < target / n && i <= max; i++) {
var arrays = getCombos(target - i, i + 1, max, n - 1);
for (var j = 0; j < arrays.length; j++) {
var array = arrays[j];
array.splice(0, 0, i);
arrs.push(array);
}
}
}
return arrs;
}
Explanation
This works by climbing up from the minimum number i as the first item in each array, and passing the remainder (target-i) back into the recursive function to be split into n-1 components, with the minimum increased by one with each recursive call.
15 = (1 + 14) = 1 + (2 + 12)
15 = (1 + 14) = 1 + (3 + 11)
15 = (1 + 14) = 1 + (4 + 10)
...
15 = (1 + 14) = 1 + (6 + 8)
15 = (2 + 13) = 2 + (3 + 10)
15 = (2 + 13) = 2 + (4 + 9)
...
15 = (4 + 11) = 4 + (5 + 6)
Note that the numbers at the first index of each array will never exceed target/n, where target is the number you're summing to, and n is the number of items in the array. (So when splitting 15 into 3 components, the first column will always be less than 5.) This holds true for the other columns as well, but n is reduced by 1 as the index of the array climbs. Knowing this allows us to recurse without requiring extra parameters on our recursive function.
Working Example
Check out the snippet below to see it in action.
function getCombos(target, min, max, n) {
var arrs = [];
if (n === 1 && target <= max) {
arrs.push([target]);
} else {
for (var i = min; i < target / n && i <= max; i++) {
var nextTarget = target - i;
var nextMin = i + 1;
var arrays = getCombos(nextTarget, nextMin, max, n - 1);
for (var j = 0; j < arrays.length; j++) {
var array = arrays[j];
array.splice(0, 0, i);
arrs.push(array);
}
}
}
return arrs;
}
document.getElementById("submit").onclick = function () {
var target = document.getElementById("target").value;
var min = document.getElementById("min").value;
var max = document.getElementById("max").value;
var n = document.getElementById("n").value;
var result = getCombos(+target, +min, +max, +n);
document.getElementById("output").innerHTML = result.join("<br/>");
};
.table {
display:table;
table-layout:fixed;
width:100%;
}
.table-row {
display:table-row;
}
.cell {
display:table-cell;
}
<div class="table">
<div class="table-row">
<div class="cell">Target:</div>
<div class="cell">
<input id="target" type="text" value=15>
</div>
<div class="cell">n:</div>
<div class="cell">
<input id="n" type="text" value=3>
</div>
</div>
<div class="table-row">
<div class="cell">Min:</div>
<div class="cell">
<input id="min" type="text" value=1>
</div>
<div class="cell">Max:</div>
<div class="cell">
<input id="max" type="text" value=12>
</div>
</div>
</div>
<input id="submit" type="button" value="submit" />
<div id="output" />
If you generate the lists in ascending order, you will avoid both kinds of repetition.
An easy recursive solution consists of selecting each possible first element, and then recursively calling the generator requesting the possible continuations: that is, the continuations are restricted to having one fewer element, to starting with a value greater than the chosen element, and summing to the desired sum minus the chosen element.
Partitions(min, size, total):
if size is 1:
if total < min: return nothing
else return the list [total]
for each value i between min and total:
get the set of lists Partitions(i+1, size-1, total-i)
add i to the beginning of each list
return all the lists.
The above can be improved by not letting i get beyond the largest practical value, or at least beyond a conservative estimate. Alternatively, you can stop incrementing i after a recursive call returns an empty set.
Below is a recursive function that does what you want.
For your example, you would call it like this:
combos(3, 1, 12, 15);
The additional function parameters (a, running, current) keep track of the current state and can be ignored:
var arr= [];
function combos(num, min, max, sum, a, running, current) {
var i;
a= a || [];
running= running || 0;
current= current || min;
for(i = current ; i <= max ; i++) {
if(num===1) {
if(i+running===sum) {
arr.push(a.concat(i));
}
}
else {
combos(num-1, min, max, sum, a.concat(i), i+running, i+1);
}
}
};
Fiddle
Here's a slightly optimized solution. By iterating from largest to smallest in the range, it becomes pretty easy to skip all the possibilities that are too large.
function combos(size, start, end, total, solution) {
var solutions = [];
solution = solution || [];
if (size === 1) {
if (start <= total && end >= total) {
solutions.push(solution.concat([total]));
}
return solutions;
} else {
while (end > start) {
var newTotal = total - end;
solutions = solutions.concat(
combos(
size - 1,
start,
Math.min(end - 1, newTotal),
newTotal,
solution.concat([end])
)
);
end--;
}
return solutions;
}
}
Might not be efficient for large numbers, but using 3 nested for() loops you can do -
$t=20; // up to X
$s=$t-3; // sets inner loop max
$r=$t/3; // sets middle loop max
$q=$r-1; // sets outer loop max
$results= array(); // array to hold results
for($x=1;$x<=$q;$x++){
for($y=($x+1);$y<=$r;$y++){
for($z=($x+2);$z<=$s;$z++){
// if sum == max && none are the same value
if(($x+$y+$z)==$t && ($x!=$y && $x!=$z && $y!=$z)){
$results[]=array($x,$y,$z);
}
}
}
}

Solving Linear Equations & similar Algebra Problems with JavaScript

I'm new to JavaScript and I am trying to write a simple script that solves linear equations. So far my script solves linear equations that are plus and minus only such as "2x + 28 - 18x = 36 - 4x + 10". I want it to also be able to solve linear equations/algebra problems that contain multiplication and division such as "2x * 3x = 4 / 2x".
I kind of have an idea of what to do next but I think the script I have right now maybe overly complex and it's only going to make it more complicated to add the multiplication and division.
Below is my script. I'm hoping for a few pointers on how I could improve and simplify what I already have and what the best way to add multiplication and division?
My script on JS Bin: http://jsbin.com/ufekug/1/edit
My script:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Problem Solver</title>
<script>
window.onload = function() {
// Total Xs on each side of equation
// Example problem: 5x + 2 = 10 - 2x
var leftSideXTotal = 0; // 5
var rightSideXTotal = 0; // -2
// Total integers on each side of equation
// Example problem: 5x + 2 = 10 - 2x
var leftSideIntTotal = 0; // 2
var rightSideIntTotal = 0; // 10
// Enter a math problem to solve
var problem = "5x + 2 = 10 - 2x";
// Remove all spaces in problem
// Example problem: 5x + 2 = 10 - 2x
problem = problem.replace(/\s/g,''); // 5x+2=10-2x
// Add + signs in front of all - signs
// Example problem: 5x + 2 = 10 - 2x
problem = problem.replace(/-/gi, "+-"); // 5x+2=10+-2x
// Split problem into left and right sides
// Example problem: 5x + 2 = 10 - 2x
var problemArray = problem.split("=");
var problemLeftSide = problemArray[0]; // 5x+2
var problemRightSide = problemArray[1]; // 10+-2x
// Split values on each side into an array
var problemLeftSideValues = problemLeftSide.split("+");
var problemRightSideValues = problemRightSide.split("+");
// Go through the left side values and add them up
for (var i = 0; i < problemLeftSideValues.length; i++) {
// Current value
var currentValue = problemLeftSideValues[i];
// Length of current value
var currentValueLength = currentValue.length;
if (currentValue.charAt(currentValueLength - 1) == "x") { //Check if current value is a X value
// Remove X from end of current value
currentValue = currentValue.split("x");
// Add to total Xs on left side
leftSideXTotal = Number(leftSideXTotal) + Number(currentValue[0]);
} else {
// Add to total integers on left side
leftSideIntTotal = Number(leftSideIntTotal) + Number(problemLeftSideValues[i]);
}
}
// Go through the right side values and add them up
for (var i = 0; i < problemRightSideValues.length; i++) {
// Current value
var currentValue = problemRightSideValues[i];
// Length of current value
var currentValueLength = currentValue.length;
if (currentValue.charAt(currentValueLength - 1) == "x") { //Check if current value is a X value
// Remove X from end of current value
currentValue = currentValue.split("x");
// Add to total Xs on right side
rightSideXTotal = Number(rightSideXTotal) + Number(currentValue[0]);
} else {
// Add to total integers on right side
rightSideIntTotal = Number(rightSideIntTotal) + Number(problemRightSideValues[i]);
}
}
// Compute
var totalXs = (leftSideXTotal - rightSideXTotal)
var totalIntegers = (rightSideIntTotal - leftSideIntTotal)
var solution = (totalIntegers / totalXs)
// Display solution
document.getElementById("divSolution").innerText = solution;
}
</script>
</head>
<body>
<div id="divSolution"></div>
</body>
</html>
You need to write (or use) an operator-precedence parser.
The idea is to turn the equation into a tree, e.g.
x + 3 = 3x - 2
Is really the structure
=
/ \
+ -
/ \ / \
x 3 * 2
/ \
3 x
Where each operator describes an operation between two "branches" of the tree. Using a javascript object it shouldn't be difficult to create the structure:
function tree(lterm,op,rterm) {
t.operator = op;
t.left = lterm;
t.right = rterm;
return t;
}
expression = tree("x", "/", tree("x","+",3) ); // x / (x+3)
Then by manipulating the tree you can resolve the equation, or carry out calculations. To evaluate an expression (with no unknowns), you run through the tree starting at the terminals, and upwards from intersection to intersection. You can replace a section of the tree with a result, or annotate it with a result - add a result variable to the tree object.
Here are some useful methods to include in a tree class:
getLeft
getRight
prettyPrint
evaluate
evaluate("x",5) // x=5, now evaluate
...
It's not just linear operations that can be "parsed" this way. Better parsers will have a list of operators that includes =*/+- but also unary operators: - ( ) sin cos...
I haven't used an operator-precedence parser in javascript, but some must exist prewritten. Surely a kind soul on this site will add a good link or two to my answer.
BTW, the tree approach has many applications. In a spreadsheet:
A2 = A1+B1
In a boolean solver:
A = not (B or C)
C = true
In XML parsing:
<main>
<part>A</part>
<part>B</part>
</main>
I have defined two functions:
getTotalX() : It will give you the count of x for any input string.
getTotalScalars() : It will give you the total of scalars (numbers).
And finally, your updated code (it still does only addition and subtraction):
<script>
window.onload = function() {
// Total Xs on each side of equation
// Example problem: 5x + 2 = 10 - 2x
var leftSideXTotal = 0; // 5
var rightSideXTotal = 0; // -2
// Total integers on each side of equation
// Example problem: 5x + 2 = 10 - 2x
var leftSideIntTotal = 0; // 2
var rightSideIntTotal = 0; // 10
// Enter a math problem to solve
var problem = "5x + 2 = 10 - 2x";
// Remove all spaces in problem
// Example problem: 5x + 2 = 10 - 2x
problem = problem.replace(/\s/g,''); // 5x+2=10-2x
// Add + signs in front of all - signs
// Example problem: 5x + 2 = 10 - 2x
problem = problem.replace(/-/gi, "+-"); // 5x+2=10+-2x
// Split problem into left and right sides
// Example problem: 5x + 2 = 10 - 2x
var problemArray = problem.split("=");
var problemLeftSide = problemArray[0]; // 5x+2
var problemRightSide = problemArray[1]; // 10+-2x
leftSideXTotal = getTotalX(problemLeftSide);
leftSideIntTotal = getTotalScalars(problemLeftSide);
rightSideXTotal = getTotalX(problemRightSide);
rightSideIntTotal = getTotalScalars(problemRightSide);
// Compute
var totalXs = (leftSideXTotal - rightSideXTotal)
var totalIntegers = (rightSideIntTotal - leftSideIntTotal)
var solution = (totalIntegers / totalXs)
// Display solution
document.getElementById("divSolution").innerText = solution;
// Find the total number of X in the string
function getTotalX(data) {
data = data.replace(/\s/g,'');
xCount = 0;
if(data.indexOf('x') != -1) {
if (data.indexOf('+') != -1) {
data = data.split('+');
for(var i = 0; i < data.length; i++) {
xCount += getTotalX(data[i]);
}
} else if (data.indexOf('-') != -1) {
data = data.split('-');
// Single negative
if(data[0] == "") {
xCount -= getTotalX(data[1]);
} else {
xCount += getTotalX(data[0]);
for(var i = 1; i < data.length; i++) {
xCount -= getTotalX(data[i]);
}
}
} else {
xCount = parseInt(data.split('x')[0]);
}
}
return xCount;
}
// Find the total of scalars
function getTotalScalars(data) {
data = data.replace(/\s/g,'');
intCount = 0;
if (data.indexOf('+') != -1) {
data = data.split('+');
for(var i = 0; i < data.length; i++) {
intCount += getTotalScalars(data[i]);
}
} else if (data.indexOf('-') != -1) {
data = data.split('-');
// Single negative
if(data[0] == "") {
intCount -= getTotalScalars(data[1]);
} else {
intCount += getTotalScalars(data[0]);
for(var i = 1; i < data.length; i++) {
intCount -= getTotalScalars(data[i]);
}
}
} else {
if(data.indexOf('x') == -1) {
intCount = parseInt(data.split('x')[0]);
} else {
intCount = 0;
}
}
return intCount;
}
}
</script>

Generate all combinations for pair of bits set to 1?

I'm trying to generate all possible combinations for pair of 1's within given bit width.
Let's say the bit width is 6, i.e. number 32. This is what I would like to generate:
000000
000011
000110
001100
001111
011000
011011
011110
110000
110011
110110
111100
111111
If I have variables:
var a = 1,
b = 2;
num = a | b;
and create a loop that I'll loop over width - 1 times, and where I shift both a << 1 and b << 1, I'll get all combinations for one pair. After that, I'm pretty much stuck.
Could someone , please, provide some help.
Update: working example
Based on Barmar's mathematical approach, this is what I managed to implement
var arr = [],
arrBits = [];
function getCombs(pairs, startIdx) {
var i, j, val = 0, tmpVal, idx;
if (startIdx + 2 < pairs) {
startIdx = arr.length - 1;
pairs -= 1;
}
if (pairs < 2) {
return;
}
for (i = 0; i < pairs-1; i++) {
idx = startIdx - (i * 2);
val += arr[idx];
}
for (j = 0; j < idx - 1; j++) {
arrBits.push((val + arr[j]).toString(2));
}
getCombs(pairs, startIdx-1);
}
(function initArr(bits) {
var i, val, pairs, startIdx;
for (i = 1; i < bits; i++) {
val = i == 1 ? 3 : val * 2;
arr.push(val);
arrBits.push(val.toString(2));
}
pairs = Math.floor(bits / 2);
startIdx = arr.length - 1;
getCombs(pairs, startIdx);
console.log(arrBits);
}(9));
Working example on JSFiddle
http://jsfiddle.net/zywc5/
The numbers with exactly one pair of 1's are the sequence 3, 6, 12, 24, 48, ...; they start with 3 and just double each time.
The numbers with two pairs of 1's are 12+3, 24+3, 24+6, 48+3, 48+6, 48+12, ...; these are the above sequence starting at 12 + the original sequence up to n/4.
The numbers with three pairs of 1's are 48+12+3, 96+12+3, 96+24+3, 96+24+6, ...
The relationship between each of these suggests a recursive algorithm making use of the original doubling sequence. I don't have time right now to write it, but I think this should get you going.
if the bit width isn't that big then you'll be way better off creating bit representations for all numbers from 0 to 31 in a loop and simply ignore the ones that have an odd number of "ones" in the bit representation.
Maybe start counting normally in binary and replace all 1's with 11's like this:
n = 5
n = n.toString(2) //= "101"
n = n.replace(/1/g, "11") //= "11011"
n = parseInt(n, 2) //= 27
So you'll get:
0 -> 0
1 -> 11
10 -> 110
11 -> 1111
100 -> 1100
101 -> 11011
110 -> 11110
111 -> 111111
And so on. You'll have to count up to 31 or so on the left side, and reject ones longer than 6 bits on the right side.
See http://jsfiddle.net/SBH6R/
var len=6,
arr=[''];
for(var i=0;i<len;i++){
for(var j=0;j<arr.length;j++){
var k=j;
if(getNum1(arr[j])%2===1){
arr[j]+=1;
}else{
if(i<len-1){
arr.splice(j+1,0,arr[j]+1);
j++;
}
arr[k]+=0;
}
}
}
function getNum1(str){
var n=0;
for(var i=str.length-1;i>=0;i--){
if(str.substr(i,1)==='1'){n++;}
else{break;}
}
return n;
}
document.write(arr.join('<br />'));
Or maybe you will prefer http://jsfiddle.net/SBH6R/1/. It's simpler, but then you will have to sort() the array:
var len=6,
arr=[''];
for(var i=0;i<len;i++){
for(var k=0,l=arr.length;k<l;k++){
if(getNum1(arr[k])%2===1){
arr[k]+=1;
}else{
if(i<len-1){
arr.push(arr[k]+1);
}
arr[k]+=0;
}
}
}
function getNum1(str){
var n=0;
for(var i=str.length-1;i>=0;i--){
if(str.substr(i,1)==='1'){n++;}
else{break;}
}
return n;
}
document.write(arr.sort().join('<br />'));
See http://jsperf.com/generate-all-combinations-for-pair-of-bits-set-to-1 if you want to compare the performance. It seems that the fastest code is the first one on Chrome but the second one on Firefox.
You can also do this with bit twiddling. If the lowest two bits are zero, we need to set them, which is equivalent to adding 3. Otherwise, we need to replace the lowest block of ones by its top bit and a 1-bit to the left of it. This can be done as follows, where x is the current combination:
x3 = x + 3;
return (((x ^ x3) - 2) >> 2) + x3;

Categories

Resources