How can I us a single var for multiple values? - javascript

I am trying to get random values, getting random array elements.
The problem that when i generate them, they are the same.
This may be a stupid question, but how can I get a random value for each instance.
my HTML looks like this
Our Array consists of:<br>
<span id="massParts"></span><br><br>
Generating a word from syllables:<br>
<span id="oneWord"></span><br><br>
Generating a sentence from several words<br>
<span id="oneSentence"></span>
What I am trying to achieve is getting a sentence of randomly generated words. I seethe only solution to create multiple words and then putting them together. But this is not the solution for a bigger text.
my script is:
<script>
// creating an array of syllables
var parts = ["ing", "er", "a", "on", "po", "i", "re", "tion"];
var partsAsString = parts.join(', ');
// display syllables array elements
document.getElementById("massParts").innerHTML = partsAsString;
// getting random element from an array
var a = Math.floor(Math.random() * parts.length);
var b = Math.floor(Math.random() * parts.length);
var c = Math.floor(Math.random() * parts.length);
// making a word with one, two and three syllables
var oneSylWord = parts[a];
var twoSylWord = parts[a]+parts[b];
var threeSylWord = parts[a]+parts[b]+parts[c];
//putting three words into an array
var newWord = [oneSylWord, twoSylWord, threeSylWord];
// taking one of those free words fron the new array
var randWord = newWord[Math.floor(Math.random() * newWord.length)];
// display a random 1,2,3 syllable word
document.getElementById("oneWord").innerHTML = randWord;
// generating a sentence
var sentence = randWord + " " + randWord + " " + randWord + ".";
document.getElementById("oneSentence").innerHTML = sentence;
</script>
I understand that I display the same var randWord and that causes the repetition. but how can I avoid using multiple variables for it.
Thank you.
here is a jsfiddle https://jsfiddle.net/2j9jpcoo/

Put the code into a function and call it multiple times to get a (potentially) different value every time it is called:
function getRandomValue(arr);
return arr[Math.floor(Math.random() * arr.length)];
}
var sentence = getRandomValue(newWord) + " " + getRandomValue(newWord) + " " + getRandomValue(newWord) + ".";
Functions allow you to organize and reuse code. From the above link:
Functions are the bread and butter of JavaScript programming. The concept of wrapping a piece of program in a value has many uses. It is a tool to structure larger programs, to reduce repetition, to associate names with subprograms, and to isolate these subprograms from each other.

I liked the following algorithm in generating random numbers, according to this article where it mentions it is even better in performance but to be honest I did not benchmark it but you could check this in jsfiddle demo, just run it and see the benchmark results
// the initial seed
Math.seed = 6;
// in order to work 'Math.seed' must NOT be undefined,
// so in any case, you HAVE to provide a Math.seed
Math.seededRandom = function(max, min) {
max = max || 1;
min = min || 0;
Math.seed = (Math.seed * 9301 + 49297) % 233280;
var rnd = Math.seed / 233280;
return min + rnd * (max - min);
}

I re-organized your code a bit and created some re-usable functions to get a different random word each time. In this case we can skip the variable and use the return value from the function directly:
// creating an array of syllables
var a, b, c, newWord;
var parts = ["ing", "er", "a", "on", "po", "i", "re", "tion", "con", "de", "sta"];
var partsAsString = parts.join(', ');
// display syllables array elements
document.getElementById("massParts").innerHTML = partsAsString;
function shuffleLetters() {
// getting random element from an array
a = Math.floor(Math.random() * parts.length);
b = Math.floor(Math.random() * parts.length);
c = Math.floor(Math.random() * parts.length);
var oneSylWord = parts[a];
var twoSylWord = parts[a]+parts[b];
var threeSylWord = parts[a]+parts[b]+parts[c];
//putting three words into an array
newWord = [oneSylWord, twoSylWord, threeSylWord];
}
function getRandomWord() {
shuffleLetters();
// taking one of those free words fron the new array
return newWord[Math.floor(Math.random() * newWord.length)];
}
// making a word with one, two and three syllables
shuffleLetters();
// display a random 1,2,3 syllable word
document.getElementById("oneWord").innerHTML = getRandomWord();
// generating a sentence
var sentence = getRandomWord() + " " + getRandomWord() + " " + getRandomWord() + ".";
document.getElementById("oneSentence").innerHTML = sentence;

Related

Set a custom start and end range in an array that displays a random string?

