Calculate count of permutations in array without repetition by Javascript - javascript

First I have an array, like this:
var arr = [[2,3,4,5,6,7,8,9,10],
[3,4,5,6,7,8,9,10,11],
[4,5,6,7,8,9,10,11,12]]
It is not necessarily should be this array, it could be any other, it is just example. So I need to know the count of all possible permutations, something like this:
2,3,4
2,3,5
...
2,3,12
2,4,5
2,4,6
...
2,4,12
...
10,11,12
It is not simple permutations, as I understand. And also I don't need all this combination, I just need their count, may be exist formula or something like this. In this example I know that answer is 165. Thank you

Assuming that the order must increase:
var arr = [[2,3,4,5,6,7,8,9,10],
[3,4,5,6,7,8,9,10,11],
[4,5,6,7,8,9,10,11,12]];
function count(stack, history) {
var counter = 0;
history = history || [];
stack[0].forEach(function(it) {
if (! history.length || history[history.length -1] < it) {
if (stack[1]) {
counter += count(stack.slice(1), history.concat([it]));
} else {
counter++;
}
}
});
return counter;
}
console.log(count(arr)); //165

This is an interesting mathematical problem. I think what you are referring to is combinations and not permutations. I place the javascript here first. The math follows below that.
<script type="text/javascript">
var arr = new Array();
arr[0] = new Array(2,3,4,5,6,7,8,9,10);
arr[1] = new Array(3,4,5,6,7,8,9,10,11);
arr[2] = new Array(4,5,6,7,8,9,10,11,12);
function countcombinations() {
var history = new Array();
for (var i=0;i<arr[0].length;i++) {
for (var j=0;j<arr[1].length;j++) {
for (var k=0;k<arr[2].length;k++) {
if (arr[0][i] == arr[1][j] || arr[0][i] == arr[2][k] || arr[1][j] == arr[2][k]) {
} else {
// If all are different, consider this set as candidate
var found = false;
history.forEach(function(entry) {
if (
// The various possible sequences for comparison
(arr[0][i] == entry[0] && arr[1][j] == entry[1] && arr[2][k] == entry[2]) ||
(arr[0][i] == entry[0] && arr[1][j] == entry[2] && arr[2][k] == entry[1]) ||
(arr[0][i] == entry[1] && arr[1][j] == entry[0] && arr[2][k] == entry[2]) ||
(arr[0][i] == entry[1] && arr[1][j] == entry[2] && arr[2][k] == entry[0]) ||
(arr[0][i] == entry[2] && arr[1][j] == entry[0] && arr[2][k] == entry[1]) ||
(arr[0][i] == entry[2] && arr[1][j] == entry[1] && arr[2][k] == entry[0])
) found = true;
});
// If not found, add to history
if (!found) history[history.length] = new Array(arr[0][i], arr[1][j], arr[2][k]);
}
}
}
}
alert ("Count: " + history.length);
}
countcombinations(); // Gives 165
</script>
Mathematically, the problem can be solved by iterating the first set and considering the possibilities for each. This is what the algorithm in the above javascript code does. The sequence of the elements do not matter. Each time a new unique combination is found, it appends this combination to the history. For fun, you could experiment with the above code and apply the math below to understand it further.
For a human approach to the math, let's consider the first set and use (X, Y, Z) to denote the three chosen numbers. The numbers in each set need to be in increasing order and the smallest number in subsequent sets also need to be in increasing order. The array given to us meets these conditions. So, for the first set:
[2,3,4,5,6,7,8,9,10]
When X = 2, i.e., (2, Y, Z), there are two possibilities to consider:
Y = 3
Y > 3
If Y = 3, then Z has 9 possibilities (4 through to 12).
If Y > 3, then if Z < 12, (Y, Z) has 8C2 (8 choose 2), or 28, possible combinations.
If Z = 12, then (Y, 12) has 8 possible combinations. Thus:
X = 2, Y = 3, Z > 3 : 9 combinations
X = 2, Y > 3, Z < 12 : 8C2 = 28 combinations
X = 2, Y > 3, Z = 12 : 8 combinations
In short, there are 45 possible combinations where any of the numbers is 2.
Phew! Moving on, from numbers 3 to 9, you can reuse two conditions above: whether Z < 12 or Z = 12. You will see a pattern emerging as shown below:
X = 3, Y > 3, Z < 12: 8C2 = 28 combinations
X = 3, Y > 3, Z = 12: 8 combinations
X = 4, Y > 4, Z < 12: 7C2 = 21 combinations
X = 4, Y > 4, Z < 12: 7 combinations
...
X = 9, Y > 9, Z < 12: 2C2 = 1 combination
X = 9, Y > 9, Z = 12: 2 combinations
Finally, when X = 10, there is only 1 possibility that is (10, 11, 12).
Thus the number of combinations (with a nice decreasing pattern) is:
X = 2: 9 + 8C2 + 8 = 45
X = 3: 8C2 + 8 = 36
X = 4: 7C2 + 7 = 28
X = 5: 6C2 + 6 = 21
X = 6: 5C2 + 5 = 15
X = 7: 4C2 + 4 = 10
X = 8: 3C2 + 3 = 6
X = 9: 2C2 + 2 = 3
X = 10: 1 = 1
TOTAL: 165

