Evaluate a number to numbers in an array in JavaScript - javascript
I am making a random number generator to assign tasks. I want to give everyone a random number then generate the random number. I then want to list the people in order of how close they were.
I thought maybe to iterate through the array and find the absolute difference between the winningNumber and the numbers in the way. However, I'm not sure how to link the numbers back to the name in the list.
How can I evaluate these numbers?
Fiddle here.
HTML:
Random Number Assigner
<p>Have tasks to assign but no volunteers? Sign them up here</p>
<div id="input-area">
<input type="text" placeholder="Lucky person here" id="input">
<button id="button">Add Them!</button>
<br>
<br>
<button id="random">Generate Random Number</button>
</div>
<hr>
<div id="list-area">
<ul id="list"></ul>
</div>
CSS:
#input-area {
width: 100%;
border: 1px solid black;
}
JavaScript:
function randomNumber() {
return Math.round((Math.random()) * 100);
};
var randomNumberValue;
var winningNumber;
var myArray = [];
$(document).ready(function () {
console.log("The JavaScript has loaded");
$('#button').on('click', function () {
randomNumberValue = randomNumber();
var inputValue = $('#input').val();
if (inputValue === "") {
return;
};
$('#list').append("<ul>" + inputValue + ": " + randomNumberValue + " </ul>");
myArray.push(randomNumberValue);
$('#input').val("");
});
$('#random').on('click', function () {
myArray.sort();
winningNumber = randomNumber();
if (winningNumber === 0) {
winningNumber++;
};
console.log(myArray);
console.log("The winning number is: " + winningNumber);
for (var i = 0; i < myArray.length; i++) {
i - winningNumber;
};
console.log(myArray);
});
});
With some small adaptions:
function randomNumber() {
return Math.round((Math.random()) * 100);
};
var randomNumberValue;
var winningNumber;
var myArray = [];
$(document).ready(function () {
console.log("The JavaScript has loaded");
$('#button').on('click', function () {
var randomNumberValue = randomNumber();
var inputValue = $('#input').val();
if (inputValue === "") {
return;
};
// an item in a list is the <li> element
$('#list').append("<li>" + inputValue + ": " + randomNumberValue + " </li>");
// to simplify things I've used normal arrays for storage
// instead of a list of {key:value} pairs
// Advantage of {key:value} pairs here would be an easier check for multiple name entries
myArray.push([randomNumberValue,inputValue]);
$('#input').val("");
});
$('#random').on('click', function () {
// not needed in this simple algorithm
// You can use a binary search if the array is sorted which would make it faster
// but also much more complicated and isn't worth the hassle for small lists
//myArray.sort();
var winningNumber = randomNumber();
// get the first number for a start (numbering starts at zero)
var current = myArray[0][0];
// we need something to keep the position of the entry
var pos = 0;
console.log("The winning number is: " + winningNumber);
for (var i = 0; i < myArray.length; i++) {
// the actual number at position i in the array
var value = myArray[i][0];
/*
Compute two differences
a) between the drawn number and the actual number
b) between the drawn number and the last number that was
nearest to the last actual number
If the actual difference a is smaller than the last difference
it is better, hence we keep it. We have to know where it was to
be able to name the winner and keep the position to do so.
*/
if(Math.abs(winningNumber - value) < Math.abs(winningNumber - current)){
current = value;
pos = i;
}
// No "else" here because, well, we don't need to do anything, just go on
// until something is found.
};
console.log("The winner is: " + myArray[pos][1]);
console.log(myArray.join(" | "));
});
});
One caveat: you do not check for double entries. Both, the name and the random number can repeat and need to be checked, otherwise it may fail in curious ways.
Related
I would like to know how I can make the "namePrinter" loop function work well?
I was trying to get javascript to print the result of the "generateName" function at least 10 times when I press a button in the html, so i tried a loop inside the function that generates the names and but it didn't work then I separated the loop and wrote it in the function "namePrinter" and create the global variable "names" to store the results of the function "generateName" but I don't know what part of this whole process is wrong, I already reviewed other questions that were made in this forum but I didn't find an answer either JS: //this run the funtion that prints the names document.getElementById("elvenFemButton").onclick = namePrinter; //cutting characters function function capFirst(string){ return string.charAt(10).toUpperCase() + string.slice(1); } //Randomizer function getRandomInt (min,max){ return Math.floor(Math.random() * (max-min)) + min; } //this function generates names using both "elfFemName" and "elfLastName" and the functions from above function generateName(){ var elfFemName1 = ["Adaia","Alisaie","Allisara","Alengwan","Alglaranna","Alachia","Alysia","Amberle","Anethra","Anwen","Apolline","Arathel","Ariane","Arianni","Ariel","Arwen","Ashalle","Ashniel","Atara","Ayara","Brelyna","Briala","Celebrían","Clothild","Cullich","Cylia","Dalish","Dirael","Eldyra","Elanor","Elenwen","Elezen","Ellia","Elynea","Éowyn","Failla","Faralda","Fleur","Freyalise","Galadriel","Gheyna","Jenassa","Katriel","Kira","Laina","Laniatte","Lauriel","Liallan","Liriel","Liselle","Loriel","Lorian","Lúthien","Máire","Mayael","Merril","Miara","Mihris","Minaeve","Nadja","Niranye","Nirya","Raewyn","Selveni","Sera","Shaera","Siofra","Taarie","Tauriel","Valora","Valya","Vanadis","Vanora","Velanna","Ylthin","Ysayle","Yvraine","Zelda"]; var elfLastName2 = ["Aearonian"," Agaraen","Agarher","Agarvran","Aire","Airendil","Amamion","Amdirthor","Amathal","Amather","Amathuilos","Amatheldir ","Amlugol","Aessereg","Aupwe","Calear","Caranagar","Cemno","Duindaer","Duirro","Eilianther","Gaer","Galadher","Gollor","Gulduron","Guldur","Guldurion","Hithaerben","Holiilo","Ingolmondur","Lar","Leucandil","Lanthir","Loeg","Lo","Lumorndaer","Morguldir","Morgulon","Naur","Neithaor","Nullion","Olchanar","Othanar","Olerydon","Ranchon","Rimdor","Rodor","Roher","Rhovanion","Rhovanion","Ruina","Russarocco","Sir","Sirdhemion","Tawaren","Tawarenion","Tawarher","Tordil","Uirchanar","Urendur","Urucher","Yr"]; var elfFemNameGenerator = capFirst(elfFemName1[getRandomInt(0, elfFemName1.length + 2)]) + " " + capFirst(elfLastName2[getRandomInt(0,elfLastName2.length +2)]); return elfFemNameGenerator; } //i want this to get the result's from "generateName" and it should be a global value so i can use it in the next function var names = generateName(); // this should print the name at least ten times but no function namePrinter(){ var text = document.getElementById("textArea"); for (var i = 0; i < 10; i++) { text[i].innerHTML(`${names}`) } return namePrinter; }
innerHTML is not a function, it's a property. So, in the loop use text.innerHTML += name However, if it's a <textarea> element, then you need to use value property instead: //this run the funtion that prints the names document.getElementById("elvenFemButton").onclick = namePrinter; document.getElementById("elvenFemButton2").onclick = namePrinter2; //cutting characters function function capFirst(string){ return string.charAt(10).toUpperCase() + string.slice(1); } //Randomizer function getRandomInt (min,max){ return Math.floor(Math.random() * (max-min)) + min; } //this function generates names using both "elfFemName" and "elfLastName" and the functions from above function generateName(){ var elfFemName1 = ["Adaia","Alisaie","Allisara","Alengwan","Alglaranna","Alachia","Alysia","Amberle","Anethra","Anwen","Apolline","Arathel","Ariane","Arianni","Ariel","Arwen","Ashalle","Ashniel","Atara","Ayara","Brelyna","Briala","Celebrían","Clothild","Cullich","Cylia","Dalish","Dirael","Eldyra","Elanor","Elenwen","Elezen","Ellia","Elynea","Éowyn","Failla","Faralda","Fleur","Freyalise","Galadriel","Gheyna","Jenassa","Katriel","Kira","Laina","Laniatte","Lauriel","Liallan","Liriel","Liselle","Loriel","Lorian","Lúthien","Máire","Mayael","Merril","Miara","Mihris","Minaeve","Nadja","Niranye","Nirya","Raewyn","Selveni","Sera","Shaera","Siofra","Taarie","Tauriel","Valora","Valya","Vanadis","Vanora","Velanna","Ylthin","Ysayle","Yvraine","Zelda"]; var elfLastName2 = ["Aearonian"," Agaraen","Agarher","Agarvran","Aire","Airendil","Amamion","Amdirthor","Amathal","Amather","Amathuilos","Amatheldir ","Amlugol","Aessereg","Aupwe","Calear","Caranagar","Cemno","Duindaer","Duirro","Eilianther","Gaer","Galadher","Gollor","Gulduron","Guldur","Guldurion","Hithaerben","Holiilo","Ingolmondur","Lar","Leucandil","Lanthir","Loeg","Lo","Lumorndaer","Morguldir","Morgulon","Naur","Neithaor","Nullion","Olchanar","Othanar","Olerydon","Ranchon","Rimdor","Rodor","Roher","Rhovanion","Rhovanion","Ruina","Russarocco","Sir","Sirdhemion","Tawaren","Tawarenion","Tawarher","Tordil","Uirchanar","Urendur","Urucher","Yr"]; var elfFemNameGenerator = capFirst(elfFemName1[getRandomInt(0, elfFemName1.length)]) + " " + capFirst(elfLastName2[getRandomInt(0,elfLastName2.length)]); return elfFemNameGenerator; } //i want this to get the result's from "generateName" and it should be a global value so i can use it in the next function var names = generateName(); var names2 = []; // this should print the name at least ten times but no function namePrinter(){ var text = document.getElementById("textArea"); text.value = ""; //clear previous result for (var i = 0; i < 10; i++) { text.value += names; } } function namePrinter2(){ var text = document.getElementById("textArea"); names2.length = 0; //clear array for (var i = 0; i < 10; i++) { names2[names2.length] = generateName(); } text.value = names2; } <textarea id="textArea"></textarea> <button id="elvenFemButton">generate names</button> <button id="elvenFemButton2">generate different names</button> This however as you can see will print the same name 10 times, if you need generate 10 names and store them globally, than you'll need save them in the array instead. P.S. Unrelated, but elfLastName2[getRandomInt(0,elfLastName2.length +2)] is wrong, you can't get value from an index that is larger than length of the array (aka +2 is wrong)
Javascript card game: once card is used, never use card again?
I am creating a card game using Javascript. I got this far with the code and everything works perfectly, but I am having trouble figuring out a way to make sure that once a card is selected it is never picked again. Preview: https://natialollie.github.io/javascript-card-game/ // function 2: generate and show random card function generateNumber() { // combine all card arrays let allCards = cardArray.concat(acesArray).concat(jackArray).concat(kingArray).concat(queenArray); // select a random letter within the array let cardLetter = allCards[Math.floor(Math.random() * allCards.length)]; // generate a random number between 2 and 10 let randomNumber = Math.floor(Math.random() * 9) + 2; // if generic card is choosen, concatenate letter with random number if ((cardArray).indexOf(cardLetter) !==-1) { var genericCard = randomNumber + cardLetter; var cardToShow = "PNG/" + genericCard + ".png" } // OR if special card is choosen, leave as is else { var specialCard = cardLetter; cardToShow = "PNG/" + specialCard + ".png" } console.log('The card slot with id: ' + "'" + selectedSlot + "'" + ' was selected! The new card file path to show is: ' + cardToShow); // change the current file path of the card, to the newly generated one let changeImgSrc = document.getElementById(selectedSlot) changeImgSrc.src = cardToShow; // remove file path from cardToShow and store the result let pathRemoved = cardToShow.replace("PNG/", '').replace(".png", ''); // take the result and append to array, each time a card is shown usedCard.push(pathRemoved); console.log(usedCard); //for cards inside the usedCard array, when you run the function dont include this as a file path option }
How about this. Filter out all the cards who are found in the usedCards array. let allCards = cardArray.concat(acesArray).concat(jackArray).concat(kingArray).concat(queenArray); allCards = allCards.filter(card => usedCards.indexOf(card) === -1) Alternatively you could keep track of the remaining cards (instead of the used cards) and remove from that list when you use a card.
One method is to use a fixed number table — your cards need to be mapped to an array and removed when picked. Here's a working example I built for a "use-all-numbers" random number generator: function rand(min, max) { return Math.floor(Math.random() * (max - min) + min); } var array = [], output = document.getElementById("output"); function generatelist() { for (i = 0; i < 10; i++) { array.push(i + 1); } output.innerHTML += "<br>List is: " + array; } generatelist(); function selectnumber() { x = rand(0, array.length); output.innerHTML += "<br>Number is: " + array[x]; array.splice(x, 1); output.innerHTML += "<br>List is: " + array; if (array.length == 0) { output.innerHTML += "<br>There are no more numbers! Regenerating list."; generatelist(); } } <button onclick="selectnumber()">Select a number from list</button> <div id="output"></div>
From Decimal to Binary system
I want to make an easy website because I want to learn javascript. The website will have just one (number) input named "number". After clicking on submit button the website will convert the number from decimal to binary system and show the answer. This is the javascript part that should convert the number and show the answer in a div with ID = result: var selectedNumber = document.getElementByName("number").value; var k = []; var a = 0; var b = 1; while (selectedNumber > 1){ if(selectedNumber%2 < 1){ k=k.append(a); selectedNumber = Math.floor(selectedNumber/2); } else{ k=k.append(b); selectedNumber = Math.floor(selectedNumber/2); } } k=k.append(b); for i in reversed(k){ document.getElementById("result").innerHETML = i; } Unfortunately, I don't have much experience using javascript and this code doesn't work. I've made a similar program in python and based this code on that in python.
Here's the corrected code: Tip - Whenever you have to glue two numbers to form a string make sure to do 1 + "" +2 var selectedNumber = 105;//document.getElementByName("number").value; var k = []; var a = 0; var b = 1; var output = ''; while (selectedNumber > 1){ if(selectedNumber%2 < 1){ k=k+""+a; selectedNumber = Math.floor(selectedNumber/2); } else{ k=k+""+b; selectedNumber = Math.floor(selectedNumber/2); } } k=k+""+b; console.log(k); //document.getElementByName("number").value = k;
Simplest way is to use toString(2) method. let a =7 console.log(a.toString(2)) I have made some minor changes to your code. removed redundant lines. i am appending values to a front of string instead of an array ( which you later reverse and join). function handle(){ let selectedNumber = document.getElementById("number").value; let k = '',a = 0, b = 1; while (selectedNumber > 1){ if(selectedNumber%2 < 1){ k= a+k } else{ k=b+k } selectedNumber = Math.floor(selectedNumber/2); } k=b+k; document.getElementById("result").innerHTML = k; } #result{ color: green; font-size:25px; } <input id='number' placeholder='enter value'></input> <button onClick=handle()>Convert to binary</button> <div id='result'></div>
It's a whole lot simpler than that. The .toString() method takes an optional argument that can be used to convert a number to a different numerical base system, like its binary, octal or hex values. Prepending the input's value with +, forces the input's value to become a number. document.querySelector("button").addEventListener("click", function(){ let number = +document.querySelector("input").value; // Convert input into a string console.clear(); console.log("The decimal: " + number + " converted to a binary is: " + number.toString(2)); console.log("The decimal: " + number + " converted to an octal is: " + number.toString(8)); console.log("The decimal: " + number + " converted to a hex is: " + number.toString(16)); }); <input><button>Convert!</button>
For this goal, actually you can forget all your code and simple use Number.prototype.toString(). It takes an optional argument of the base you want to use for convert the number to string. Example: const convert = () => { let number = document.getElementById("iNumber").value; binNumber = Number.parseInt(number, 10).toString(2); document.getElementById("dRes").innerHTML = binNumber; }; <input id="iNumber" type="number"> <button id="btnToBinary" onclick="convert()"> Convert To Binary </button> <div id="dRes"></div>
Adding splitted values in loops
I suggest u look at this picture, and then u look at the code I have written: function addNumbers() { var splitted = document.getElementById("listInput").value.split(" "); for(i = 0; i <= splitted.length; i+=1) { document.getElementById("resultNumberTotal").value = splitted[i]; } } I am taking the value from the box which says "Enter list of numbers and/or words" and I am splitting it. I split it so I have all the numbers like this "1 2 3" and so I can add them. I use the for loop for that. The for loop goes through every number and then it adds it. But when I press the button, it shows me undefined. Why am I getting undefined?
function addNumbers() { var splitted = document.getElementById("listInput").value.split(" "); //make sure that the values are in a number format document.getElementById("resultNumberTotal").value = splitted.reduce(function(a, b) {return Number(a) + Number(b);}, 0) } for the best practice make sure that allow number only for the input fields :) good luck
You need to somehow add the numbers up, either using the += operator, or by using something like .reduce() as I have done below. function addNumbers() { var val = document.getElementById("listInput").value; document.getElementById("resultNumberTotal").value = val.split(" ").reduce(function(runningTotal, currentArrayElement) { // make sure the value they typed is a number // if not, fail gracefully and simply ignore it if (!isNaN(Number(currentArrayElement))) { // if it is a number, add it to the running total runningTotal+= Number(currentArrayElement); } return runningTotal; // return the running total }, 0); // start with 0 as the initial value for runningTotal } <input type="text" id="listInput" placeholder="insert values here..." style="width: 300px;" /> <button onclick="addNumbers()">Add Numbers</button> <br/> <br/> <hr/> Number Total: <input id="resultNumberTotal"/>
You are getting undefined, because you are displaying the value of the last element of the array and not doing the Sum as you mentioned in the question. Following code always overrides the value of resultNumberTotal by the value of splitted[i]. Since, your for loop iterates for i <= splitted.length it reaches the index which doesn't exist in the array, when you get a property which doesn't exist on an object, you get undefined for(i = 0; i < splitted.length; i+=1) { document.getElementById("resultNumberTotal").value = splitted[i]; } So, for doing the sum, you need to make the code like function addNumbers() { var splitted = document.getElementById("listInput").value.split(" "); var total = 0; for(i = 0; i < splitted.length; i++) { var numberValue = +splitted[i]; if(!isNaN(numberValue)){ total = total + numberValue ; } } document.getElementById("resultNumberTotal").value = total; }
Javascript convert array of numbers with duplicates into unique sets of numbers
I have a javascript sorting algorithm problem which I am struggling to solve efficiently . I have an array of numbers which I am calling cards e.g. [1,2,3,4,5,6,7,8,9,10] Each day I have 6 teaching sets. In each set I want to display a maximum of 5 RANDOM & UNIQUE cards. Each card must be displayed exactly 3 times a day. What I have done so far is to create 6 empty arrays (sets). I then iterate through my cards 3 times each attempting to add them to a random set if the card does not already exist in that array. Sometimes it works, but most of the time I get a problem where I have only one array with space left and that array already contains the card. my code: Assume in my code that numberOfSetsPerCard = 3 & totalSets = 6. The only library available is JQuery. shuffleIntoSets : function(cards, numberOfSetsPerCard, totalSets) { var sets = []; // initialize the sets as empty arrays for (i = 0; i < totalSets; i++) { sets[i] = []; } $.each(cards, function(index, card) { for(x=0;x<numberOfSetsPerCard;) { // attempt to place the card in a set which doesnt already contain the card setNo = Math.floor((Math.random() * totalSets)); console.log("setNo: " + setNo); if(jQuery.inArray(card,sets[setNo]) == -1 && sets[setNo].length<5) { console.log(setNo + "does not contain: " + card); sets[setNo].push(card); console.log("Added the card, set now looks like :" + sets[setNo]); x++; } } }); return sets; },
This is my solution to your problem, it is a bit long, but i think it a bit long, but it definitely creates randomness in the teach sets, and satisfy the conditions you have stated codepen link: http://codepen.io/anon/pen/yyoaZy html/include jquery: <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> js: //----------------------------------------------- //For this question on StackOverflow: //http://stackoverflow.com/questions/28192127/javascript-convert-array-of-numbers-with-duplicates-into-unique-sets-of-numbers //----------------------------------------------- var cards = [1,2,3,4,5,6,7,8,9,10]; var numOfTeachingSets = 6; var numOfUniqueCardsPerTeachingSet = 5; var numOfCardRepetitionPerDay = 3; var shuffleCards = function(cards, numOfTeachingSets, numOfUniqueCardsPerTeachingSet, numOfRepetitionPerCard){ if(cards.length*numOfRepetitionPerCard != numOfTeachingSets*numOfUniqueCardsPerTeachingSet){ alert("invalid param"); return null; } //since each card is required to repeat numOfRepetitionPerCard times //the available choices should be numOfRepetitionPerCard times of the original deck of cards var availableCardChoices = cards.concat([]); for (var i=0;i<numOfRepetitionPerCard-1;i++){ availableCardChoices = availableCardChoices.concat(cards); } //Record down items from [availableCardChoices] has been picked var choosenList = []; //Put 6 sets of unique cards into the result var result = []; for (var i=0;i<numOfTeachingSets;i++){ result.push( pickOutUniqueNumberSet(availableCardChoices,numOfUniqueCardsPerTeachingSet, choosenList) ); } //return the result - an array of [numOfTeachingSets] arrays return result; } //----------------------------------------------------------- // Function: // picks [cardsPerSet] number of unique item out of [availableChoices] // each time an item is picked, this item is removed from [availableChoices] // // Important note: The number of card repetition is not really meaningful // because if each round of picking produces unique sets, // then the number of card repetition condition will be // automatically satisfied. //----------------------------------------------------------- var pickOutUniqueNumberSet = function(availableChoices, cardsPerSet, disabledChoices){ if (cardsPerSet==0 || availableChoices.length==0){ return null; } var choosenSet = []; var maxAttempts = 10000; //these 2 counter are used to prevent infinite looping var attempts = 0; for(var i=0;i<cardsPerSet;i++){ //items are choosen from [availableChoices] by their array index. var randomIndex = Math.floor((Math.random() * availableChoices.length)); //repeatedly grab a random index from availableChoices till a unique one is selected //unique item is an item that is not repeated in choosenSet, and its index is not in disabledChoices while( (InArray(choosenSet, availableChoices[randomIndex]) || InArray(disabledChoices, randomIndex)) && attempts<maxAttempts){ randomIndex = Math.floor((Math.random() * availableChoices.length)); attempts++; } //Add this item to the chooseSet choosenSet.push(availableChoices[randomIndex]); //Add this item's index to disabledChoices disabledChoices.push(randomIndex); } return choosenSet; } var InArray = function(array, itemToFind){ for(var i=0;i<array.length; i++){ if(array[i]==itemToFind){ return true; } } return false; } //---------- Test -------- var teachingSets = shuffleCards(cards, numOfTeachingSets, numOfUniqueCardsPerTeachingSet, numOfCardRepetitionPerDay); for(var i=0;i<teachingSets.length; i++){ document.write(teachingSets[i] + "<br>"); }