I am playing around with JavaScript while preparing for my junior developer interview.
I am trying to write a function that accepts two parameters, a beginning point and an ending point, in an array. This function should generate a random name within a custom start and end point of the array. I seemed close to getting it right, but it displays NaN. What is NaN?
Here is the code I wrote.
const names = ['Kitana', 'Liu Kang', 'Sonya Blade', 'Johnny Cage', 'Jax Briggs', 'Smoke', 'Sheeva', 'Jade']
const section = document.querySelector('section')
const para = document.createElement('p');
// Add your code here
function random(beginIndex, endIndex) {
for (let beginIndex = 0; beginIndex < names.length; beginIndex = beginIndex + endIndex) {
let newRangeOfIndices = names[beginIndex]
const randomName = Math.floor(Math.random() * newRangeOfIndices)
para.textContent = randomName
}
}
random(2, 5)
// Don't edit the code below here!
section.innerHTML = ' ';
section.appendChild(para);
<section></section>
You will notice that I already set a custom limit in the function to be run, 2 to 5. But it's still not working. Please help me out.
You don't for loop to get a random number.
To get a random index.
let randomIndex = Math.floor(Math.random() * (endIndex - beginIndex + 1) + beginIndex)
Then get the random name from the names array.
let randomName = names[randomIndex]
const names = ['Kitana', 'Liu Kang', 'Sonya Blade', 'Johnny Cage', 'Jax Briggs', 'Smoke', 'Sheeva', 'Jade']
const section = document.querySelector('section')
const para = document.createElement('p');
// Add your code here
function random(beginIndex, endIndex) {
let randomIndex = Math.floor(Math.random() * (endIndex - beginIndex + 1) + beginIndex)
let randomName = names[randomIndex]
para.textContent = randomName
}
random(2, 5)
// Don't edit the code below here!
section.innerHTML = ' ';
section.appendChild(para);
<section></section>
The author asked two questions here...
the first one related to the code and here is my solution:
const names = ['Kitana', 'Liu Kang', 'Sonya Blade', 'Johnny Cage', 'Jax Briggs', 'Smoke', 'Sheeva', 'Jade'];
// create a generic randomName function that takes 3 parameters beginIndex, endIndex and an array which returns a random positioned value within the range
function randomName(beginIndex, endIndex, arr) {
const randomNumber = Math.floor(Math.random() * (endIndex - beginIndex + 1) + beginIndex);
return arr[randomNumber];
}
// call the function with the proper argument
randomName(2, 5, names);
the second question is What is NaN?
Answer: as stated by MDN Docs
The global NaN property is a value representing Not-A-Number.
When calculating numbers but sending a string value to parse, the JavaScript parser is throwing an error that it is Not-A-Number.
let's see we have two variables
let x = 10;
let y = 'hello';
console.log(typeof x); // number
console.log(typeof y); // string
// try to multiplied x by y
console.log(x * y); // NaN
In Your case:
function random(beginIndex, endIndex) {
for (let beginIndex = 0; beginIndex < names.length; beginIndex = beginIndex + endIndex) {
// this will be a string that extracts the value of the beginIndex position value from the names array.
let newRangeOfIndices = names[beginIndex]
// here you try to multiply the Random Number by a string and getting NaN
const randomName = Math.floor(Math.random() * newRangeOfIndices)
para.textContent = randomName
}
}
random(2, 5)
Best wishes for your interview
Use:
return Math.random() * (max - min) + min;
To get a number as min-max. Then, use the random number output as an index in the array. Always avoid for loops in situations like this - there is most likely always another way to do it.
Math.floor(Math.random()* (max_number)+min_number)
you are using string not index number.
newRangeOfIndices is giving the value of particular index.
this will work.

How to make value auto update when input numbers are changed in javascript?

