Javascript string to object error? random array var not aloowed - javascript

I want create a array from array by random, but I'm starting on javascript. Here is my question.
//array
var t = ["house","pen","table","eletronic"];
//-> selected a name option 0
var w = t[0]; // selected
var x = w;
var y = 0 to 3; // random
var house =["red","blue","orange","black"];
var pen =["silver", "gold", "cooper","plastic"];
var table =["marble","oak","yep","pine"];
var eletro=["computer","mobile","mac","tablet"];
// what i wish
var z = house[0]; // return red // x = typeof return object
//x this is the error type string not recognize list array query
var z = x[y]; // x = typeof return string
var z = "house"[0]; // return h - return string - not object
//after make a default
var a = x[y]; //y != y
var b = x[y]; //y != y
document.getElementById("demo1").innerHTML=z; // blue house;
document.getElementById("demo2").innerHTML=a; // silver pen;
document.getElementById("demo3").innerHTML=b; // marble table;
<p id "demo1"></p>
<p id "demo2"></p>
<p id "demo3"></p>
I think I must convert double quotes - "house" - string to object - house - to convert to a var and before feed the system?

I'm not 100% sure what you're asking here, but the behaviour i believe you want can be accomplished using 2d arrays as such -
const t = [["red","blue","orange","black"], ["silver", "gold", "cooper","plastic"], ["marble","oak","yep","pine"], ["computer","mobile","mac","tablet"]]
const [rand1, rand2] = [Math.floor(Math.random() * t.length), Math.floor(Math.random() * t[0].length)]
console.log(t[rand1][rand2])

It's not quite clear to me if this is what you're looking for, but one solution might be to structure your data so that it's easier to get at:
const items = {
house: ["red","blue","orange","black"],
pen: ["silver", "gold", "cooper","plastic"],
table: ["marble","oak","yep","pine"],
eletro: ["computer","mobile","mac","tablet"]
}
const randomChoice = list => list[Math.floor(list.length * Math.random())]
const randomObject = (items) => {
const itemType = randomChoice(Object.keys(items))
const modifier = randomChoice(items[itemType])
return `${modifier} ${itemType}`
}
randomObject(items) //=> "marble table" or "plastic pen", etc.
Update
The comment asked to pick a random element of a certain type. This variation would allow for that:
const randomOfType = (items, itemType) => {
const modifier = randomChoice(items[itemType])
return `${modifier} ${itemType}`
}
const randomObject = (items) => randomOfType(items, randomChoice(Object.keys(items)))
randomOfType(items, 'table') //=> "oak table" or "marble table", etc.

You could use the eval() function to obtain the object reference, but it could lead to hairy problems so it would better use another option like for example a switch statement:
//array
var t = ["house","pen","table","electronic"];
var house = ["red","blue","orange","black"];
var pen = ["silver", "gold", "cooper","plastic"];
var table = ["marble","oak","yep","pine"];
var electronic = ["computer","mobile","mac","tablet"];
var w = Math.floor(Math.random() * 3); // random type index (0 to 3)
var x = t[w]; // name of the random type
var y = Math.floor(Math.random() * 3); // random option (0 to 3)
switch (w) { // use the appropriate object based on type index
case 0: z=house[y]; break;
case 1: z=pen[y]; break;
case 2: z=table[y]; break;
case 3: z=electronic[y]; break;
}
console.log(w, z);
var z = z + ' ' + x // appending "house" to color
console.log(z);
document.getElementById("demo1").innerHTML=z;
<p id="demo1"></p>
<p id="demo2"></p>
<p id="demo3"></p>

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 do I iterate the price in parentheses and add it to the total price, My code doesn't seem to work

