Counting up within a function of Javascript. - javascript

I have the following javascript code:
nback.lightElement = function(index) {
var letterArray = new Array('Lorem', 'Ipsum' , 'Dolor', 'Est');
var r = Math.floor(Math.random()*4);
var letter = letterArray[r];
nback.numbers[index] = letter;
nback.numbers.innerHTML = letter;
nback.litCell = letter;
nback.current = letter;
nback.previous.push(nback.current);
};
nback.startGame = function() {
nback.round += 1;
nback.updateRound();
nback.blink_count = 0;
// Make a new game
nback.queue = new Queue();
for (i = 0; i < BLINKS; i++) {
// Populate with random data, less fun than created games
// but this is way easier to program.
nback.queue.queue(Math.floor(Math.random() * 1));
}
// Run the game loop every TIME_BETWEEN_ROUNDS
nback.intervalId = window.setInterval(nback.next, TIME_BETWEEN_BLINKS);
};
This gives my a random word output from the letterArray for TIME_BETWEEN_BLINKS milliseconds (e.g. 1000). That word is shown for 1000ms, disappears, and another word appears randomly. This loops BLINKS-times.
Now I do not want it to choose random words from the letterArray (the var r = Math.floor(Math.random()*4); is one of my main concerns). It should just show them one after another. I tried so many different approches (mainly loops of every kind) but still can't make it work. Most of the time I tried loops I got "undefined" (instead of the actual words) or just nothing (blank).
I use https://github.com/chuckha/N-back as a reference.
Help will be much appreciated.

You can use an index for that array that is initialized outside of the function. Here is some code that gives the next word from the array whenever the lightElement function gets called. It also wraps around.
var letterArrayIndex=0;
nback.lightElement = function(index) {
var letterArray = new Array('Lorem', 'Ipsum' , 'Dolor', 'Est');
var letter = letterArray[letterArrayIndex];
letterArrayIndex = (letterArrayIndex+1) % letterArray.length;
nback.numbers[index] = letter;
nback.numbers.innerHTML = letter;
nback.litCell = letter;
nback.current = letter;
nback.previous.push(nback.current);
};

Related

How to display non-repetitive letter within 3 boxes?

The below code can display a single random letter in each box. However, a letter should not be able to appear on different boxes at the same time as one of the boxes. For example, box 1 displays "A", then box 2 and 3 cannot display "A" also.
function random() {
var letter = [];
for (var i = 65; i < 91; i++)
{
letter.push(String.fromCharCode(i));
}
return letter[Math.floor(Math.random() * letter.Length)];
}
function display()
{
document.getElementById("box1").textContent = random();
document.getElementById("box2").textContent = random();
document.getElementById("box3").textContent = random();
}
A good way to do this would be to overhaul your random function to generate all the letters at once, like so:
function randomN(n=3) {
const letters = new Set()
while (letters.size < 3) {
const i = Math.floor(Math.random() * (91-65)) + 65
letters.add(String.fromCharCode(i))
}
return [...letters]
}
function display() {
const [letter1, letter2, letter3] = randomN()
document.getElementById("box1").textContent = letter1
document.getElementById("box2").textContent = letter2
document.getElementById("box3").textContent = letter3
}
For a more modern approach you can utilize generators:
function* randomLetters() {
const letters = "QWERTYUIOPASDFGHJKLZXCVBNM".split('')
while (letters.length > 0) {
const i = Math.floor(Math.random() * letters.length)
yield letters[i]
letters.splice(i, 1)
}
}
function display() {
const letters = randomLetters()
document.getElementById("box1").textContent = letters.next()
document.getElementById("box2").textContent = letters.next()
document.getElementById("box3").textContent = letters.next()
/* and so on and so forth! */
}
function letterGenerator(n=1) {
var generated_letters = [];
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
for (var i=0; i<n; i++){
var random = Math.floor(Math.random() * alphabet.length);
var letter = alphabet.splice(random, 1)[0];
generated_letters.push(letter)
}
return generated_letters;
}
var letters = letterGenerator(3)
gives Array(3) [ "Q", "T", "I" ], for example.
by using splice, we are making sure the randomly chosen letters are removed from the alphabet variable.
you can then go over the letters with for (letter of letters) or something like that, and add each one to the desired element.
by the way, maybe run a document.querySelectorAll('[id^="box"]'); to get all elements and add to them with a for loop.
this, alongside the n parameter, allows for any number of generated letters.
(if you really want it to be generic, create the box elements using js as well)
the solutions attached in the comments are certainly clever.
I especially liked this one

Manipulate more javascript array based on another array