Here is a link to the tip calculator - it's hosted on netlify.
I created a tip calculator using html, scss, javascript. no tutorials used, so I'm pretty proud. It took me waaayyyyy longer than I had planned on, but it's done. needless to say, I am a complete beginner.
In any event, I need some help.
I need to know how to make the numbers auto-update if I input a new dollar amount into the billing input.
For instance, if the bill is $50, and the tip percent is 50% that's a $25 tip Amount. for a total bill of $75 dollars.
But let's say I mistyped the bill, so I go back to put in $60, 50% of $60 is $30. so the total bill amount should auto-update to $90. But I can't figure out how to get all of that to happen instantaneously when I change the dollar amount in the billing input.
I have a feeling that it has something to do with using a "change" event listener. but I don't understand how to best implement it, or if that's even the answer here.
// Upper Box Selections
const tipPercent = document.querySelector(".tip-percent");
const tipSlider = document.querySelector("#tip-slider");
tipSlider.oninput = function () {
billInput = Number(document.querySelector("#bill-amt").value);
tipPercent.innerHTML = this.value + "%";
//Discovered that number input type still returns a string
//You can wrap multiple variables in parenthesis in order to append methods
let tipAmount = document.querySelector(".tip-amount");
// if a variable is referenced but not defined, it will be added to the window element - can now use in second function
tipTotal = Number((billInput * Number(this.value / 100)).toFixed(2));
tipAmount.innerHTML = "$" + tipTotal.toFixed(2);
const billTotal = document.querySelector(".bill-total");
billForSplit = Number(billInput + tipTotal).toFixed(2);
billTotal.innerHTML =
"<strong>$</strong>" + "<strong>" + billForSplit + "</strong>";
};
// Bottom Box Selections
// -Grab slider value
const splitSlider = document.querySelector("#split-slider");
splitSlider.oninput = function () {
// -Grab split person value-split PERSON for 1, people for more than 1
const splitPeople = document.querySelector(".split-people");
if (splitSlider.value <= 1) {
splitPeople.innerHTML = splitSlider.value + " person";
} else {
splitPeople.innerHTML = splitSlider.value + " people";
}
// -grab tip per person value
const splitTip = document.querySelector(".split-tip");
// -grab total bill per person value
const splitTotal = document.querySelector(".split-total");
// - tip per person equals tipTotal / split slider value
splitTip.innerHTML = "$" + (tipTotal / splitSlider.value).toFixed(2);
// -total bill/person = billTotal / splitSlider.value
splitTotal.innerHTML =
"<strong>$</strong>" +
"<strong>" +
(billForSplit / splitSlider.value).toFixed(2) +
"</strong>";
};
https://wonderful-meninsky-e0b1c7.netlify.app/
You should declare the function with a name like calcTotal() which will be run every time there is an input for the bill and tip:
const tipPercent = document.querySelector(".tip-percent");
const tipSlider = document.querySelector("#tip-slider");
function calcTotal() {
billInput = Number(document.querySelector("#bill-amt").value);
tipPercent.innerHTML = this.value + "%";
//Discovered that number input type still returns a string
//You can wrap multiple variables in parenthesis in order to append methods
let tipAmount = document.querySelector(".tip-amount");
// if a variable is referenced but not defined, it will be added to the window element - can now use in second function
tipTotal = Number((billInput * Number(this.value / 100)).toFixed(2));
tipAmount.innerHTML = "$" + tipTotal.toFixed(2);
const billTotal = document.querySelector(".bill-total");
billForSplit = Number(billInput + tipTotal).toFixed(2);
billTotal.innerHTML =
"<strong>$</strong>" + "<strong>" + billForSplit + "</strong>";
};
tipSlider.oninput = calcTotal;
document.querySelector("#bill-amt").oninput = calcTotal;

Javascript adding multiple arrays in a loop