I've found this on google and gave it a go. But it seems as if its not doing anything. it isn't updating the price total area at all, nor is it adding or subtracting.
<script type="text/javascript">
function doMath() {
// Capture the entered values of two input boxes
var my_input1 = document.getElementsByName("case").value;
var my_input2 = document.getElementsByName("cpu").value;
var my_input3 = document.getElementsByName("cooling").value;
var my_input4 = document.getElementsByName("ram").value;
var my_input5 = document.getElementsByName("gpuchoice").value;
var my_input6 = document.getElementsByName("storage").value;
var my_input7 = document.getElementsByName("storage1").value;
var my_input8 = document.getElementsByName("storage2").value;
var my_input9 = document.getElementsByName("powersupchoice").value;
var my_input10 = document.getElementsByName("fans").value;
var my_input11 = document.getElementsByName("lighting").value;
var my_input12 = document.getElementsByName("sleeving").value;
var my_input13 = document.getElementsByName("peripherals").value;
var my_input14 = document.getElementsByName("headsets").value;
var my_input15 = document.getElementsByName("controllers").value;
var my_input16 = document.getElementsByName("wirelessadapter").value;
// Add them together and display
var sum = parseInt(my_input1) + parseInt(my_input2) + parseInt(my_input3) + parseInt(my_input4) + parseInt(my_input5) + parseInt(my_input6) + parseInt(my_input7) + parseInt(my_input8) + parseInt(my_input9) + parseInt(my_input10) + parseInt(my_input11) + parseInt(my_input12) + parseInt(my_input13) + parseInt(my_input14) + parseInt(my_input15) + parseInt(my_input16);
document.getElementsByName("text2").value = sum;
document.getElementsByName("text2").innerHTML = sum;
}
</script>
Any advice, or a better way of handling this perhaps?
The code works, but it wont get the data price of storage 1 or storage 2, with those two removed from the sum function it adds the totals of everything else perfect. just not these two inputs.
<select name="storage1" id="storage1">
<option data-productprice="45.00" value="None" selected>None</option>
<option data-productprice="45.00" value="Crucial MX500 SSD 500 GB (+$0.00)">Crucial MX500 500 GB (+$0.00)</option>
<option data-productprice="45.00" value="Crucial MX500 SSD 1 TB (+$0.00)">Crucial MX500 1 TB (+$0.00)</option>
<option data-productprice="45.00" value="Crucial MX500 SSD 2 TB (+$0.00)">Crucial MX500 2 TB (+$0.00)</option>
</select>
here is the JS that is broken with the storage options in sum function, remove the parseFloat(my_input7) everything works great. put it back in and NAN haha
function doMath() {
//var regExp = /\(([^)]+)\)/;
//var matches = regExp.exec("I expect five hundred dollars ($500).");
// Capture the entered values of two input boxes
var my_input1 = document.querySelector('[name=case]:checked').dataset.productprice;
var my_input2 = document.querySelector('[name=cpu]:checked').dataset.productprice;
var my_input3 = document.querySelector('[name=cooling]:checked').dataset.productprice;
var my_input4 = document.querySelector('[name=ram]:checked').dataset.productprice;
var my_input5 = document.querySelector('[name=gpuchoice]:checked').dataset.productprice;
var my_input6 = document.querySelector('[name=storage]:checked').dataset.productprice;
var my_input7 = document.querySelector('[name=storage1]').dataset.productprice;
var my_input8 = document.querySelector('[name=storage2]').dataset.productprice;
var my_input9 = document.querySelector('[name=powersupchoice]:checked').dataset.productprice;
var my_input10 = document.querySelector('[name=fans]:checked').dataset.productprice;
var my_input11 = document.querySelector('[name=lighting]:checked').dataset.productprice;
var my_input12 = document.querySelector('[name=sleeving]').dataset.productprice;
var my_input13 = document.querySelector('[name=peripherals]').dataset.productprice;
var my_input14 = document.querySelector('[name=headsets]').dataset.productprice;
var my_input15 = document.querySelector('[name=controllers]').dataset.productprice;
var my_input16 = document.querySelector('[name=wirelessadapter]').dataset.productprice;
// Add them together and display
var sum = parseFloat(55.00) + parseFloat(50.25) + parseFloat(20.55) + parseFloat(my_input1) + parseFloat(my_input2) + parseFloat(my_input3) + parseFloat(my_input4) + parseFloat(my_input4) + parseFloat(my_input6) + parseFloat(my_input7);
document.getElementById('pricetotal').value = sum;
document.getElementById('text2').innerHTML = sum;
}
I have solved it due to the two wonderful people that posted there answers! I read up on what you guys recommended and ended up using this to fix it due to the select option field.
Code is below :D
function doMath() {
var my_input1 = document.querySelector('[name=case]:checked').dataset.productprice;
var my_input2 = document.querySelector('[name=cpu]:checked').dataset.productprice;
var my_input3 = document.querySelector('[name=cooling]:checked').dataset.productprice;
var my_input4 = document.querySelector('[name=ram]:checked').dataset.productprice;
var my_input5 = document.querySelector('[name=gpuchoice]:checked').dataset.productprice;
var my_input6 = document.querySelector('[name=storage]:checked').dataset.productprice;
var my_input7 = document.querySelector('[name=storage1]');
var my_input8 = document.querySelector('[name=storage2]');
var my_input9 = document.querySelector('[name=powersupchoice]:checked').dataset.productprice;
var my_input10 = document.querySelector('[name=fans]:checked').dataset.productprice;
var my_input11 = document.querySelector('[name=lighting]:checked').dataset.productprice;
var my_input12 = document.querySelector('[name=sleeving]');
var my_input13 = document.querySelector('[name=peripherals]:checked').dataset.productprice;
var my_input14 = document.querySelector('[name=headsets]');
var my_input15 = document.querySelector('[name=controllers]');
var my_input16 = document.querySelector('[name=wirelessadapter]');
var valueofssd1 = my_input7.options[my_input7.selectedIndex].dataset.productprice;
var valueofssd2 = my_input8.options[my_input8.selectedIndex].dataset.productprice;
var valueofsleeving = my_input12.options[my_input12.selectedIndex].dataset.productprice;
var valueofheadset = my_input14.options[my_input14.selectedIndex].dataset.productprice;
var valueofcontroller = my_input15.options[my_input15.selectedIndex].dataset.productprice;
var valueofadapter = my_input16.options[my_input16.selectedIndex].dataset.productprice;
// Add them together and display
var sum = parseFloat(my_input1) + parseFloat(my_input2) + parseFloat(my_input3) + parseFloat(my_input4) + parseFloat(my_input5) + parseFloat(my_input6) + parseFloat(my_input9) + parseFloat(my_input10) + parseFloat(my_input11) + parseFloat(my_input13) + parseFloat(valueofssd1) + parseFloat(valueofssd2) + parseFloat(valueofsleeving) + parseFloat(valueofheadset) + parseFloat(valueofcontroller) + parseFloat(valueofadapter);
document.getElementById('pricetotal').value = "$" + sum + ".00";
document.getElementById('text2').innerHTML = "$" + sum + ".00";
}
I write an answer as it's a bit too long for a comment.
There's a lot of mess both in your HTML code and in the way you try to select elements. You have a mix of <input> and <select> elements in your page, whose values you try to select and sum.
When you select <input> elements via getElementsByName, you select indeed a NodeList of elements (there are also some <h1> inside!), so you have to narrow them to the ones you really need to get their value.
The right selections for your elements would be:
var my_input1 = document.querySelector('[name=case]:checked').value;
var my_input2 = document.querySelector('[name=cpu]:checked').value;
var my_input3 = document.querySelector('[name=cooling]:checked').value;
var my_input4 = document.querySelector('[name=ram]:checked').value;
var my_input5 = document.querySelector('[name=gpuchoice]:checked').value;
var my_input6 = document.querySelector('[name=storage]:checked').value;
var my_input7 = document.querySelector('[name=storage1]').value;
var my_input8 = document.querySelector('[name=storage2]').value;
var my_input9 = document.querySelector('[name=powersupchoice]:checked').value;
var my_input10 = document.querySelector('[name=fans]:checked').value;
var my_input11 = document.querySelector('[name=lighting]:checked').value;
var my_input12 = document.querySelector('[name=sleeving]').value;
var my_input13 = document.querySelector('[name=peripherals]').value;
var my_input14 = document.querySelector('[name=headsets]').value;
var my_input15 = document.querySelector('[name=controllers]').value;
var my_input16 = document.querySelector('[name=wirelessadapter]').value;
Still too much cumbersome to be honest, but at least it selects the right elements.
But, also this way it won't work for your purposes. That's because sometimes your <input>/<select> elements have a value like value="45", some other times they have a value like value="Moroval Diamond Mesh Case"; this way, they are not summable:
"45" + "Moroval Diamond Mesh Case" // will yield the string "45Moroval Diamond Mesh Case"
That's the exact list of values you would get from my code above:
"45" // parseInt() -> 45
"Ryzen 5 3600 (+$0.00)" // parseInt() -> NaN
"Thermaltake TH120 RGB (+$0.00)" // parseInt() -> NaN
"Corsair Vengeance LPX 16 GB (2 x 8 GB) DDR4-3200 Memory (+$0.00)" // parseInt() -> NaN
"XFX Radeon RX 6500 XT 4 GB Speedster QICK 210" // parseInt() -> NaN
"Samsung 970 Evo Plus M2 NVME SSD 500 GB (+$0.00)" // parseInt() =-> NaN
"None" // parseInt() -> NaN
"None" // parseInt() -> NaN
"Corsair CX 650M 650 WATT BRONZE Power Supply (+$0.00)" // parseInt() -> NaN
"Artic P12 Non-RGB Case Fans x3 (+$0)" // parseInt() -> NaN
"No Lighting Selected" // parseInt() -> NaN
"None" // parseInt() -> NaN
undefined // parseInt() -> NaN
"None" // parseInt() -> NaN
"None" // parseInt() -> NaN
"No Wireless Adapter" // parseInt() -> NaN
The only number comes from the first selection. Others are strings or undefined, so parseInt() won't be a number but NaN (Not a Number).
Edit (based on #MikeT comment):
It's better to always use numbers for value attribute in this case. Something like (random numbers):
Consider that in your <select> elements, each <option> tag should always have a unique identifier as value (to be sure to uniquely identify each option):
// select HTML element
<select name="headsets" id="headsets">
<option value="1">None</option>
<option value="2">Razer BlackShark V2 Pro 7.1 Wireless (+$100.00)</option>
<option value="3">HyperX Cloud II 7.1 Wireless (+$95.00)</option>
<option value="4">Corsair Void RGB Elite 7.1 Wireless (+$87.60)</option>
<option value="5">Logitech G935 DTS:X 7.1 Wireless (+$156.99)</option>
</select>
// hard-coded array of products to link selected value and price. probably a database-based solution is a better choice
const headsets = [
{ id: 1, description: 'None', price: 0 },
{ id: 2, description: 'Razer BlackShark V2 Pro 7.1 Wireless', price: 100 },
{ id: 3, description: 'HyperX Cloud II 7.1 Wireless', price: 95 },
{ id: 4, description: 'Corsair Void RGB Elite 7.1 Wireless', price: 87.6 },
{ id: 5, description: 'Logitech G935 DTS:X 7.1 Wireless', price: 156.99 },
];
// this is the price to sum
const selectedHeadsetPrice = headsets.find(item => item.id === +document.getElementById('headsets').value).price;
as #cheesyMan says your html is a mess and you are trying to brute for something that is better handled by finesse
i would aim for something more like this
const headsetData = { // preferably this would be read form a database or other not on page source
"none":{
display:"None",
price:0
},
"rzp7":{
display:"Razer BlackShark V2 Pro 7.1 Wireless (+$100.00)",
price:100
},
"hxc7":{
display:"HyperX Cloud II 7.1 Wireless (+$95.00)",
price:95
},
}
you could then populate from this list
const headsetselect = document.querySelector('select[name=headsets]')
for(const [key, {display} of Object.entries(headsetData)){
const opt = document.createElement("option");
opt.value = key;
opt.innerHTML = display;
headsetselect .appendChild(opt );
}
and then at the calculation stage you would do
const headsetselect = document.querySelector('select[name=headsets]')
total += headsetData[headsetselect.value].price
though if you follow best practice and ids are unique per element then
document.getElementById("headset")
would be be better than a query selector
edit:
you mention that you also wanted the text for an email
which can also be easilty accompliched like this
const product = headsetData[headsetselect.value]
text += `${product.display} ( ${product.price})`

Implementing Binomial DIstribution in JavaScript error?

I'm just hoping someone could double check my implementations to make sure everything is correct on the math and JS sides. I'm wondering where my implementation went wrong b/c the formulas do not compute the same probabilities, specifically probability_three seems to have a computation error I cannot find.
Here's the JSFiddle: https://jsfiddle.net/s73Lh1fk/5/
There are 3 functions I'm hoping to get reviewed.
probability_one
probability_two
probability_three
The formulas are as follows.
P(d, n) = 1 - (d - 1 / d)^n
P(d, n, o) = 1 - (d - (d - o + 1) / d)^n
P(d, n, o, k) = nCk * (p * k) * q^(n−k)
for nCk, I implemented https://www.calculatorsoup.com/calculators/discretemathematics/combinations.php
function factorialize(num) {
// Step 1. Create a variable result to store num
var result = num;
// If num = 0 OR num = 1, the factorial will return 1
if (num === 0 || num === 1)
return 1;
// Instatiate the while loop
while (num > 1) {
// Decrement by 1
num--
// Update the result
result *= num
}
// Return
return result;
}
function nCr(n, r){
// Compute n factorial
var nFact = factorialize(n)
// Compute r factorial
var rFact = factorialize(r)
// Compute n - r factorial
var nrFact = factorialize(n - r)
// Compute nCr
var result = (nFact / (rFact * nrFact))
// Return
return result
}
If you need any more information, please don't hesitate to ask. I'll do my best to provide it.
For example:
The result here is 9.75%
function probability_one() {
// Get number of dice
var n = document.getElementById("n1").value
// Get sides on each die
var d = document.getElementById("d1").value
// Calculate
var prob = 1 - ((d - 1) / d)**n
prob = parseFloat(prob*100).toFixed(2)+"%"
prob = `<B>${prob}</B>`
// Print the probability
var p = document.createElement('p')
p.innerHTML = prob
document.getElementById("output1").appendChild(p)
}
The result here is 9.75%
function probability_two() {
// Get number of dice
var n = document.getElementById("n2").value
// Get sides on each die
var d = document.getElementById("d2").value
// Get the specific outcome
var o = document.getElementById("o2").value
// Calculate
var prob = 1 - ((d - (d - o + 1)) / d)**n
prob = parseFloat(prob*100).toFixed(2)+"%"
prob = `<B>${prob}</B>`
// Print the probability
var p = document.createElement('p')
p.innerHTML = prob
document.getElementById("output2").appendChild(p)
}
The result here is 18.00%, not 9.75%
function probability_three(){
// USER INPUTS
// Get number of dice
var n = document.getElementById("n3").value
// Get sides on each die
var d = document.getElementById("d3").value
// Get the value that defines a success
var o = document.getElementById("o3").value
// Get the number of success needed
var k = document.getElementById("k3").value
// CALCULATIONS
// p
var p = ((d - o) + 1)/10
console.log(`p: ${p}`)
// q
var q = (1 - p)
console.log(`q: ${q}`)
// nCr
var vnCr = nCr(n, k)
console.log(`nCr: ${vnCr}`)
// p**k
var pk = p**k
console.log(`p**k: ${pk}`)
// q**n-k
var pnk = q**(n-k)
console.log(`q**n-k: ${pnk}`)
// Probability
var prob = (vnCr * pk * pnk) / (p + q)**n
console.log(`Prob.: ${prob}`)
prob = parseFloat(prob*100).toFixed(2)+"%"
prob = `<B>${prob}</B>`
// Print the probability
var p = document.createElement('p')
p.innerHTML = prob
document.getElementById("output3").appendChild(p)
}

Resulting "undifined" after using splice

Im trying to code a random houses generator in JS for a game of thrones game,
the code looks like that at the moment:
//Houses Array:
var HousesArray = [
'Stark',
'Lanister',
'Greyjoy',
'Barathion',
'Arryn',
'Tyrell',
'Martell',
'Targaryen'
];
//Houses Variables:
var house1 = {}
var house2 = {}
var house3 = {}
//Random House Generator
var RandomIndex = Math.floor(Math.random()*HousesArray.length)
var RandomElement = HousesArray[RandomIndex]
//3 Players Generator:
house1 = RandomElement
console.log(house1)
HousesArray.splice(house1,1)
RandomElement = HousesArray[RandomIndex]
house2 = RandomElement
console.log(house2)
HousesArray.splice(house2,1)
RandomElement = HousesArray[RandomIndex]
house3 = RandomElement
console.log(house3)
What I tryed to do here is to give the house1 variable a random house name from one of the HousesArray Eelements,
echo that to the console log,
then remove the selected element from HousesArray using the splice commend (to ensure that the next selection will not be the same one).
after all that - generate new house name from the elements left in the HousesArray and repeat.
But for some reasos, Every time house1 = "Targaryen" (or house2) the next 2/1 resolts automaticly return "undifined" (I beleive its becuse the "Targaryen" element is the last in the list)
How can i fix that?
Your code is not working because RandomIndex is always the same, if it's 7, it will return undefined because splice modifies the original array by removing the found House,
change RandomIndex to be a function to call everytime so it generates a new index using the new length of the array:
var RandomIndex = () => Math.floor(Math.random() * HousesArray.length)
//Houses Array:
var HousesArray = [
'Stark',
'Lanister',
'Greyjoy',
'Barathion',
'Arryn',
'Tyrell',
'Martell',
'Targaryen'
];
//Houses Variables:
var house1 = {}
var house2 = {}
var house3 = {}
//Random House Generator
var RandomIndex = () => Math.floor(Math.random() * HousesArray.length)
var RandomElement = HousesArray[RandomIndex()]
//3 Players Generator:
house1 = RandomElement
console.log(house1)
HousesArray.splice(HousesArray.indexOf(house1), 1)
RandomElement = HousesArray[RandomIndex()]
house2 = RandomElement
console.log(house2)
HousesArray.splice(HousesArray.indexOf(house2), 1)
RandomElement = HousesArray[RandomIndex()]
house3 = RandomElement
console.log(house3)
Doesn't appear you're using the splice method correctly here, it takes the first 2 arguments as numbers, and the third argument would be an element you want to replace it with if you'd like. Instead I would use a filter here:
let newHouseArray = HousesArray.filter(house => house !== house1)
This kept me stumped for quite a while, I would do something like this instead:
Now if you console.log(houses) you will get 3 random houses from random positions (as stated in the above comment) allowing players 2 and 3 to get houses earlier in position than players 1 and 2
Hope this helps :) seem's like a fun game:
//Houses Array:
var HousesArray = ['Stark', 'Lanister', 'Greyjoy', 'Barathion', 'Arryn', 'Tyrell', 'Martell', 'Targaryen'];
// stores the houses
var houses = [];
// Generates 3 random numbers and allows players 2 and 3 to get the houses early in position than player 1 and 2
var arr = [];
while (arr.length < 3) {
var r = Math.floor(Math.random() * 8);
if(arr.indexOf(r) === -1) arr.push(r);
}
// Pushed the houses to the house array
for (var x = 0; x < arr.length; x++) {
houses.push(HousesArray[arr[x]])
}
console.log(houses);

JavaScript Pattern Comparison

I'm working on a small machine learning theoretical algorithm using nodeJs.
My goal is to compare many array patterns to one source pattern then return how
similar they are represented as a percent . For an example pattern1 maybe 80% similar to the source pattern .
What can be the best method for determining percent similarity for one array to another?
What I've done so far..
//source
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60]
//patterns to compare
var sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60]
var sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62]
Since I've chosen a percent based outcome , I figured I should base my source pattern off percentage change from first value to second value in array .
var percentChange = (firstVal, secondVal) => {
var pChange = ((parseFloat(secondVal) - firstVal) /
Math.abs(firstVal)) * 100.00;
//To avoid NaN , Infinity , and Zero
if(!pChange || pChange == 0){
return 0.00000001
}
return pChange;
}
Here I will generate my source pattern from my source sequence
var storePattern = function(sequence){
var pattern = [];
for(var i = 0 ; i < sequence.length ; i++){
let $change = percentChange(sequence[i] , sequence[i + 1]);
if(i != sequence.length && $change ){
pattern.push($change)
}
}
return pattern;
}
var sourcePattern = storePattern(soureSequence);
Now I will create more patterns to be compared
var testPattern1 = storePattern(sequence1);
var testPattern2 = storePattern(sequence2);
Below is my comparison function
var processPattern = function(source , target){
var simularityArray = [];
for(var i = 0 ; i < target.length ; i++){
//Compare percent change at indexof testPattern to sourcePattern of same index
let change = Math.abs(percentChange(target[i] , source[i]));
simularityArray.push(100.00 - change);
}
var rating = simularityArray.reduce((a,b) => {
return a + b
});
//returns percent rating based of average of similarity pattern
rating = rating / parseFloat(source.length + ".00");
return rating;
}
Now I can try to estimate the similarity
var similarityOfTest1 = processPattern(sourcePattern , testPattern1)
My problem is that this only works on sequences within the same range of value .. for example 0.50 , 0.52 .. the percent change in these values would not be the same for 0.20 , 0.22 but the value difference is the same ie -> 0.02
I thought about a difference in value based pattern but at this point I'm lost.
All answers will be considered . Thanks for the help!
used reduce to get the difference than the average.
//patterns to compare
var sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60]
var sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62]
function diff(sequence){
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60]
var delta = soureSequence.reduce(function (r, a, i, aa) {
i && r.push(a - sequence[i]);
return r;
}, []),
average = delta.reduce(function (a, b) { return a + b; }) / delta.length;
return {delta:delta, average:average}
}
console.log('sequence1',diff(sequence1));
console.log('sequence2',diff(sequence2));
In my experience, the similarity of two vectors (arrays) is measured using the dot product ex. Like it says in that link, you multiply each corresponding elements of the arrays, add those up, then divide by the magnitude of each array (square root of the sum of the squares of each component). Rosetta Code has an example of the dot product in JavaScript, copied here
// dotProduct :: [Int] -> [Int] -> Int
const dotProduct = (xs, ys) => {
const sum = xs => xs ? xs.reduce((a, b) => a + b, 0) : undefined;
return xs.length === ys.length ? (
sum(zipWith((a, b) => a * b, xs, ys))
) : undefined;
}
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
const zipWith = (f, xs, ys) => {
const ny = ys.length;
return (xs.length <= ny ? xs : xs.slice(0, ny))
.map((x, i) => f(x, ys[i]));
}
So, you would call
const score1 = dotProduct(sourceSequence, sequence1);
const score2 = dotProduct(sourceSequence, sequence2);
And whichever is bigger is the closer sequence to sourceSequence.
I'm not sure you need machine learning for this. You have a source pattern and you have some inputs and you basically want to perform a diff of the patterns.
Machine learning could be used to find the patterns, assuming you have some heuristic for measuring the error (if you're using unsupervised learning techniques) or you have sample sets to train the network.
But if you are simply wanting to measure the differences between one pattern and another pattern then just perform a diff operation. What you'll need to do is decide what differences your measuring and how to normalize the result.
I can't tell how exactly you would like to measure the similarity. I go by calculating the difference of corresponding items and accumulating these differences to see how much deviation it would result from the sum of the source array. You can play with the calculation the way you like.
function check([x,...xs],[y,...ys], state = {sumSource: 0, sumDiff: 0}){
state.sumSource += x;
state.sumDiff += Math.abs(x-y);
return xs.length ? check(xs,ys,state) : (100 - 100 * state.sumDiff / state.sumSource).toFixed(4) + "% similarity";
}
var soureSequence = [0.53,0.55,0.50,0.40,0.50,0.52,0.58,0.60],
sequence1 = [0.53,0.54,0.49,0.40,0.50,0.52,0.58,0.60],
sequence2 = [0.53,0.55,0.50,0.42,0.50,0.53,0.57,0.62];
console.log(check(soureSequence,sequence1));
console.log(check(soureSequence,sequence2));

Categories

Resources