Related

Find closest number divisible by 3 [duplicate]

This question already has answers here:
Next Nearest Number Divisible By X [closed]
(2 answers)
Getting a number divisible by five with Math.Round
(5 answers)
Closest divisible integer
(8 answers)
Closed 1 year ago.
I need to find a way to get the closest number divisible by three for a given number. As it's only the number three, and i was in a rush, i used if statements. I was wondering if there was a cleaner way of getting the same result?
https://jsfiddle.net/
let indexes = [0, 9, 26, 39];
for (let i = 0, l = indexes.length; i < l; i++) {
newIndex = indexes[i];
if (!(newIndex % 3 == 0)) {
if (((newIndex - 1) % 3 == 0)) {
newIndex = (newIndex - 1);
} else {
if (((newIndex + 1) % 3 == 0)) {
newIndex = (newIndex + 1);
} else if (((newIndex + 2) % 3 == 0)) {
newIndex = (newIndex + 2);
} else if (((newIndex + 3) % 3 == 0)) {
newIndex = (newIndex + 3);
}
}
}
console.log(newIndex);
}
input: 0
expected output: 0
input: 9
expected output: 9
input: 26
expected output: 27
input: 39
expected output: 39
I think i made it a little cleaner.
let indexes = [0, 9, 26, 39, 29];
for (let i = 0; i < indexes.length; i++) {
if(indexes[i] % 3 == 0) {
console.log('Closest multiple: ', indexes[i])
}
else {
if((indexes[i] + 1) % 3 == 0) {
console.log('Closest multiple: ', indexes[i] + 1)
}else {
console.log('Closest multiple: ', indexes[i] - 1)
}
}
}
this switch case would make it better readable
function Get(input){
var number = input % 3;
switch(number){
case 0:
return input;
case 1:
return input-1;
case 2:
return input+1;
default:
return "somethign went wrong";
}
}
So now, you basically have to iterate through your array calling the function above.

How can I assign a number to X, if X is in a range of numbers?

I am working with random and what I want is that if, (for example) X = 173. X must be 10.
Let me explain: depending on a range of numbers, X will have a new value:
if X is less than or equal to 10, X must be equal to 26
if X is less than or equal to 20, X must be equal to 35,
if X is less than or equal to 30, X must be equal to 12...
Every 10 units X will have a different value
So far this is what I have, but I don't think this code is the most appropriate:
var X = 55;
if(X <= 10){
X = 26;
}else if (X<=20){
X = 35;
}else if (X <= 30){
X = 12;
}else if(X <= 40){
X = 28;
}else if (X <= 50 ) {
X = 7;
}else if (X <= 60) {
X = 29
}
console.log(X);
The problem is that if you continue like this, it should do 36 validations (if)
I'm working with vanilla JS
Come to think of it, you can do this without any looping at all, still assuming the ranges you provided.
Thanks to #TedHopp for my math error fix!
const values = [26, 35, 12, 28, 7, 29];
var x = 55;
x = x ? (values[Math.ceil(x/10)-1] || x) : values[0];
console.log(x);
original answer
Assuming you actually have ranges of 10, you can use a single array of the potentially assigned values, and iterate the array until you find the range you want.
Like this:
const values = [26, 35, 12, 28, 7, 29];
var x = 55;
for (let i = 0; i < values.length; i++) {
if (x <= ((i + 1) * 10)) {
x = values[i];
break;
}
}
console.log(x);
Or you can use .find() for this to be a little more succinct.
const values = [26, 35, 12, 28, 7, 29];
var x = 55;
x = values.find((_, i) => x <= ((i + 1) * 10)) || x
console.log(x);

While loop output not correct