I am trying to add multiple arrays in javascript.
Here are my arrays I have made, and are working.
function getAmountSpent(){
var amountSpent = ((Math.random() * 500) + 1);
return amountSpent.toFixed(2)
}
function getGift(){
var gift = ((Math.random()* 50) + 1);
return gift.toFixed(2)
}
var names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
var spent = [];
for (let i = 0; i < 5; i++) {
spent.push(getAmountSpent());
}
var gifts = [];
for (let i = 0; i<5; i++) {
gifts.push(getGift());
}
What I need help with is adding these arrays in a new function. I have began writing the code, and I am not sure what is wrong.
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals())
}
function getSumTotals(a){
totals= spent+(spent * gifts);
return totals.toFixed(2)
}
From what you can see, I am trying to add up the totals much like this:
totals[0] = spent[0] + (spent[0] * gifts[0]);
totals[1] = spent[1] + (spent[1] * gifts[1]);
totals[2] = spent[2] + (spent[2] * gifts[2]);
totals[3] = spent[3] + (spent[3] * gifts[3]);
totals[4] = spent[4] + (spent[4] * gifts[4]);
if it helps, the professor added guided instructions for function getSumTotals(a) stating:
This function will return the sum of the elements in array a.
You will be passing the array that holds your totals to
the parameter a. Be sure to treat the values in a as numbers.
I am not sure if this helps but here is the output to my document.
Current Total should equal (spent) + (spent * gifts). For instance, for Jeremy in this example, current total should equal:
$36.55 + ($36.55*0.0626) = $38.83. Since there are many variables involved, I am not 100% sure what I should write for function getSumTotals(a)
The parameter "a" is a placeholder because I am not sure how many parameter values I need, and the proper format I need to use.
As for the code...
You're both
not passing an index to getSumTotals
not using this parameter within getSumTotals to access your spent and gifts arrays
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals(i)) // you were missing i
}
function getSumTotals(idx) { // I took liberties to rename this
totals = spent[idx] + (spent[idx] * gifts[idx]);
return totals.toFixed(2);
}
Now for the Math...
All that said, this math of spent[i] + spent[i] * gifts[i] doesn't make much sense either. Was this specified in the problem?
you may use like this
defined gifts
gifts=[45,43,32];
defined spends
spends=[43,32,21];
this is the getSumTotal funtion
getSumTotal=(x)=>(x.a+x.b)
this is where added
totals=gifts.map((d1,i)=>{
return fu({a:gifts[i],b:spends[i]})
})
I understand this is your assignment, however - if the idea is to both generate arrays, and then add them together, it is a redundant step. Just use the name array to iterate once and do all your calculations within that single loop.
Here, I had some fun and took some liberties, but hopefully you see why multiple arrays are redundant.
function getSumTotals() {
const getAmountSpent = () => Math.random() * 500 + 1;
const getGift = () => Math.random() * 50 + 1;
const names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let totals = []
names.forEach((name, i) => {
let spent = getAmountSpent()
let gifts = getGift()
let $$$ = (spent + spent * gifts).toFixed(2);
totals[i] = $$$
console.log(`${name} cost me $${$$$}${'!'.repeat(($$$/1000) | 1)}`)
});
return totals;
}
getSumTotals()
Note, that toString returns a type of "String", but not "Number".
When you try to sum a number with string, you get a concatenated string "1" + 2 = "12"
To turn a string into Number, you must use a Number("str") function, or just a bunary + before the string:
console.log( "1" + 2 );
console.log( Number("1") + 2 );
console.log( +"1" + 2 );
Also, you use the same loop 3 times, but can use just one loop instead, and call all functions inside the one loop. And use your array.length instead of fixed number 5:
let names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let spent = [];
let gifts = [];
let totals = [];
for (let i = 0; i < names.length; i++) {
spent.push( getAmountSpent() );
gifts.push( getGift() );
totals.push( getSumTotals(i) );
}
console.log( totals );
function getAmountSpent() {
return rand(1, 500, 2);
}
function getGift() {
return rand(1, 50, 2);
}
function getSumTotals(i) {
return +( spent[i] * ( 1 + gifts[i] ) ).toFixed(2);
}
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
P.s. Math.random() returns a number between 0 (included) and 1 (not included). If you need a random number between (example) 20 and 100, Math.random()*(100-20) will give a number between 0 and 80. After adding +20 to the result, you get a number from 20 to 100. That's what does this formula Math.random()*( to - from ) + from
P.P.s. Another way, to get the same thing:
var names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"].reduce( (prev, elem) => {
let spent = rand(1, 500, 2);
let gift = rand(1, 50, 2);
prev[elem] = new UserData( spent, gift );
return prev;
}, {});
console.log( "Jeremy spent: " + names.Jeremy.spent );
console.log( names );
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
function UserData(spent, gift){
this.spent = spent;
this.gift = gift;
this.total = +(spent * ( 1 + gift )).toFixed(2);
}
/* Google → Array reduce, Constructor functions */
function getAmountSpent(){
let amountSpent = ((Math.random() * 500) + 1);
return Number(amountSpent.toFixed(2))
}
function getGift(){
let gift = ((Math.random()* 50) + 1);
return Number(gift.toFixed(2))
}
let names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
let spent = [];
let gifts = [];
let totals =[];
for (let i = 0; i < names.length; i++) {
spent.push(getAmountSpent());
gifts.push(getGift());
totals[i] = (spent[i]+(spent[i] * gifts[i])).toFixed(2);
totals[i] = parseFloat(totals[i])
}
Hi there
I don't think you need a function to add the totals. you just need to loop through and assign totals[i] to spent[i] + (spent[i] * gifts[i]).
then you can use the parseFloat and toFixed function to change the string to a number. remember toFixed() function turns numbers to string. so you need to use the parseFloat to change it to number again as shown in the code above. or you can come up with an easy way of changing it to number. I hope this helps!

stopping random choose existing option

