Javascript all unique options of array of elements and number of options - javascript

Problem 1
I have this variables
var myArr = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
var nOptions = 10;
and I'm trying to get all unique possible combination with 10 options.
Results example:
var result1 = ["A", "A", "A", "A", "A", "A", "A", "A", "A", "A"];
var result2 = ["A", "A", "A", "A", "A", "A", "A", "A", "A", "B"];
var result3 = ["A", "A", "A", "A", "A", "A", "A", "A", "B", "A"];
var result4 = ["A", "A", "A", "A", "A", "A", "A", "B", "A", "A"];
----------------------------------------------------------------
var result5 = ["A", "A", "A", "A", "A", "A", "A", "A", "B", "B"];
var result6 = ["A", "A", "A", "A", "A", "A", "A", "B", "A", "B"];
var result7 = ["A", "A", "A", "A", "A", "A", "B", "A", "A", "B"];
----------------------------------------------------------------
var result8 = ["A", "A", "A", "A", "A", "A", "A", "A", "C", "B"];
var result9 = ["A", "A", "A", "A", "A", "A", "A", "C", "A", "B"];
var result10 = ["A", "A", "A", "A", "A", "A", "C", "A", "A", "B"];
----------------------------------------------------------------
var result11 = ["A", "A", "A", "A", "A", "A", "A", "C", "B", "B"];
var result12 = ["A", "A", "A", "A", "A", "A", "C", "A", "B", "B"];
var result13 = ["A", "A", "A", "A", "A", "C", "A", "A", "B", "B"];
----------------------------------------------------------------
var resultn = ["I", "I", "I", "I", "I", "I", "I", "I", "I", "I"];
Is there any way to print all that results in JavaScript?
Is there a math formula so I can know the number of all combinations without making all the loops?
Problem 2
Finally I want to make a filter so I can have all possible combinations with the new filters.
Example:
var minA = 0;
var maxA = 3;
var minB = 2;
var maxB = 4;
var minC = 0;
var maxC = 3;
-------------
var minI = 3;
var maxI = 5;
Example valid results with filter:
var result1 = ["B", "B", "B", "B", "I", "I", "I", "I", "I", "A"];
var result2 = ["B", "B", "B", "B", "I", "I", "I", "I", "I", "C"];
var result3 = ["B", "B", "B", "B", "I", "I", "I", "I", "A", "A"];
Is there any way to print all filter results in JavaScript directly or I have to loop throw all results and make counters for each letter and then if all counters are valid with the filter options print the new results?
Is there a math formula so I can know the number of all combinations with filters without making all the loops?
Thanks to everybody who can help in making the code. I will update the code so everybody can use it for future projects.
CODE Problem 1
var myArr = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
var nOptions = 10;
myCounter = 0;
allResults = [];
for (let a = 0; a < 9; a++) {
for (let b = 0; b < 9; b++) {
for (let c = 0; c < 9; c++) {
for (let d = 0; d < 9; d++) {
for (let e = 0; e < 9; e++) {
for (let f = 0; f < 9; f++) {
for (let g = 0; g < 9; g++) {
for (let h = 0; h < 9; h++) {
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
allResults.push([myArr[a], myArr[b], myArr[c], myArr[d], myArr[e], myArr[f], myArr[g], myArr[h], myArr[i], myArr[j]]);
myCounter++;
}
//break;
}
//break;
}
//break;
}
//break;
}
//break;
}
//break;
}
//break;
}
//break;
}
//break;
}
Better CODE Problem 1
I made a better code so now nOptions can be a reasonable number (min 0, max 26) but a number too big will have too much possible combinations and the pc couldn't process all that data. A maxium reasonable number would be nOptions = 6. That means 9^6 = 531.441 results.
var myArr = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
var nOptions = 2;
var myCounter = 0;
var allResults = [];
var myLetters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
codeLine='';
for (let i = 0; i < nOptions; i++) {
codeLine += 'for (let ' + myLetters[i] + ' = 0; ' + myLetters[i] + ' < 9; ' + myLetters[i] + '++) {';
}
codeLine += 'allResults.push([';
for (let i = 0; i < nOptions; i++) {
codeLine += 'myArr[' + myLetters[i] + ']';
if (i !== nOptions - 1) {
codeLine += ', ';
}
}
codeLine += ']);';
codeLine += 'myCounter++;';
//codeLine += 'console.log(myCounter);';
for (let i = 0; i < nOptions; i++) {
codeLine += '}';
}
//console.log(codeLine);
eval(codeLine);
console.table(allResults);

