Combinations of a string double loop (JavaScript) - javascript

I'm trying to understand how to find all the combinations of a string using a double loop but the solution I've come across is too complicated for my understanding. The function does what I need but I have beginner understanding of setting up a single or double for loop.
I'm hoping for a general step by step explanation of what is going on but for specific questions: what functions are "i < Math.pow(2,n)-1", "((i & (1 << j)) == 1 << j)", and "var comb = ''; (temporary storage?)" serving?
subsets = function(str) {
var n = str.length;
for (var i=1; i< Math.pow(2,n)-1; i++) {
var comb = '';
for (var j=0; j<n; j++) {
var use = ((i & (1 << j)) == 1 << j);
if(use)comb+=str.charAt(j);
}
console.log(comb);
}
}
subsets("age");
Output: a ag ae g ge e

To get a random combination of the string, we could set up a boolean array, storing if one of the characters should be displayed or not, e.g:
"a","g","e"
[true,false,true]
=>"ae"
So the number of possible variations is
2 /*true/false*/ ** str.length
written in old style:
Math.pow(2,str.length)
So the main for loop iterates over all possible combinatons except the first one (as i starts with 1),as that would be an empty string and the last one (-1) that would be "age". While i is an integer which simply counts up, we could also imagine that its a boolean array (in a bitwise view):
integer
bits
boolean array
1
001
[false,false,true]
2
010
[false,true,false]
3
011
[false,true,true]
4
100
[true,false,false]
...
6 < 2 ** 3 -1
110
[true,true,false]
Now the inner loop:
for (var j=0; j<n; j++) {
var use = ((i & (1 << j)) == 1 << j);
if(use)comb+=str.charAt(j);
}
Just goes over our letters and checks if the boolean flag is true, so at i = 5 the boolean array would be:
[true,false,true]//101
and that is converted to
"ae"
How it looks bitwise:
A true one ("a"):
101 // i
&001 //1<<j where j is 0
=001
===
001 //1<<j
A false one ("g"):
101
&010 //1<<j where j is 1
=000
!==
010 //1<<j
A true one ("e"):
101 // i
&100 //1<<j where j is 2
=100
===
100 //1<<j
So it checks if the boolean array (i) is true at js index, if so it adds that letter. BTW shorter:
if(i & (1<<j))

