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);
Related
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);
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/
I have built an ngram model implementation in Javascript, which works fine. However, I am looking to change my data structure so that I do not have to iterate through all the history each time a new word/character is observed.
Here, I take a seedtext and use it to build ngrams with an order 2.
var ngrams = {};
var order = 2;
var seedtext = "adadwsdawdsadawdsadadasdwdadaaasdsadsdadwdasdasd";
build();
function build(){
for (var i = 0; i < seedtext.length - order; i++) {
var gram = seedtext.substring(i, i + order);
var next = seedtext.charAt(i + order);
if (!ngrams.hasOwnProperty(gram)) {
ngrams[gram] = [];
}
ngrams[gram].push(next);
}
}
console.log(ngrams);
console.log(ngrams["wd"]);
I am looking to have a data structure that holds a record of each observed pattern (for a given order. Each observed pattern should have a next possible observation and its count.
For example, if you run the below code, an output such as this can be seen:
[object Object] {
aa: ["a", "s"],
ad: ["a", "w", "a", "a", "a", "a", "s", "w"],
as: ["d", "d", "d", "d"],
aw: ["d", "d"],
da: ["d", "w", "w", "d", "s", "d", "a", "d", "s", "s"],
ds: ["a", "a", "a", "d"],
dw: ["s", "d", "d"],
sa: ["d", "d", "d"],
sd: ["a", "w", "s", "a", "a"],
wd: ["s", "s", "a", "a"],
ws: ["d"]
}
["s", "s", "a", "a"]
Now, if we take "ad" for example: ngrams["ad"], we get back ["a", "w", "a", "a", "a", "a", "s", "w"].
Clearly, after ad we can either get a w,a or s.
I'd like to group the letters so that ngrams["ad"] returns something like:
{a: 5
w: 2
s :1}
Note that they are in order so that the most frequently occurring letter is at the top, with its count.
I'd like to be able to access the data like so (for example):
ngrams["ad"].a;
ngrams["ad"].w;
ngrams["ad"].s;
and get back 5 for a, 2 for w and 1 for s.
I also want to be able to increment the values as a previously seen pattern is observed again... I also want to be able to remove patterns.
Any ideas?
Here is a working version. Instead of an array, you add another object to store counts of next characters in it.
var ngrams = {};
var order = 2;
var seedtext = "adadwsdawdsadawdsadadasdwdadaaasdsadsdadwdasdasd";
build();
function build(){
for (var i = 0; i < seedtext.length - order; i++) {
var gram = seedtext.substring(i, i + order);
var next = seedtext.charAt(i + order);
if (!ngrams.hasOwnProperty(gram)) {
ngrams[gram] = {};
}
if (!ngrams[gram].hasOwnProperty(next)) {
ngrams[gram][next] = 0;
}
ngrams[gram][next] += 1;
}
}
console.log(ngrams);
console.log(ngrams["wd"]);
example:
var arr = ["a", "b", "c", "d", "e", "f"];
how to check if "a", "b" and "c" are in array?
i tried indexOf() but i cant check if more than 1 strings are in array...
You are use Array.protoype.every and Array.prototype.indexOf, like this
["a", "b", "c"].every(function(currentItem) {
return arr.indexOf(currentItem) !== -1;
});
This will return true, only if all the elements in ["a", "b", "c"] are present in arr.
try like this:
var arr = ["a", "b", "c", "d", "e", "f"];
var arr1=['a','b','c'];
for(i=0;i<arr1.length;i++){
var a1 = arr.indexOf(arr1[i]);
console.log(a1);
}
or
var a = arr.indexOf("a");
console.log(a);//0
var b = arr.indexOf("b");
console.log(b);//1
var c = arr.indexOf("c");
console.log(c);//2
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;});