I'm busy with a udacity excercise and the following question:
A while loop that:
Loop through the numbers 1 to 20
If the number is divisible by 3, print "Julia"
If the number is divisible by 5, print "James"
If the number is divisible by 3 and 5, print "JuliaJames"
If the number is not divisible by 3 or 5, print the number
I keep submitting the answer but it tells me that my while loop condition is incorrect, Is there anything im doing wrong?
var x = 1;
while (x <= 20) {
if (x/3 === 0) {
console.log("julia" );
} // check divisibility
else if (x/5 === 0) {
console.log("james");
}
else if (x/5 === 0 && x/3 === 0 ) {
console.log("juiliajames");
} // print Julia, James, or JuliaJames
else {
console.log(x);
}
x= x + 1;// increment x
}
You need to use Modulus (%) instead of divide (/). And make x % 5 === 0 && x % 3 === 0 as your first condition.
Change your code like following.
var x = 1;
while (x <= 20) {
if (x % 5 === 0 && x % 3 === 0) {
console.log("juiliajames");
} // print Julia, James, or JuliaJames
else if (x % 3 === 0) {
console.log("julia");
} // check divisibility
else if (x % 5 === 0) {
console.log("james");
} else {
console.log(x);
}
x = x + 1; // increment x
}
var x = 1;
while (x <= 20) {
if(x%3 === 0 && x%5 === 0 ){
console.log("juiliajames" );
} // check divisibility
else if(x%3 === 0){
console.log("juilia");
}
else if (x%5 === 0){
console.log("james");
} // print Julia, James, or JuliaJames
else{
console.log(x);
}
x= x + 1;// increment x
}
If you want to check divisibility, you should use the % operator instead of / operator.
Check x divisible by 5 AND 3 at the begining or it will never been done because if it is divisible by 3 your loop won't go to the else if statment.
To check divisibility use modulo (x/3 === 0 only for x = 0)
var x = 1;
while (x <= 20) {
if(x%5 === 0 && x%3 === 0){
console.log("juiliajames" );
}
else if(x%5 === 0){
console.log("james");
}
else if (x%3 === 0 ){
console.log("juilia");
}
else{
console.log(x);
}
x= x + 1;// increment x
}
My approach works by setting bitwise flags on an integer. If it's divisible by three (value % 3 === 0, where % is 'modulo' which gives an integer remainder from division) The first bit is set and if it's divisible by five the second bit is set. That gives a result that could have three binary values 01, 10 or 11, or in decimal 1, 2 & 3 (The three comes about when both bits are set).
var DIVISABLE_BY_THREE = 1;
var DIVISABLE_BY_FIVE = 2;
var DIVISABLE_BY_THREE_AND_FIVE = 3;
var value = 0;
while(value++ < 20) {
var modulo_3 = (value % 3 === 0) | 0;
var modulo_5 = ((value % 5 === 0) | 0) << 1;
switch(modulo_3 | modulo_5) {
case DIVISABLE_BY_THREE:
console.log("Julia");
break;
case DIVISABLE_BY_FIVE:
console.log("James");
break;
case DIVISABLE_BY_THREE_AND_FIVE:
console.log("JuliaJames");
break;
default:
console.log(value);
break;
}
}
var x = 1;
while (x <= 20) {
var name ="";
if (x % 3 == 0) {
name = name + "julia";
}
if (x % 5 == 0) {
name = name + "james";
}
if(name.length > 0)
console.log(name);
else
console.log(x);
x++;
}

Fill a zero for missing days