If you think of this recursively, it becomes fairly simple to write the code that generates these combinations. Simply take each letter in turn as the first letter, then recursively calculate all the words one character shorter for the remainder and combine them. We bottom out with a result holding just one empty array when the count is 0. Here's a simple version of the code:
const makeWords = (cs, n) =>
n == 0
? [[]]
: cs .flatMap (c => makeWords (cs, n - 1) .map (w => [c, ...w]))
const letters = ['A', 'B', 'C', 'D']
console .log (makeWords (letters, 3))
.as-console-wrapper {max-height: 100% !important; top: 0}
As others have pointed out the formula for the count of such words is simply (number of letters) ^ (word length). So for my example of three-letter words on a four-character alphabet, there are 4 ^ 3, or 64 results. For ten-letter words on a nine-character alphabet, there are 9 ^ 10 or 3486784401 results. I hope you're not planning on printing them all, or even logging them all to the console!

You can convert between numbers and letters by their digit. Here you have 9 letters you care about, so using base 9 we have: 0=a, 1=b, ... 8=i.
Then use toString to convert all the integers from 0 to 9^11-1 to base 9, with leading 0s. Finally, convert the digits back to the appropriate letters.
0 -> 0000000000 -> aaaaaaaaaa
1 -> 0000000001 -> aaaaaaaaab
...
64340123 -> 0064340123 -> aagedeabcd
...
8888888888 -> 8888888888 -> iiiiiiiiii

Solution to problem 1#
var myArr = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
var nOptions = 2;
var myCounter = 0;
var allResults = [];
var myLetters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
codeLine='';
for (let i = 0; i < nOptions; i++) {
codeLine += 'for (let ' + myLetters[i] + ' = 0; ' + myLetters[i] + ' < 9; ' + myLetters[i] + '++) {';
}
codeLine += 'allResults.push([';
for (let i = 0; i < nOptions; i++) {
codeLine += 'myArr[' + myLetters[i] + ']';
if (i !== nOptions - 1) {
codeLine += ', ';
}
}
codeLine += ']);';
codeLine += 'myCounter++;';
//codeLine += 'console.log(myCounter);';
for (let i = 0; i < nOptions; i++) {
codeLine += '}';
}
//console.log(codeLine);
eval(codeLine);
console.table(allResults);

Related

Get the point where the replace occurred in a replace

I'm trying to create a string increaser function that will take one string and raise it up one, for example:
000000 is the first string, then comes 000001, up to 000009 where it then goes onto 00000a up to 00000z.
My idea was that I will replace the last pattern (z) with the first (0), then, get the point where it was replaced and increase that by one in the pattern.
The code I tried to use:
cycler(string) {
//string="00000z"
var pos = string.replace('z', '0');
console.log(pos);
}
I sadly realized that the return of this function was the replaced version, not what I was after. Which makes total logical sense.
I'm wondering if there is a function in JavaScript for this functionality of finding where the all the replaces were made?
this way you can increase the string.
first you find the place you want to change. and then you change it
const range = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
cycler = function(string) {
const pos = string.match(/[0-9a-z]z/ )
return pos === null ? string.length - 1 : pos.index
}
inc = function(string,pos) {
let rangeIndex = range.indexOf(string[pos]);
rangeIndex++;
let arr = string.split("");
arr[pos] = range[rangeIndex];
return arr.join("");
}
var string = '00002z';
const pos = cycler(string);
alert(inc(string,pos))
If I understand correctly, you want to replace all occurrences.
cycler(string) {
//string="00000z"
var pos = string.replace(/z/g, '0');
console.log(pos);
}
Ignore if misunderstood. Thanks.
I don't think there is any inbuilt method for this but you can create your customized logic as follows:
var orgstr = '000000';
var arr = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
function getNextStr(str) {
var count = (str.match(/0/g) || []).length;
var rStr = ""
var found = str.replace(/0/g, '');
var next = getNext(found);
var nexIn = arr.indexOf(found) + 1;
if (next.length != found.length) {
rStr = str.slice(0, count - 1) + next;
} else {
rStr = str.slice(0, count) + next;
}
return rStr;
}
function getNext(fou) {
var str = '';
var nextTobeGrown = true;
for (var i = fou.length - 1; i >= 0; i--) {
var x = fou.substring(i + 1, i);
var ind = arr.indexOf(x);
if (nextTobeGrown) {
if (ind + 1 < arr.length) {
str += arr[ind + 1];
nextTobeGrown = false;
} else {
str += arr[0]
}
} else {
str += x;
}
}
//console.log(str)
if (nextTobeGrown) {
str += arr[0];
}
return str.split("").reverse().join("");;
}
var rst;
for (var i = 0; i < 160; i++) {
var org = i == 0 ? orgstr : rst;
rst = getNextStr(org);
console.log(rst)
}