var i=1; i< Math.pow(2,n)-1; i++
What the Math.pow(2, n) - 1 is saying is run this loop until (2^n)-1, where 'n' is the length of the string. So with the input 'age', the first for loop will run while i, starting at 1 and incrementing by 1 each loop, is less than (2^3)-1. Therefore, this first loop will run 6 times.
var comb = ''
Is exactly what you think it is - storage for what to log that populates as the for loops do their thing!
As for (i & (1 << j)) == 1 << j), that's where we get into Bitwise operators! Unfortunately, I don't understand these nearly well enough to explain them :(

Math.pow is a power function. The first argument is the base, and the second argument is the exponent, so Math.pow(2, n) is equivalent to 2^n. In the loop, i< Math.pow(2,n) means the boundary of the for loop is while i is less than 2^n, where n is the string length.
var comb = ''; is initializing an empty string. This string is concatenated later in the loop so this declaration serves to establish that variable for concatenation.

It's a code based on binary (0/1)
operators in javascript explain << it's a "Shift a into binary representation of b bits to the left, by inserting zeros by the right"
and & : Returns a 1 for each bit position for which the corresponding bits of the two operands are 1.
If u had some problem to undestand a code, Try it on paper step by step with simple example.
Try example str = "a", after try "on" ...
For "a" the beginning is
var n = str.length; // 1
for (var i=1; i< Math.pow(2,n)-1; i++) { // for i=1;i<2^1-1 =2-1=1;i++
var comb = '';
for (var j=0; j<n; j++) {//for j=0;j<1;j++
var use = ((i & (1 << j)) == 1 << j);// use = 1 & (1 << 0 insert 0 times 0)) == 1 << 0= (1 & 1)== 1=true (1==1)
if(use)comb+=str.charAt(j);//comb='' + a.charAt(0)= comb= '' + "a"='a'
... You continue the loops.
binary is a method to write number with 0/1 :
Example 00101(binary)
U have 5 digits then the 1rst 0 = 0*2^(number of place of digit from right-1) = 0*2^4=0
Then 00101(binary) = 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 1*2^0
= 0 + 0 + 1*4 + 0 + 1*1
= 5 in current using (decimal)
U find lot of explanation on binary with Google

Related

Sum of Array of Odd numbers - JS

Given the triangle of consecutive odd numbers:
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
// Calculate the row sums of this triangle from the row index (starting at index 1) e.g.:
rowSumOddNumbers(1); // 1
rowSumOddNumbers(2); // 3 + 5 = 8
I tried to solve this using for loops:
function rowSumOddNumbers(n){
let result = [];
// generate the arrays of odd numbers
for(let i = 0; i < 30; i++){
// generate sub arrays by using another for loop
// and only pushing if the length is equal to current j
let sub = [];
for(let j = 1; j <= n; j++){
// if length === j (from 1 - n) keep pushing
if(sub[j - 1].length <= j){
// and if i is odd
if(i % 2 !== 0){
// push the i to sub (per length)
sub.push(i);
}
}
}
// push everything to the main array
result.push(sub);
}
// return sum of n
return result[n + 1].reduce(function(total, item){
return total += item;
});
}
My code above is not working. Basically I was planning to 1st generate an array of odd numbers less than 30. Next I need to create a sub array base on the length of iteration (j) that would from 1 - n (passed). Then finally push it to the main array. And then use reduce to get the sum of all the values in that index + 1 (since the index starts at 1).
Any idea what am I missing and how to make this work?
Most code problems involve some analysis first in order to spot patterns which you can then convert into code. Looking at the triangle, you'll see the sum of each row follows a pattern:
1: 1 === 1 ^ 3
2: 3 + 5 = 8 === 2 ^ 3
3: 7 + 9 + 11 = 27 === 3 ^ 3
... etc
So from the analysis above you can see that your code could probably be simplified slightly - I won't post an answer, but think about using Math.pow.
No need for any loops.
function rowSumOddNumbers(n) {
// how many numbers are there in the rows above n?
// sum of arithmetic sequence...
let numbers_before_n_count = (n - 1) * n / 2;
let first_number_in_nth_row = numbers_before_n_count * 2 + 1;
let last_number_in_nth_row = first_number_in_nth_row + 2 * (n - 1);
// sum of arithmetic sequence again...
return n * (first_number_in_nth_row + last_number_in_nth_row) / 2;
}

How to use result from a hash function to get an array index?

I am in the process of learning about bloom filters and I am looking through various hash functions in JavaScript.
For example I found this one in another Stack Overflow answer:
Found here https://stackoverflow.com/a/7616484/5217568)
String.prototype.hashCode = function() {
var hash = 0, i, chr, len;
if (this.length == 0) return hash;
for (i = 0, len = this.length; i < len; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
If I run:
String.prototype.call(null, "hello")
I get the numerical value of : 99162322
(two other hash functions got me: 1335831723, and 120092131).
Now If I create a hypothetical bloom filter with 3 hash functions, and 18 indices (k=3, m=18), How are these large values indexed in an array with indices from 0-17?
Use the remainder/modulo operator % to wrap a randomly-generated value within a certain bound.
If you have 18 elements (indices 0 to 17), you could get an index with 99162322 % 18 (16).
If the number of hash value is not a multiple of the number of indices, the result will be biased. For example, if your hash value is one of the five values from 0 to 4, but you were mapping it onto the three indices from 0 to 2, it would be biased towards 0 (0 % 3, 3 % 3) and 1 (1 % 3 or 4 % 3) over 2 (only 2 % 3). Depending on your needs, the bias may be acceptable if the number of hash values is sufficiently larger than the number of indices. If you want to to avoid it you'll need a scheme to generate a new hash input if the hash result is from the bias-inducing range. Something like this:
function hashIndex(string, length, hashValueCount) {
var minBiasedIndex = hashValueCount - (hashValueCount % length);
for (var i = 0; ; i++) {
var hashInput = string + ":" + String(i);
var hashResult = hash(hashInput);
if (hashResult < minBiasedIndex) {
return hashResult % length;
}
}
}

create all possible variations of a string with inserted character

I'm trying to take the variable email and create all possible combinations with a "." in it like so:
Results
andrew
andre.w
andr.ew
andr.e.w
and.rew
and.re.w
and.r.ew
and.r.e.w
an.drew
an.dre.w
an.dr.ew
an.dr.e.w
an.d.rew
an.d.re.w
an.d.r.ew
an.d.r.e.w
a.ndrew
a.ndre.w
a.ndr.ew
a.ndr.e.w
a.nd.rew
a.nd.re.w
a.nd.r.ew
a.nd.r.e.w
a.n.drew
a.n.dre.w
a.n.dr.ew
a.n.dr.e.w
a.n.d.rew
a.n.d.re.w
a.n.d.r.ew
a.n.d.r.e.w
I'm not sure how to do about doing this exactly. I know how to use a loop to go over each character, but as far as the rest goes I'm stumped. I was looking at substr, slice and few other functions but couldn't get anything working.
Code
var email = "andrew";
for (var i = 0; i < email.length; i++) {
console.log( email[i] + "." );
}
That's easy:
var str = 'andrew';
var results = [],
bin;
for (var i = 0; i < Math.pow(2, str.length - 1); ++i) {
bin = i.toString(2).split('').reverse().join('');
results.push(str.replace(/./g, function(letter, index) {
if (bin.charAt(index) == 1) {
letter += '.';
}
return letter;
}));
}
console.log(results);
Demo: http://jsfiddle.net/9qLY6/
Short description:
For 'abc' string there are 2 positions for a dot character: between a and b; b and c. These 2 positions might be presented as a digits of a binary number. All the possible combinations in this case are:
00
01
10
11
If you treat 1 as - . there, and 0 as no . there - you can just iterate over 2^(n-1) numbers and put . if the corresponding bit is set.
If you're interested in a recursive solution like Dinesh mentioned, here's some code to get you started.
function withPeriods(str, prev) {
prev = prev || '';
if(!str || str.length == 0) {
return prev ? [prev] : [];
} else if(str.length == 1) {
return [prev + str];
} else {
var c = str.charAt(0);
var newStr = str.slice(1);
return withPeriods(newStr, prev+c).concat(withPeriods(newStr, prev+c+'.'));
}
}
The idea here is that you are working your way through the string, keeping the current result in the 'prev' variable. If the string is length 0 or 1, there's nothing left to do. Otherwise, you need consider two options: one where you take a character from 'str' and add it to 'prev', and one where you do that but also add a '.'
If you think about it, you need to either insert a dot, or not insert one, at every possible location in the string (between any two characters). A funky way to do this is to realize that if you have n characters, there are n-1 places. If you wrote the combinations of period = 1 and no period = 0, then you can write all possible solutions as a 2^n-1 binary sequence. Showing this for a four letter word "word":
000 word
001 wor.d
010 wo.rd
011 wo.r.d
100 w.ord
101 w.or.d
110 w.o.rd
111 w.o.r.d
In pseudo code (can't test JS syntax right now):
n = strlen( email );
combinations = 1 << n - 1; // left shift operation
for i = 0 to combinations - 1:
dot = 1
for j = 0 to n:
print email[j];
if dot & i:
print '.'
dot << 1;
Can you take it from here?
You might take a recursive approach to this problem. Maybe you can use the base case as a string with 2 characters.

Coderbyte Array Addition Solution -- For Loop with a For Loop

I'm trying to understand the logic in a solution to the Array Addition CoderByte problem. Here is the question prompt -- "Using the JavaScript language, have the function ArrayAdditionI(arr) take the array of numbers stored in arr and return the string true if any combination of numbers in the array can be added up to equal the largest number in the array, otherwise return the string false. For example: if arr contains [4, 6, 23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 = 23. The array will not be empty, will not contain all the same elements, and may contain negative numbers."
This is a solution that works, but I get lost with the for loop within the for loop. Why isn't it always the case that i = j since the for loops both start with their counters at 0. So wouldn't it always be 0 = 0?
function ArrayAdditionI(arr) {
arr.sort(function(a,b){return a - b})
var largest = arr.pop();
var sum = 0;
for (var i = 0; i < arr.length; i++){
sum += arr[i];
for (var j = 0; j < arr.length; j++){
if (i != j) {
sum += arr[j];
if (sum == largest) {
return true;
}
}
}
for (var k = 0; k < arr.length; k++) {
if (i != k) {
sum -= arr[k];
if (sum == largest) {
return true;
}
}
}
sum = 0;
}
// code goes here
return false;
}
Thanks!
i_made_that & user3085131:
To further explain the k loop, it is used to work back through and subtract array values in the order that they were initially added, to yield new results not otherwise obtainable.
Without the k loop you can't solve many potential arrays (although it will actually pass the coderbyte test cases due to lack of appropriate test).
Consider [1,2,3,98,100]...this should pass since 2+98 = 100. However it won't without the k loop. If you log the results of sum without the k, you would see:
3 (1 + 2)
6 (3 + 3)
104 (6 + 98)
3 (2 + 1)
6 (3 + 3)
104 (6 + 98)
4 (3 + 1)
6 (4 + 2)
104 (6 + 98)
99 (98 + 1)
101 (99 + 2)
104 (101 + 3)
With the k loop however, on the second iteration of i it will pass as it will subtract 1 from 104, and then 3 from 103 to reach 100.
The thing is, is that you have 2 for loops inside the for loop with the "i" variable.
variable "i" is always going to be 0 until you finish iterating thru the 2 for loops that are inside.
for(var i=0){
for(var j=0){}
for(var k=0){}
}

How to use unit8array in javascript?

Accorting to this answer's comment, I would like to use Unit8Array to achieve the same thing:
var bin = parseInt('1000', 2); //=8
I mean:
inputs are:
length = 4
digits = [1,0,0,0]
and after some TypedArray magic the output will be:
8
Lets see a concrete example with (2 bits length):
counts = {};
var a = [[0,1],[0,0],[0,1],[0,0],[0,0],[1,1]];
for(var i in a){
var id = parseInt(a[i].join(''), 2);
if(!++counts[id])counts[id] = 1;
}
console.log(counts); //{0: 3, 1: 2, 3: 1}
my notes are here.
If you want more speed, handle allready the ids as integers, not array, and have bit changed with & and | operations :
counts = {};
var a = [1,0,1,0,0,3];
for(var i=0; i<a.length; i++ ){
var c = counts[a[i]] || 0 ;
counts[a[i]]= c+1 ;
}
console.log(counts); // { 0: 3, 1: 2, 3: 1 }
to set the k-th bit :
id |= 1 << k;
to clear the k-th bit :
id &= !(1 << k);
to swap the k-th bit :
id ^= (1 << k);
to read the k-th bit :
bitK = (id >> k ) & 1;
So you might write small functions to do those operations, with a 99% chance they will get
inlined by the javascript engine, it will be much faster than array handling + parseInt.
You might even write this code directly. Maybe in some case you will be able to
cache 1 << k, but anyway, shift instructions have a very little cost.
Another advantage is that you can handle several tests in a single instruction,
for instance :
var setRequiredMask = ( 1<<3 | 1<<5 ) ; // to test if bits 3 and 5 set
var clearRequiredMask = ( 1<<2 | 1 <<4 ) ; // to test if bit 2 and 4 cleared
var someRequiredMask = ( 1<<0 | 1 <<6 ) ; // to test if either bit 0 or bit 6 to be set
var satisfyConditions = ((id & setRequiredMask) == setRequiredMask) &&
((id & !clearRequiredMask) ==0 ) &&
(id & someRequiredMask) ;
Here we trade 7 access to memory to quite the same number of boolean operations.
If this test is used in a loop to filter an array, the speed gain is huge.
In the same way you can set / clear / swap several bits in a single instruction, test if one condition set is included in the other, test if they are orthogonal, .... all in a very fast way.
Only limit is that you can handle no more than 32 possibilities with this method.
Then you can store the ids in a typed a typed array, depending on the max number
of possibilities, use only a Int8Array or a Int32Array, but i am not sure the gain
in performance will be that interesting compared to [].
Syntax :
var arr = new Int8Array( _length_ );
or
var arr = new Int32Array( _length_ );
Are you trying to get this parseInt(string, radix)
radix An integer that represents the radix of the above mentioned
string.
Not sure, is like this somewhat you expect
var x = new Uint8Array([1,0,0,0]);
var a = x[0].toString()+x[1].toString()+x[2].toString()+x[3].toString();
console.log(parseInt(a, 2));
console.log(a.length);
Is this useful?
var a = 1 << 3; // shift the bits of 1 (0001) 3 places: 1000
if (a == 8) {
// this block will execute
}
Another example:
var i,
result = 0,
len = 4,
bits = [1, 0, 0, 0];
for (i = 0; i < len; ++i) {
result = (result << 1) + bits[i];
}
alert(result);
Keep in mind, parseInt is probably faster than this.

Categories