For every day there is no data, I want to add a 0 into the array:
The code I did is wrong because it doesn't add a 0 for missing days.
Goes from 1, 2, 6.. should go 1, 2, 3, 4, 5, 6 - and have zeros leading upto that 6. Results are below.
var i = 1;
var found = false;
try {
for (var x = 0; x < #ViewBag.MonthDays; x++) {
i = 1;
do{
found = false;
try {
if ( i == cheque[x].theDay) {
s2.push(cheque[x].theMoney * -1);
found = true;
console.log("Day: " + cheque[x].theDay + " i " + i);
break
}
}
catch (error) {
s2.push(0);
}
console.log(i == cheque[x].theDay, i, cheque[x].theDay);
i++
} while ((i < #ViewBag.MonthDays))
console.log(found == false);
if (found == false)
s2.push(0);
}
}
catch (error){
s2.push(0);
}
console.log ("Push: " + s2);
Results:
Day: 1 i 1
false
false 1 2
Day: 2 i 2
false
false 1 6
false 2 6
false 3 6
false 4 6
false 5 6
Day: 6 i 6
Says Day: 6 i 6 when it matches.
I know there is a better way to do this, a method sort of like this:
items = items2.map( row =>
//is there a matching row in items?
items.filter( r => r.theString == row.theString).length == 0 ?
//if not, fill with zeros
{theString:0, theCount:0} :
//if there is, return the items' row
items.filter( r => r.theString == row.theString)[0] );
but that just matches two arrays with each other. This one needs every day of the month covered.
This is how I've done it now:
var monthD = new Array(#ViewBag.MonthDays)
.join().split(',')
.map(function(item, index){ return ++index;})
console.log (monthD);
cheque = monthD.map( row =>
//is there a matching row in items?
cheque.filter( r => r.theDay == row).length == 0 ?
//if not, fill with zeros
{theDay:0, theMoney:0} :
//if there is, return the items' row
cheque.filter( r => r.theDay == row)[0] );
try {
for (var x = 0; x < #ViewBag.MonthDays; x++) {
s2.push(cheque[x].theMoney * -1);
}
}
catch (error){
s2.push(0);
}
Much better and quicker method. Without all the confusing loops to mess with my mind.

JavaScript programme

I am putting an interactive java script form whereas the the out put is getting confused with switch case. Kindly help me: It is pipe weight calculation.
Pipe sizes: 100mm, 150 mm, 200 mm, 250mm up to 1000mm
For each pipe the pressure class varies: PN3, PN6 and PN9
For each pressure class the stiffness varies: SN124 and SN256
For given Pipes size, pressure class and stiffness class - the weight will be different. To arrive the out put - I am using the switch case, which is very lengthy and time consuming. Any body can help me in solving the java script so that same will be put in the HTML file.
This is the code I have, but I think there must be a better way to do it.
What's a better way?
<SCRIPT LANGUAGE="JavaScript">
function CalculateSum(Atext, Btext, Ctext,form)
{
var A = parseFloat(Atext);
var B = parseFloat(Btext);
var C = parseFloat(Ctext);
switch (true){
case (A == 100 && B == 3 && C == 124): K =21.4; L=102; M =55; break ;
case (A == 100 && B == 3 && C == 256): K =21.9; L=125; M=49; break ;
case (A == 100 && B == 3 && C == 512): K =22.2; L=133; M=45; break ;
case (A == 100 && B == 6 && C == 124): K =42.9; L=139; M=41; break ;
case (A == 100 && B == 6 && C == 256): K =42.78;L=141; M=39; break ;
case (A == 100 && B == 6 && C == 512): K =43.01;L=144; M=37; break ;
case (A == 100 && B == 9 && C == 124): K =54.84;L=148; M=34; break ;
case (A == 100 && B == 9 && C == 256): K =55.02;L=152; M=31; break ;
case (A == 100 && B == 9 && C == 512): K =56.90;L=157; M=29; break ;
case (A == 150 && B == 3 && C == 124): K =39.4; L=164; M=25; break ;
....
......
.......
break ;
}
form.Ans1.value = K + " Kg/Rmt";
form.Ans1.value = L + " Rmt";
form.Ans1.value = M + " Nos";
}
</SCRIPT>
I assume you can't calculate K from A, B, and C, which would of course be best. Assuming that's the case:
Your way works. It's an unusual way of using switch, but it's valid in JavaScript. (Not in most other languages.)
The other way to do it would be to have a table as a nested bunch of objects, and look the values up in the table:
var Values = {
// Values for A
100: {
// Values for B when A = 100
3: {
// Values for C when A == 100 and B == 3
124: 21.4,
256: 21.9,
512: 22.2
},
6: {
// Values for C when A == 100 and B == 6
124: 42.9,
256: 42.78,
512: 43.01
},
9: {
// Values for C when A == 100 and B == 9
124: 54.84,
256: 55.02,
512:39.4
}
},
150: {
// Values for B when A = 150
3: {
// Values for C when A == 150 and B == 3
124: 39.4
}
}
};
I'm not sure that makes the data more readable/maintainable, but it's quite quick to use, and you can write it a bit more concisely (see the end of the answer); I wanted to include the comments above.
CalculateSum ends up looking like this:
function CalculateSum(Atext, Btext, Ctext,form)
{
var A = parseFloat(Atext);
var B = parseFloat(Btext);
var C = parseFloat(Ctext);
var entry;
// Get the top-level entry for A
entry = Values[A];
if (entry) {
// We have one, get its entry for this value of B
entry = entry[B];
if (entry) {
// We have one, get _its_ entry for C
entry = entry[C];
}
}
if (typeof entry === "number") {
form.Ans.value = entry + " Kg/Rmt";
}
else {
// Didn't find it
}
}
Or as Deestan points out in the comments, you can shorten that a bit if you're not doing this in a hyper-tight loop you run hundreds of thousands of times (which I'm guessing you're not):
function CalculateSum(Atext, Btext, Ctext,form)
{
var A = parseFloat(Atext);
var B = parseFloat(Btext);
var C = parseFloat(Ctext);
var K;
// Get the entry from our tables
K = Values[A] && Values[A][B] && Values[A][B][C];
if (typeof K === "number") {
form.Ans.value = K + " Kg/Rmt";
}
else {
// Didn't find it
}
}
(There I changed entry to K because we never store anything but the final value in it.)
And here's the more concise Values:
var Values = {
100: {
3: { 124: 21.4, 256: 21.9, 512: 22.2 },
6: { 124: 42.9, 256: 42.78, 512: 43.01 },
9: { 124: 54.84, 256: 55.02, 512: 39.4 }
},
150: {
3: { 124: 39.4 }
}
};

Categories