In my game, when the "next-question" button is clicked, it should choose a new word in the grid for the user to spell. It does this, but the problem is that instead of going to another word, sometimes the randomization brings it back to the word it is already on. I need to make it so that it chooses any other than the one its on.
//Next question click event
$('.next-question').on('click', function () {
$('td').removeClass('highlight-problem');
var r = rndWord;
while (r == rndWord) {
rndWord = Math.floor(Math.random() * (listOfWords.length));
}
//Adds and removes nesesary classes
$('td[data-word="' + listOfWords[rndWord].name + '"]').addClass('highlight-problem');
$('td[data-word=' + word + ']').removeClass('wrong-letter').removeClass('wrong-word').removeClass('right-letter');
var spellSpace = $('td[data-word="' + listOfWords[rndWord].name + '"]').hasClass('right-word');
if (spellSpace) {
$(".next-question").eq(($(".next-question").index($(this)) + 1) %$(".next-question").length).trigger("click");
} else {
$("#hintSound").attr('src', listOfWords[rndWord].audio);
hintSound.play();
$("#hintPic").attr('src', listOfWords[rndWord].pic);
$('#hintPicTitle').attr('title', listOfWords[rndWord].hint);
}
});
What's the value of rndWord before your while loop? It looks like a scoping issue - you either need to declare rndWord outside your function so it's preserved between calls or pass it in every time.
var rndWord;
function() {
//Next question click event
....
var r = rndWord;
while (r == rndWord) {
rndWord = Math.floor(Math.random() * (listOfWords.length));
}
After further clarification:
var currentWord;
function ClickEventHere() {
r = currentWord;
while (r == currentWord) {
nextIndex = Math.floor(Math.random() * (listOfWords.length));
currentWord = listOfWords[nextIndex];
}
...
}
There's no point in comparing an integer r with an array as you're doing in your while statement - you can either store the index or the word itself in a global and then check to make sure it's not being reused.
After this loop, currentWord will contain the next, different word
Find random word, compare to last found if the same find another. Provided you have a decent number of words it should be enough.

Seeded random number

Ive been wondering for some time. Is there a good (And fast) way to make an number random while its seeded?
is there a good algorithm to convert one number into a seemingly random number.
A little illustration:
specialrand(1) = 8
specialrand(2) = 5
specialrand(3) = 2
specialrand(4) = 5
specialrand(5) = 1
specialrand(1) = 8
specialrand(4) = 5
specialrand(1) = 8
It would be very nice if the output could also be huge numbers.
As a note: I don't want to fill a array and randomize the numbers because I want to be able to feed it huge difference of numbers because I want the same output whenever I restart the program
You're not looking for a seeded random number. Instead what I think you're looking for is a hashing function. If you put in the same input and get the same output, that's not random.
If you're looking to generate a sequence of random numbers for a run, but have the same sequence generate from run to run, you can use a random number generator that generates the same sequence given the same seed value.
Thats how most basic pRNG's work. There are more cryptographically secure RNG's out there, but your standard Math.rand() should work to accomplish your needs.
Maybe pseudorandom number generators are what you are looking for.
For example the XORshift.
uint32_t xor128(void) {
static uint32_t x = 123456789;
static uint32_t y = 362436069;
static uint32_t z = 521288629;
static uint32_t w = 88675123;
uint32_t t;
t = x ^ (x << 11);
x = y; y = z; z = w;
return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
}
You could create something like this:
take a seed
specialrand(5) is a function which takes the fifth random number from this seed
or specialrand(5) is a function which gets the first random number from the seed+5
Maybe this is enough for your purpose.
Try setting a key or set of keys then writing a function with an equation to return a new number based on that key:
a very basic example would be:
function specialrand(value) {
key = array (1,2,4,6,8);
for (k in key) {
if (k%2 === 0) {
value -= key[k] * value;
} else {
value += key[k] / value;
}
}
return value;
}
however you could create a highly complex equation to generate your 'random' number and ensure you return the same number each time.
You can use Date functionality
Math.valueOfSeed = function(n)
{
return Number(new Date(n%9999, n%12, n%30, n%24, n%60, n%60, n%1000));
};
alert(Math.valueOfSeed(1) + " = " + Math.valueOfSeed(1));
alert(Math.valueOfSeed(2) + " = " + Math.valueOfSeed(2));
alert(Math.valueOfSeed(15) + " = " + Math.valueOfSeed(15));
alert(Math.valueOfSeed(5555) + " = " + Math.valueOfSeed(5555));
alert(Math.valueOfSeed(21212121) + " = " + Math.valueOfSeed(21212121));
alert(Math.valueOfSeed(6554654654) + " = " + Math.valueOfSeed(6554654654));​
test is here

Categories

Resources