I've a strange thing to do but I don't know how to start
I start with this vars
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];
So to start all the 3 array have the same length and the very first operation is to see if there is a duplicate value in sky array, in this case the 0 is duplicated and only in this case is at the end, but all of time the sky array is sorted. So I've to remove all the duplicate (in this case 0) from sky and remove the corresponding items from base and sum the corresponding items on ite. So if there's duplicate on position 4,5 I've to manipulate this conditions. But let see the new 3 array:
var new_base = [1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var new_sky = [0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var new_ite = [139,38,13,15,6,4,6,3,2,1,2,1,1,1];
If you see the new_ite have 139 instead the 64,52,23, that is the sum of 64+52+23, because the first 3 items on sky are the same (0) so I remove two corresponding value from base and sky too and I sum the corresponding value into the new_ite array.
There's a fast way to do that? I thought a for loops but I stuck at the very first for (i = 0; i < sky.length; i++) lol, cuz I've no idea on how to manipulate those 3 array in that way
J
When removing elements from an array during a loop, the trick is to start at the end and move to the front. It makes many things easier.
for( var i = sky.length-1; i>=0; i--) {
if (sky[i] == prev) {
// Remove previous index from base, sky
// See http://stackoverflow.com/questions/5767325/how-to-remove-a-particular-element-from-an-array-in-javascript
base.splice(i+1, 1);
sky.splice(i+1, 1);
// Do sum, then remove
ite[i] += ite[i+1];
ite.splice(i+1, 1);
}
prev = sky[i];
}
I won't speak to whether this is the "fastest", but it does work, and it's "fast" in terms of requiring little programmer time to write and understand. (Which is often the most important kind of fast.)
I would suggest this solution where j is used as index for the new arrays, and i for the original arrays:
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];
var new_base = [], new_sky = [], new_ite = [];
var j = -1;
sky.forEach(function (sk, i) {
if (!i || sk !== sky[i-1]) {
new_ite[++j] = 0;
new_base[j] = base[i];
new_sky[j] = sk;
}
new_ite[j] += ite[i];
});
console.log('new_base = ' + new_base);
console.log('new_sky = ' + new_sky);
console.log('new_ite = ' + new_ite);
You can use Array#reduce to create new arrays from the originals according to the rules:
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];
var result = sky.reduce(function(r, n, i) {
var last = r.sky.length - 1;
if(n === r.sky[last]) {
r.ite[last] += ite[i];
} else {
r.base.push(base[i]);
r.sky.push(n);
r.ite.push(ite[i]);
}
return r;
}, { base: [], sky: [], ite: [] });
console.log('new base:', result.base.join(','));
console.log('new sky:', result.sky.join(','));
console.log('new ite:', result.ite.join(','));
atltag's answer is fastest. Please see:
https://repl.it/FBpo/5
Just with a single .reduce() in O(n) time you can do as follows; (I have used array destructuring at the assignment part. One might choose to use three .push()s though)
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330],
sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17],
ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1],
results = sky.reduce((r,c,i) => c === r[1][r[1].length-1] ? (r[2][r[2].length-1] += ite[i],r)
: ([r[0][r[0].length],r[1][r[1].length],r[2][r[2].length]] = [base[i],c,ite[i]],r),[[],[],[]]);
console.log(JSON.stringify(results));

Ignore words less than or equal 3 javascript array

I'm building my own boorkmarklet for analyze the words in the current page, currently it's working good, but I would like filter the words and just show the words longer than 3 letters, I'm new with javascript but here is my code:
var sWords = document.body.innerText.toLowerCase().trim().replace(/[,;.]/g,'').split(/[\s\/]+/g).sort();
// count duplicates
var iWordsCount = sWords.length;
// array of words to ignore
var ignore = ['and','the','to','a','of','for','as','i','with','it','is','on','that','this','can','in','be','has','if'];
ignore = (function(){
var o = {};
var iCount = ignore.length;
for (var i=0;i<iCount;i++){
o[ignore[i]] = true;
}
return o;
}());
thanks for the time !
You can use filter function :
function greaterThanThree(element){
return element.length > 3;
}
var longer_words = ['f','as','i','with','on','that','this','can','has','if'].filter(greaterThanThree);
//Will return ["with", "that", "this"]
Hope this helps.

Generate 7 unique random numbers in javascript

