I have static questions such as below. I'm using these questions for my quiz in my blog.
var quiz = {
"data": [
{
"question": "What is 10 + 5 ?",
"answer": "15",
},
{
"question": "What is 10 - 5 ?",
"answer": "5",
},
{
"question": "What is 10 + (- 5) ?",
"answer": "5",
},
{
"question": "What is -10 + 5 ?",
"answer": "-5",
},
{
"question": "What is -6 + (-6) ?",
"answer": "-12",
},
]
}
How can i make the questions & answer dynamic? In other words, each of the numbers will take a value between 1 and 20. The answer will be calculated based on the question.
thanks
function generateQuestion(template, min, max){
// Generate first random number
var numOne = Math.floor(Math.random() * (max - min) ) + min;
// Generate second random number
var numTwo = Math.floor(Math.random() * (max - min) ) + min;
// append first question part
var question = template[0];
// check if first number is negative to put brackets around the string
if(numOne < 0 )
question += "(" + numOne + ")";
else
question += numOne;
// append operator
question += " + ";
// check if second number is negative to put brackets around the string
if(numTwo < 0 )
question += "(" + numTwo + ")";
else
question += numTwo;
// append last part of question
question += template[1];
// return your object
return {
question: question,
answer: numOne + numTwo
};
}
var numberOfQuestions = 4;
var questions = [];
for(var i = 0; i < numberOfQuestions; i++)
questions.push(generateQuestion(["What is ", "?"], -20, 20))
console.log(questions);
I find the expr-eval package to be quite useful for use cases such as yours.
A simplified example:
const { Parser } = exprEval;
const randomNumber = (min, max) => Math.floor(Math.random() * max) + min;
const quiz = {
equation: `${randomNumber(1, 20)} + ${randomNumber(1, 20)}`,
get question() {
return `What is ${this.equation.toString()}`;
},
get answer() {
return `The answer is: ${Parser.evaluate(this.equation)} 👩🎓`;
},
};
console.log(quiz.question);
console.log(quiz.answer)
<script src="https://cdnjs.cloudflare.com/ajax/libs/expr-eval/2.0.2/bundle.js"></script>
You can use template literal and Math.random
// define all the airthmeatic operation
let operations = ["+","-","*","/"]
// map airthmeatic sign to related function
let funcs = {
"+" : (a,b)=> a+b,
"-" : (a,b)=> a-b,
"*": (a,b)=> a*b,
"/" : (a,b)=> a/b
}
// function to build random question
let randomQuizBuilder = (a,b,operation) =>{
let val = prompt(`what is ${a} ${operation} ${b}`)
console.log(+val === funcs[operation](a,b))
}
let i=2
// a loop to build a fix number of question
while(i--){
// get random value in range of 20
let a = Math.floor(Math.random() * 20)
let b = Math.floor(Math.random() * 20)
// select a random operation
let operation =operations[Math.floor(Math.random() * (operations.length))]
// call quizBuilder to build a random question
randomQuizBuilder(a,b, operation)
}
Related
i am in a bit tricky situation. I fetch some price values from a sqlite db and store it in a react state.
the response looks like: [{"price":50},{"price":"49,95"}]
i need to store these values as TEXT insted of INTEGER, because i have a lot of differrent decimal places. also using float in sqlite will not give me exact values, see the problem in this example: https://dba.stackexchange.com/questions/15729/storing-prices-in-sqlite-what-data-type-to-use
So to my main problem: how can i extract and convert the values from the json array to numbers, and sum it up?
If you don't want to use a library, you could convert all numbers to strings and write your own sum function for strings. This algorithm supports arbitrary long strings containing numbers and returns exact results without rounding errors.
function add(l, r, sep) {
if (!sep) sep = '.';
const [ll, lr] = l.split(/[,.]/).map(el => el.split('').map(Number));
const [rl, rr] = r.split(/[,.]/).map(el => el.split('').map(Number));
let carry = 0;
const result = [[], []];
for (let i = Math.max(lr?.length ?? 0, rr?.length ?? 0); i > 0; --i) {
result[1][i - 1] = (lr?.[i - 1] ?? 0) + (rr?.[i - 1] ?? 0) + carry;
carry = Math.floor(result[1][i - 1] / 10);
result[1][i - 1] %= 10;
}
for (let il = ll.length, ir = rl.length, iResult = Math.max(ll.length, rl.length); iResult > 0; --il, --ir, --iResult) {
result[0][iResult - 1] = (ll[il - 1] ?? 0) + (rl[ir - 1] ?? 0) + carry;
carry = Math.floor(result[0][iResult - 1] / 10);
result[0][iResult - 1] %= 10;
}
if (carry) result[0] = [carry, ...result[0]];
return result[0].join('') + sep + result[1].join('');
}
function sum(arr, sep) {
return arr.map(el => String(el.price)).reduce((acc, el) => add(acc, el, sep));
}
console.log(sum([{ "price": "0.9" }, { "price": "1.2" }], ','));
console.log(sum([{ "price": "100000000" }, { "price": "0.0000002" }]));
console.log(sum([{ "price": 123.123 }, { "price": "1234.5678" }, { "price": "9876,54321" }, { "price": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111.111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"}]));
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I am writing some JS and I can't seem to figure out how to write a function that will give a true or false statement back.
The way I want to write it is:
Loop function 5 times
on each loop give 1 of 8 random prizes
then check the probability of getting the prize, e.g 1 out of 10,000.
One of the loops has to provide with 1 as true
Any help is appreciated.
This is what I have tried, in terms of getting the probability
function prob(n) {
var old = n - 1;
var val = (n += 1);
return Math.floor(Math.random() * val) == old;
}
console.log(prob(2));
I generally use these helper functions if I need random
const chance = (percentage) => Math.random() * 100 < percentage;
const getRandomInt = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
const getRandomArbitrary = (min, max) =>
Math.random() * (max - min) + min;
console.log(chance(50));
console.log(getRandomInt(1, 10));
console.log(getRandomArbitrary(0, 5));
// Full code
const prizes = [{
name: 'Bear',
probability: 5,
},
{
name: 'Car',
probability: 0.02,
},
{
name: 'Poster',
probability: 90,
},
];
let count = 5;
while (count--) {
const prize = prizes[getRandomInt(0, prizes.length - 1)];
const win = chance(prize.probability);
console.log(`Prize: ${prize.name} - Won: ${win}`);
}
As the topic states what is the best way to make it so that when you pass an array of emotions/values, to show the closest value based on a numeric mapping in javascript?.
Assume that 'Glad' is the same thing as 'Happy', and 'Down' is the same thing as 'Sad'. Ithe code I've tried seems incredibly lengthy and gets bloated if I add more emotions/states (i.e. Angry). Aside from the emotions array, any new functions and data structures and variables can be changed/introduced.
for example, I can get a list of emotions:
let emotions = ['Happy','Happy','Sad','Glad','Angry'];
Now I want to return a string that reflects what the 'closest' emotion based on these 5 emotions.
For a better example, let's assume the values correspondent to each emotion is:
Angry = 1, Happy = 2, Sad = 3
I was trying something like:
var numb = 0;
for (var i = 0; i < emotions.length; i++) {
if (numb == 'Angry')
numb += 1;
if (numb == 'Happy' || numb == 'Glad')
numb += 2;
if (numb == 'Sad' || numb == 'Down')
numb += 3;
}
var average = numb / emotions.length;
// check which number is closer to
if (average < 1.5)
return 'Angry';
if (average >= 1.5 && < 2.5)
return 'Happy';
if (average > 2.5)
return 'Sad';
if (average == 1.5)
return 'Angry or Happy';
if (average == 2.5)
return 'Happy or Sad';
My expected result based on this list of emotions is:
2(*Happy*) + 2(*Happy*) + 3(*Sad*) + 2(*Happy|Glad*) + 1(*Angry*) = 10
Then divide by 5 (the emotions array length), resulting in 2.
So the result that should be returned, as string, is "Happy".
Let's say I added a fourth type of emotion/feeling... I would be adding more and more of these conditions, and it gets more complicated in the logic checking for the ranges of the numbers.
I am looking at the list of emotions as a whole, and trying to come up with an overall emotion that represents the whole list.
What is the best way to do this so that the code looks clean and I can support more states without having the lines of code become too long?
What about something like this:
Having two object constants:
emotionsValues: Here you assing a value to each emotion you want, like a score to each.
emotionsRank: Here is the final result of each value, based on average you'll get the result from here.
Now:
Receive the emotions array by parameter.
reduce it based on the value of each mapped emotion (using emotionsValues).
Get the average
See if the floor value + ceil value divided by 2 is equal to the number itself (it means its exactly the half), so use the "emotion or emotion".
OR, if not the half, then round to the nearest and get the correct emotion. Don't forget to check if average is below 1 or bigger the the last rank (3 in this case)
const emotionsValues = {
"Angry": 1,
"Happy": 2,
"Glad": 2,
"Sad": 3,
"Down": 3,
}
const emotionsRank = {
1: "Angry",
2: "Happy",
3: "Sad",
}
function getEmotion(arrayEmot) {
let numb = arrayEmot.reduce((acc, v) => Number(emotionsValues[v]) + acc, 0);
let avg = numb / arrayEmot.length;
let min = Math.floor(avg)
let max = Math.ceil(avg)
if ((min + max) / 2 == avg && min != max) {
return emotionsRank[min] + " or " + emotionsRank[max]
} else {
let rounded = avg < 1 ? 1 : avg > 3 ? 3 : Math.round(avg);
return emotionsRank[rounded];
}
}
let emotionsTest = ['Happy', 'Happy', 'Sad', 'Glad', 'Angry'];
console.log(getEmotion(emotionsTest))
let emotionsTest2 = ['Happy', 'Happy', 'Sad', 'Sad'];
console.log(getEmotion(emotionsTest2))
You may create the function emo to value and its reciprocal one: value to emotionS:
Then you map every emotions found in array to its value
do your standard mathematical stuff
and get back to emotions via the reciprocal function
const emoToValue = {
Glad: 1,
Happy: 1,
Sad: 2
}
const valueToEmos = Object.entries(emoToValue).reduce((acc, [emo, val]) => {
acc[val] = acc[val] || []
acc[val].push(emo)
return acc
}, {})
//compute the average:
function avgEmotion (emotions) {
if (emotions.length == 0) return ''
const avg = emotions.reduce((s, em) => s + emoToValue[em], 0) / emotions.length
return valueToEmos[Math.round(avg)].join(' or ')
}
console.log('str', avgEmotion(['Happy', 'Happy', 'Sad', 'Happy'])) //Glad or Happy
console.log('str', avgEmotion(['Happy', 'Happy', 'Sad', 'Sad'])) //Sad
This function explicitly checks for the "mid" case and also for out of range values (since it's based on indices):
function getEmotion(emotions, value) {
// Out of range
if ( value > emotions.length ) return emotions[emotions.length - 1];
if ( value < 1 ) return emotions[0];
// Determine if decimal is .5
let mid = value % 1 === .5;
// Round the value to the nearest integer
let rounded = Math.round(value);
return mid ? `${emotions[rounded - 2]} or ${emotions[rounded - 1]}` : emotions[rounded - 1];
}
Output:
let emotions = ['Happy', 'Happy', 'Sad', 'Glad', 'Angry'];
console.log(getEmotion(emotions, -23)); // Happy
console.log(getEmotion(emotions, 0)); // Happy
console.log(getEmotion(emotions, 1)); // Happy
console.log(getEmotion(emotions, 2.43)); // Happy
console.log(getEmotion(emotions, 2.5)); // Happy or Sad
console.log(getEmotion(emotions, 3.1)); // Sad
console.log(getEmotion(emotions, 155.65)); // Angry
You could create a set of indices and get the values by filtering with the index.
function getEmotion(emotions, value) {
var values = new Set([value + 0.5, value - 0.5, Math.round(value)]);
return emotions.filter((e, i) => values.has(i + 1)).join(' and ');
}
console.log(getEmotion(['Happy', 'Sad', 'Glad', "Angry"], 1));
console.log(getEmotion(['Happy', 'Sad', 'Glad', "Angry"], 1.5));
console.log(getEmotion(['Happy', 'Sad', 'Glad', "Angry"], 1.7));
I need your help because I'm totally lost with a javascript exercise (I learn alone).
I cut the exercice in steps
I generate an aleatory number between 3 and 20 (with Maths Random)
I generate an array of 100 cells: In each cells, there is one " _ "
If the number is 5: 5 " _ " is aleatory replaced by a " # " (second Maths Random)
I think my cut is good but I can't write it in code.
Before this exercise I've done exercises easier with maths random but now it's more diffult for me.
Some can help me to create the code?
Thank you very much
edit: I tried to do something but without maths random.
function hashtagLine(){
var number = prompt( "Saisissez un nombre entre 3 et 10" );
var line = "";
if (number >= 1 && number <= 10){
for ( var i = 1; i <= 100; i++ ) {
if ( i % number === 0 ) {
line += "#";
} else {
line += "_";
}
}
console.log( line );
} else {
alert( "vous avez entré un nombre qui ne correspond pas" );
}
}
hashtagLine();
Here is a simple implementation:
HTML
<table id="table"></table>
JS
var t = document.getElementById('table');
var rnd = Math.ceil(Math.random() * 17 + 3);
var string = '<tr>';
for (var i = 1; i <= 100; i++) {
if (i == rnd) {
string += '<td>#</td>';
} else {
string += '<td>_</td>';
}
// for new row...
if (i % 10 == 0) {
string += '</tr><tr>';
}
}
string += '</tr>';
t.innerHTML = string;
But if you're trying to learn the language, it's best to try yourself, not just have somebody hand you the answer.
It is still not clear to me what you are trying to achieve, but here is some code that may help you. If you come back with more information then I may be able to help you some more.
Math.random
// get reference to out output element
var pre = document.getElementById('out');
// Returns a random integer between min (included) and max (excluded)
// Using Math.round() will give you a non-uniform distribution!
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
function hashtagLine() {
var min = 3,
max = 20,
cells = 100,
number = getRandomInt(min, max + 1),
line = [],
index;
// create the line array of length cells
for (index = 0; index < cells; index += 1) {
// unclear what you are trying to do here!
if (index % number === 0) {
line.push('#');
} else {
line.push('_');
}
}
// output the array as a line of text
pre.textContent += line.join('') + '\n';
}
// Add a click event listener to our generate button
document.getElementById('generate').addEventListener('click', hashtagLine, false);
<button id="generate">Generate</button>
<pre id="out"></pre>
I have a simple implementation question.
Here is the random number function I have, and returns a random number from a given range, inclusive.
function randomNum(low, high){
return Math.floor(Math.random() * (high - low + 1)) + low;
}
However, I would like to have 50% chance of getting the high number, and 25% for everything else..
for example:
randomNum(1, 3)
'3' would have a 50% chance of getting a hit, while '1' and '2' will both have a hit percentage of 25%.
I'm not too sure as to what changes I need to make to my function...tips would be great, Thanks
function randomNum(low, high){
return Math.random() > 0.5 ?
high :
Math.floor(Math.random() * (high - low)) + low;
}
In a generic manner; I suppose you're after a weighted random number generator:
function weightedRandomNumber(weights) {
var sum = 0;
for (var w in weights) {
w = weights[w];
sum += w.weight;
}
var rand = Math.random() * sum;
for (var w in weights) {
w = weights[w];
if (rand < w.weight) {
return w.value;
}
rand -= w.weight;
}
return weights[weights.length - 1].value;
}
Test:
var config = [
{ weight: 25, value: 1 },
{ weight: 25, value: 2 },
{ weight: 50, value: 3 }
];
var test = { 1: 0, 2: 0, 3: 0 }, max = 10000;
for (var i = 1; i < max; i += 1) {
test[weightedRandomNumber(config).toString()] += 1;
}
alert('From ' + max + ' rounds; results: ' + JSON.stringify(test));
Make if else condition
If it is 3 its ok or else if it is not 3 then again make a random number between 1 and 2;
Hence the 3 will get 50% chances where as 1,2 will get 25% chances
There are two approaches that you can use. (1) You can have array of value and random the index of value to get. If you want certain number to have higher chance, just put it more. For example:
var arr = [1, 2, 3, 3];
return arr[Math.floor(Math.random() * arr.length)];
(2) Second approach is doing the array shuffling.
var arr[1, 2, 3, 3];
shuffle(arr);
return arr[0];
This should work:
function randomNum(low, high){
var mid = (low + high)/2;
var randomn = Math.floor(Math.random() * (high - low + 1)) + low;
if(randomn > mid)
return randomn ;
else
return Math.floor(Math.random() * (high - low + 1)) + low;
}
here you go. high will have 50% chance, the rest will split the other 50% equally
function randomNum(low, high)
{
var myarry = []
for(var i=0;i<(high-low);i++) { myarry.push(low+i) } ; //var myarry=[low, low+1, ....,high-1] excludes high
console.log(myarry)
var magic=Math.random();
var index=Math.round(magic*(high-low)); // Gaurantee the chance is split between the elements of the array
return Math.round(magic)==1?high:myarry[index] // Guaranteed 50% chance for high either 0 or 1, the rest will split the chance
}