manually sorting a paragraph by made-up alphabet with javascript

I'm trying to sort a paragraph alphabetically, not according to the normal ABC but a made-up one (var order).
I wrote this function and it works great, but only for the first letter of each word - not in-word sorting as well (for example, in correct ABC 'banana' would come before 'birthday').
I'm not sure where to go from here.
$("#send").click(function () {
var text = $("#text").val().replace(/[^A-Za-z0-9_\s]/g, "").toUpperCase().split(" ");
var order = ["Q", "B", "K", "D", "H", "V", "Z", "E", "F", "O", "G", "L", "M", "S", "N", "P", "I", "X", "A", "R", "W", "U", "C", "J", "T", "Y"];
var i, t, j;
var newText = []; // will hold the new alphabet
// function to sort the words:
for (i = 0; i < order.length; i++) {
for (t = 0; t < text.length; t++) {
var firstChar = text[t][0];
if (order[i] == firstChar) {
newText.push(text[t]);
}
}
}
console.log(newText.join(','));
});
EDIT:
An example input can be: "Hi dan don't you think that this is awesome",
and I want the output to be: "don't dan hi is awesome this think that you".
You could use an object with the index of the letters and use Array#sort with a callback which looks for every letter adn calculates the order.
function foo(text) {
var text = text.replace(/[^A-Za-z0-9_\s]/g, "").toUpperCase().split(" "),
order = "QBKDHVZEFOGLMSNPIXARWUCJTY",
ref = {};
order.split('').forEach(function (a, i) { ref[a] = i + 1; });
text.sort(function (a, b) {
var i = 0, v;
do {
v = (ref[a[i]] || 0) - (ref[b[i]] || 0);
i++;
} while (!v)
return v;
});
console.log(text.join(', '));
}
foo('a aa ab b ba bb');
foo('banana birthday');
The problem with your algorithm is that it only compares the first letter in each word, but if the letters are the same the algorithm needs to compare the next letter in each word. Here's a solution that uses recursion:
function doSort(inputArr) {
var words = inputArr.slice(0);
var alphabet = ["Q", "B", "K", "D", "H", "V", "Z", "E", "F", "O", "G", "L", "M", "S", "N", "P", "I", "X", "A", "R", "W", "U", "C", "J", "T", "Y"];
words.sort(function(item1, item2) {
return sortRecursive(item1, item2, 0);
});
function sortRecursive(item1, item2, idx) {
if (item1.length <= idx && item2.length <= idx) {
return 0;
} else if (item1.length <= idx) {
return -1;
} else if (item2.length <= idx) {
return 1;
} else if (item1[idx] == item2[idx]) {
return sortRecursive(item1, item2, idx+1);
} else {
return alphabet.indexOf(item1[idx].toUpperCase()) - alphabet.indexOf(item2[idx].toUpperCase());
}
}
return words;
}
var arr = ["banana", "quebec", "bird", "birthday", "birdman", "bird"];
var sortedArr = doSort(arr);
console.log('unsorted',arr);
console.log('sorted', sortedArr);
https://jsfiddle.net/2qgaaozo/

pick new item from array every day