I have a project i'm working on.
I am to basically recreate lotto on the client side using javascript to generate 6 random numbers plus a bonus ball. as we all know, lotto numbers cannot be the same. this is where my question comes in.
Is it possible to remove a number that has been generated from being available in the next time round in the loop? This would make the function completely random. or do I need to still compare the number with the others in the array using indexOf?
for example, is the following possible?,
the first number that generates is 25,
the function then removes that number from being able to come up again.
so on...
Here is my js code,
function play(){
numbersArray = [];
for (i=0; i<=6;){
n = Math.floor(Math.random()*40)+1;
a = numbersArray.indexOf(n);
if ( a == "-1"){
numbersArray[i] = n;
i++;
var ballId = "ball"+i;
if( i != "7"){
document.getElementById(ballId).innerHTML = '<p>'+ n +'</p>';
} else {
document.getElementById("bonus").innerHTML = '<p>'+ n +'</p>';
}
} //end of if
}//end of for loop
}//end of play function
You need to create an object, in this case you could use an array, that holds all the possible numbers that can appear on the ball, we'll cal it n. Then you can use a while loop to keep picking numbers from that array, and splice/remove that specific number from the array on every iteration.
function play(n) {
var picks = [];
// Store possibilities in the numbersArr array
var numbersArr = [];
// n is the max number you can choose to appear on a ball
for ( var i = 0; i < n; i++ ) {
numbersArr.push(i);
}
while (picks.length < 7){
var randomIndex = Math.floor(Math.random() * numbersArr.length);
picks.push(numbersArr[randomIndex]);
numbersArr.splice(randomIndex, 1);
}
return picks;
}

better solution than a switch for change classNames

I have created a clock, that connected to date().getHours / minutes /Seconds
The images that are shows are embedded in different classes.
Now when i want to change the images i wrote a switch for every second minute and hours..
Thats probably more code than googles engine. So i wonder if there is a more simple solution.
This is some code of the hour switch
so when minute 15 gets to the clock it change the className to one and five.
switch(h){
case 15:
x = hours.appendChild(hour1).className = "clock-digit-one";
x = hours.appendChild(hour2).className = "clock-digit-five";
break
case 16:
x = hours.appendChild(hour1).className = "clock-digit-one";
x = hours.appendChild(hour2).className = "clock-digit-six";
break
default:
x = hours.appendChild(hour1).className = "clock-digit-zero";
x = hours.appendChild(hour2).className = "clock-digit-zero";
}
I have created a jsFiddle that shows more of the code.
Any tips would be great.
http://jsfiddle.net/Xk49c/2/
Thanks
Create an array of human-readable numbers:
var digits = ["zero", "one", "two", ..., "nine"];
Break down h into first and second digit:
var hours = Math.floor(h / 10);
var minutes = h % 10;
Index into digits to determine the class name you should be using:
hours.appendChild(hour1).className = "clock-digit-" + digits[hours];
hours.appendChild(hour2).className = "clock-digit-" + digits[minutes];
Of course there is a simpler solution. For example, you can make class names such as clock-digit-[number] and then use string concatnation to make the className:
x = hours.appendChild(hour1).className = "clock-digit-"+h;
To find out form which digits the time number consists, you can convert the number to string and .split() it. This is not the most effective way, but its simple and clear.
var numbers = h.toString().split(""); //Will give ["1","5"] for 15
Then you add numbers to your div using for loop:
for(var i=0; i<numbers.length; i++) { //We loop through ["1","5"]
var num = document.createElement("div"); //Use your element type here!
num.className = "clock-digit-"+numbers[i]; //Get either 1 or 5
hours.appendChild(num);
}
In case you wanted to use the original class names, you can create an Array, like #Jon proposed:
var digits = ["zero", "one", "two", ..., "nine"];
Then, the for loop would look like that:
for(var i=0; i<numbers.length; i++) { //We loop through ["1","5"]
var num = document.createElement("div"); //Use your element type here!
num.className = "clock-digit-"+digits[numbers[i]]; //Get either 1 or 5
hours.appendChild(num);
}
just expanding my initial comment
var digits = new Array("zero","one","two","three","four","five","six","seven","eight","nine");
var h=new Date().getHours().toString();
var m = new Date().getMinutes().toString();
var s = new Date().getSeconds().toString();
var t = ((h>9?h:"0"+h)+ (m>9?m:"0"+m) +(s>9?s:"0"+s));
hours.appendChild(hour1).className = "clock-digit-" + digits[t.substring(0,0+1)];
hours.appendChild(hour2).className = "clock-digit-" + digits[t.substring(1,1+1)];
minutes.appendChild(minute1).className = "clock-digit-" + digits[t.substring(2,2+1)];
minutes.appendChild(minute2).className = "clock-digit-" + digits[t.substring(3,3+1)];
seconds.appendChild(second1).className = "clock-digit-" + digits[t.substring(4,4+1)];
seconds.appendChild(second2).className = "clock-digit-" + digits[t.substring(5,5+1)];
I would suggest a solution that keeps an associative array of digits to their associated classes. Then you only need two lines to set each digit (instead of every single combination of two digits individually)
Something along these lines:
var digitToClass = {
0: 'clock-digit-zero',
1: 'clock-digit-one',
2: 'clock-digit-two',
3: 'clock-digit-three'
//..
};
var minute = "03";
minutes1.className = digitToClass[minute[0]];
minutes2.className = digitToClass[minute[1]];
Create an array of the class names and refer to its index (60 items), that's better than a switch.
EDIT: Others have posted examples and better solutions, but the logic is that an array is the best solution.

Categories

Resources