Let's say I have an array of any fixed length i.e. it could be 3, 5, 7 ... upto 30.
How can I generate an algorithm such that if I pick an item from the array, every single day, it should not pick the same item index on any two consecutive days.
Note: I do not have the ability to store, what was picked the previous day.
For example,
if my array is ["a", "b", "c", "d", "e", "f"]
valid result would be
["a", "b", "c", "d", "e", "f", "d", "a", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f"]
Invalid result would be
["a", "b", "c", "d", "e", "f", "a", "b", "b", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f"]
Note the consecutive b in above
An ideal result would be: where the whole array is perfectly rotated after the end of length is reached.
["a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f"]
Try using mod (%) that way the number can never exceed the array length. Demo:
var array = ["a", "b", "c", "d", "e", "f"];
var output = [];
for (var day = 1; day < 365; day++) {
output.push(array[day % array.length])
}
console.log(output);
var d = new Date();
var n = d.getDay();
var chr = String.fromCharCode(97 + n);
Run this every day to generate the next value in your sequence.
So your sequence will be:
a, b, c, d, e, f, g
I made a solution using the modulo operater: %. Not sure if this is exactly what you want, but it seems to work properly.
var items = ["a","b","c","d","e","f"];
var day = new Date().getDay();
console.log(items[day % items.length]);
You could presumably put that into a function, or display it however you'd like.
This is very easy to accomplish using getDate which returns the current day of the month (1 - 31 depending on the month). Combining this with the modulus operator ensures that you will always get a valid item in non-consecutive order.
function log(msg) {
document.querySelector('pre').innerHTML += msg + '\n';
}
function logItem(items, date) {
var index = (date.getDate() - 1) % items.length;
var item = items[index];
log(date.toDateString() + ' : ' + item);
}
function addDay(date) {
date.setDate(date.getDate() + 1);
}
var items = ['a', 'b', 'c', 'd', 'e', 'f'];
var day = new Date(2016, 0, 1);
for (var i = 0; i < items.length * 3; i++) {
logItem(items, day);
addDay(day);
}
<pre></pre>
There is one problem with this exact implementation: it is possible for the end of the month to have the same relative value as the first of the month.
function log(msg) {
document.querySelector('pre').innerHTML += msg + '\n';
}
function logItem(items, date) {
var index = (date.getDate() - 1) % items.length;
var item = items[index];
log(date.toDateString() + ' : ' + item);
}
function addDay(date) {
date.setDate(date.getDate() + 1);
}
var items = ['a', 'b', 'c', 'd', 'e', 'f'];
var day = new Date(2016, 0, 30);
for (var i = 0; i < 4; i++) {
logItem(items, day);
addDay(day);
}
<pre></pre>
To handle this, you can determine how many days are in the month, determine if your start and end indices are the same and change one if they are. How you pick an alternative value is up to you.
function log(msg) {
document.querySelector('pre').innerHTML += msg + '\n';
}
function logItem(items, date) {
// ---
var daysInMonth = getDays(date);
var day = date.getDate();
var index = (day - 1) % items.length;
if (day === daysInMonth && (day - 1) % items.length === 0) {
// Change to a different item
index = Math.floor(Math.random() * (items.length - 3)) + 2;
}
// ---
var item = items[index];
log(date.toDateString() + ' : ' + item);
}
function getDays(date) {
return new Date(date.getYear(), date.getMonth() + 1, 0).getDate();
}
function addDay(date) {
date.setDate(date.getDate() + 1);
}
var items = ['a', 'b', 'c', 'd', 'e', 'f'];
var day = new Date(2016, 0, 30);
for (var i = 0; i < 4; i++) {
logItem(items, day);
addDay(day);
}
<pre></pre>
Try something like this
var a = ["a", "b", "c", "d", "e", "f"],
b = [],
random;
var i = function(val) {
random = val[Math.floor(Math.random() * val.length)];
(random != b[b.length - 1]) ? b.push(random): b.push('duplicate');
console.log(b);
}
setInterval(() => {
i(a)
}, 1000);

multiple array to json object convert?

I have multiple array like as follow:
var a=[1,2,3,4,5,6,7,8,9];
var b=["a","b","c","d","e","f","g","h","i","j"];
but i need to convert arrays to array object like as below:
ab=[
["1","a"],
["2","b"],
["3","c"],
["4","d"],
["5","e"],
["6","f"],
["7","g"],
["8","h"],
["9","i"]
];
here i mentioned two arrays only but am using more than 6 array.
how can i convert as JSon object
for (var i = 0; i < a.length; i++) {
ab[i] = [a[i], b[i]];
}
underscore has a method called "zip", which performs this task for an arbitrary number of arguments. Here is a rough, not extensively tested implementation:
function zip() {
if ( ! arguments.length ) {
return [];
}
var result = [];
for (var i = 0; i < arguments[0].length; i++) {
result[i] = [];
for (var j = 0; j < arguments.length; j++) {
result[i][j] = arguments[j][i];
}
}
return result;
}
var ab = zip(a,b);
Kinda late to the party but this should get the job done
2 ARRAYS
var ab = "",
a = [1, 2, 3, 4, 5, 6, 7, 8, 9],
b = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
x = b.length,
i = 0;
for (; i < x; i++) {
if (typeof a[i] == 'undefined' || typeof b[i] == 'undefined') continue;
ab += '[' + a[i] + ',"' + b[i] + '"],';
}
ab = JSON.parse("[" + ab.substr(0, --ab.length) + "]");
// ab[0][0] === 1
// ab[0][1] === 'a'
// ab[0] === [1, "a"]
// ab === [
// [1, "a"],
// [2, "b"],
// [3, "c"],
// [4, "d"],
// [5, "e"],
// [6, "f"],
// [7, "g"],
// [8, "h"],
// [9, "i"]
// ];
Try it at JSFIDDLE
assuming that a and b are the same length this will convert your arrays to json objects.
6 ARRAYS
You can expand your code to accommodate the more arrays like so
var ab = "",
a = [1, 2, 3, 4, 5, 6, 7, 8, 9],
b = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
c = ["h", "i", "j", "k", "l", "m", "n", "o", "p", "q"],
d = ["r", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
e = ["s", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
f = ["t", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
x = b.length,
i = 0;
for (; i < x; i++) {
if (typeof a[i] == 'undefined' || typeof b[i] == 'undefined') continue;
ab += '[' + a[i] + ',"' + b[i] + '","' + c[i] + '","' + d[i] + '","' + e[i] + '","' + f[i] + '"],';
}
ab = JSON.parse("[" + ab.substr(0, --ab.length) + "]");
// ab[0] === [1, "a", "h", "r", "s", "t"]
// ab[0][5] === "t"
// ab[0][3] === "h"
6 ARRAY FIDDLE
EXPLANATION
We use one loop starting at 0 to the length of one of the array objects, this case b.length.
Then for each iteration we convert the values of the array object to a multidimensional string appended to the object ab. While ensuring that the values at each iteration aren't undefined. after the loop we convert the multidimensional string to an JSON object with JSON.parse
In jquery you can use simply like below:
$(a).each(function(n){ab[n]=[a[n],b[n]]; return true;});

Add strings in an array - Javascript

I have an array of text:
var text = new Array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s");
I would like to add the elements in the array according to a set number and then store these in a new array. For example, if I pick 3, then the resulting strings in the new array (terms) would be: ["a b c", "d e f", "g h i", ...] etc
I looked at Join and I can't get this to work - it seems to only be able to add the entire array together. I'm guessing I need to use a nested loop, but I can't seem to get this to work. Here's my attempt:
//Outer loop
for (i = 0; i < text.length; i++) {
//Inner loop
for (j = i; j < i + $numberWords; j++) {
newWord = text[j];
newPhrase = newPhrase + " " + newWord;
}
terms.push(newPhrase);
i = i + $numberWords;
}
You can use various array functions like so:
var input = new Array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s");
var output = new Array();
var length = 3;
for (var i = 0; i < input.length; i += length) {
output.push(input.slice(i, i + length).join(" "));
}
alert(output);
Variant of the above example:
var input = new Array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s");
var output = new Array();
var length = 2;
while (input.length) {
output.push(input.splice(0, length).join(" "))
}
alert(output);
Here you go:
var text=new Array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s");
var n = 3;
var a = new Array();
for (var i = 0; i < Math.ceil(text.length / 3); i++)
{
var s = '';
for (var j = 0; (j < n) && ((i*n)+j < text.length) ; j++)
{
s += text[n*i+j] + ' ';
}
a.push(s.trim());
}

Categories

Resources