I need to create a program that asks the user for a value to store in an array and continues to keep asking for values to add till they have no more numbers they want to enter into the array. Afterwards I must output the array containing no zeros (Which they're allowed to enter zeros so I have to filter them out from the output) and return the sum of the array. My current issue with my program is that arr.push(x) is currently trying to push an undefined value in the function arrin. I feel as if there's a much better way of going about this than I'm currently trying so I'm all ears for improvement.
var x = parseInt(prompt("Enter a number, to exit enter NaN", "0"), 10);
var y = arrin(x);
var arr = [];
var s;
function arrin(x) {
if(x != NaN){
arr.push(x)
x = parseInt(prompt("Enter a number, to exit enter NaN", "0"), 10);
y = arrin(x);
}else{
document.write("<p>"+arr.toString()+"</p>");
s = sum(arr);
doucment.write("<p> The sum of all elements in the array is "+s+"</p>");
}
}
x != NaN will not work.
!isNaN(x) will check if the var is a number.
x != "NaN" will check if the text is literally "NaN"
either of the last two will work.
var arr = [];
var y = arrin(0);
var s;
function arrin(x) {
if (!isNaN(x)) {
if (x != 0) arr.push(x)
x = parseInt(prompt("Enter a number, to exit enter NaN", "0"), 10);
y = arrin(x);
} else {
document.write("<p>" + arr.toString() + "</p>");
s = sum();
document.write("<p> The sum of all elements in the array is " + s + "</p>");
}
}
function sum() {
var t = 0;
for (var i = arr.length; i--;) t += parseInt(arr[i]);
return t;
}
Related
So in finance, sometimes finding the average of a salary does not make sense. For example, if someone really wealthy and someone in need had their salaries compared, that would be a really uneven average. Therefore, a median makes more sense to see what is in between. I want to try and recreate this but would like to know what you guys believe are the first steps.
var input = [];
var output = 0;
var t1 = 0;
var t2 = 0;
//variables setting start
function reset(){
input = [];
output = 0;
t1 = 0;
t2 = 0;
}
//variables setting end
//caller functions start
function start(){
reset();
t1 = prompt("how many inputs do you want");//asking for how many inputs are wanted
do{// repeat until loop
t2 = 0;
t2 = prompt("Enter values for the array");//this is how the inputs are entered
input.push(t2);
}while(input.length < t1);//waiting for condition to be met
t1 = 0;
input.sort(sortNumber);
checking();
if(t1 == 0){
logic();
}
}
//caller functions end
//logic for sorting the numbers start
function sortNumber(a, b) {
return a - b;
}
//logic for sorting the numbers end
// logic for finding the median start
function logic(){
var i = 0;
t1 = 0;
t2 = 0;
if(input.length % 2 == 0){
t1 = input.length / 2;
i = t1;
t1 = t1 - 1;
t2 = input[i] + input[t1];
output = t2 / 2;
console.log(output);
}else{
t1 = input.length / 2;
t1 = t1 - 0.5;
output = input[t1];
console.log(output);
}
}
//logic for finding the median end
// logic for checking the input end
function checking(){
i = 0;
do{
if(input[i] > 0){
if(input[i] / 1 == input[i]){
i = i + 1;
}else{
console.log("you have something other then a positive integer");
i = i + 1;
t1 = 1;
}
}else{
console.log("you have something other then a positive integer");
i = i + 1;
t1 = 1;
}
}while(i < input.length);
}
//logic for checking the input end
Here is what I tried to achieve in my code: 1 < len(data) ≤ 1000 all(0 ≤ x < 10 ** 6 for x in data)
For anyone who doesn't already know, JavaScript input/output is usually asynchronous, and listener functions can respond to clicks or other user actions in real time.
Here's a way to use them to handle calculating a median from user inputs (intentionally verbose for clarity):
/* Note: if you just want to see the math part, skip to the bottom */
// Defines globals
const
numbers = [],
inputElement = document.getElementById("input"),
outputParagraph = document.getElementById("outputParagraph"),
enterBtn = document.getElementById("enterBtn"),
calcBtn = document.getElementById("calcBtn");
// Adds Listeners
enterBtn.addEventListener("click", addToArray);
calcBtn.addEventListener("click", calculateAndDisplayMedian);
//
// Defines Listeners
//
function addToArray(){
// Gets the entered value (and ignores empty strings)
let value = inputElement.value;
if(!value.length){
return;
}
// Coverts the value to an integer (Note: This technique truncates decimals)
let num = parseInt(value);
// Complains if the value can't be converted to a positive integer
// (won't happen if the HTML Input Element is doing its job)
if(!num || num <= 0){
outputParagraph.innerHTML = "Please enter a positive integer";
}
// Adds the number to the array, and clears the input
else{
numbers.push(num);
inputElement.value = "";
outputParagraph.innerHTML = "";
}
// Puts the cursor back in the input
inputElement.focus();
}
function calculateAndDisplayMedian(){
// Automatically adds to the array any number still in the input field
addToArray();
// Declares local variables
let length = numbers.length;
let median;
// Makes sure there is at least one number before proceeding
if(length == 0){
return;
}
// Sorts the array
numbers.sort( (a, b) => a - b);
// If the the count of numbers is odd, the middle one is the median
if(length % 2 == 1){
let index = length / 2 - 0.5;
median = numbers[index];
}
// Otherwise, the average of the two middle numbers is the median
else{
let
index1 = length / 2 - 1,
index2 = length / 2,
num1 = numbers[index1],
num2 = numbers[index2];
median = (num1 + num2) / 2;
}
// Reports the result and empties the array
outputParagraph.innerHTML = "The median is " + median;
numbers.length = 0;
}
<!--
The 'input HTML Element can do some of our validation automatically
(as long as the environment where the script runs supports the attributes used)
-->
<input id="input" type="number" min="1" />
<button id="enterBtn">Enter</button>
<button id="calcBtn">Calculate Median</button>
<p id="outputParagraph"></p>
I've written a solution to take a list of integers entered through a form. It works. It gives you the sum of the two largest integers and posts it in the DOM.
However, it's not very efficient for large arrays of say 1 million integers.
How can I improve this solution to be more efficient.
App.js
// This function reverses the order of the array and places the biggest numbers first
function sortNumber(a, b) {
return b - a;
}
// this function is used to ensure the user didn't enter any letters
function getArray() {
var alphaExp = /^[a-zA-Z]+$/;
// This function takes the array, orders it, adds the sum of the two largest numbers and returns the value
function sumOf(x) {
// Sort the ary with the sortNumber function
array.sort(sortNumber);
// Then we add the two biggest numbers of the array and save it to the result variable.
var result = array[0] + array[1];
// Then we share the result with the user by updating the browser
var myHeading = document.querySelector('h2');
myHeading.textContent = "The sum of your two biggest numbers is: " + result;
// Like a good student, it's important to show your work
var showYourWork = document.querySelector('h3');
showYourWork.textContent = array[0] + " + " + array[1] + " = " + result;
}
// This grabs the value of the input
var arrayField = document.getElementById('arrayField').value;
if (arrayField.match(alphaExp)) {
// Fail if user enters letters
var raiseError = document.querySelector('h5');
raiseError.textContent = 'No not letters! We want numbers!!';
} else {
var array = JSON.parse("[" + arrayField + "]");
if (arrayField.length < 2) {
// If the user enters only 1 number, tell them to enter more!
var raiseError = document.querySelector('h5');
raiseError.textContent = 'Please enter atleast two numbers seperated by commas for us to add!'
} else {
// When the user enters a list of numbers, run the sumOf function.
sumOf(arrayField);
//Make the error go away
var raiseError = document.querySelector('h5');
raiseError.textContent = '';
}
}
};
// use an eventlistener for the event (This is where the magic happens)
var subButton = document.getElementById('subButton');
subButton.addEventListener('click', getArray, false);
You don't have to sort it, just search linearly for the two biggest ones:
EDIT: the code below should work now and is asymptotically faster than the OP's code. The OP does sorting first which can be done in O(n log n), assuming a random list. My code does a linear search through the list in O(cn) with c = 2 (the two loops are not necessary but simple). The solution for ceil(n log n) = 2n with n a positive integer is 14, that is for every list longer than 14 entries the code below is faster. E.g.: for one million entries the relation is 13,815,511 to 2,000,000, more than six times faster. You can do the same thing in a single loop which halves the runtime (theoretically, but it is also a tiny bit faster because of the better locality).
function maxtwo_wrong(a){
var b1 = -Infinity;
var b2 = -Infinity;
for (var i=0; i < a.length; i++) {
if (a[i] > b1) {
b1 = a[i];
}
}
for (var i=0; i < a.length; i++) {
if (a[i] > b2 && a[i] < b1) {
b2 = a[i];
}
}
return [b1,b2];
}
EDIT-2: The code above maxtwo_wrong seems not to fit the requirements, so I wrote another one maxtwo_rightand put it below. Please, OP, tell me which one fulfills your requirements such that I can delete the wrong one.
EDIT-3: made it simpler and correct.
function maxtwo_right(a){
var b1 = -Infinity;
var b2 = -Infinity;
for (var i=0; i < a.length; i++) {
// If the current entry is bigger than variable b1
// keep the old value in the variable b2 and set b1 to the
// value of the current entry
if (a[i] > b1) {
b2 = b1;
b1 = a[i];
}
// if the current entry equals b1 set the variable b2 to
// the value of the current entry
else if(a[i] === b1){
b2 = a[i];
}
}
// return the sum of the two variables as requested
return b1 + b2;
}
I finally found some time to sit down and work this one out.
I was looking at the problem all wrong.
Here is my new solution
// This function adds the sum of the two largest integers of an array and returns the value
function topTwoInt(theArray) {
var intArray = theArray;
var highestInt = -Infinity;
var secondHighestInt = -Infinity;
var answer = 0;
//Loop through the array
for (var i=0; i < intArray.length; i++) {
//grab the biggest int and assign it to the highestInt variable;
if (intArray[i] > highestInt) {
secondHighestInt = highestInt;
highestInt = intArray[i];
}
//If the next number is equal too highestInt or greater than secondHighestInt
//Make that number become the new secondHighestInt
else if(intArray[i] === highestInt || intArray[i] > secondHighestInt) {
secondHighestInt = intArray[i];
}
}
answer = highestInt + secondHighestInt;
return answer;
};
This solution is largely inspired by #deamentiaemundi
Thanks man.
I am creating a program which takes two variables as user prompts. The first one is a starting number, the next is a number to determine a range. The program then spits out how many steps it takes for the original number entered to reach zero using the collatz function and then displays this information to the screen. It should then increment the starting number by 1 and repeat the process until starting number reaches the second inputted number
Currently i only have this working for one number, which is the original starting number. I am unsure of how to code the collatz function to run through all the numbers between the start number (first input) and the range number(second input) my guess is i will need some sort of for loop and push an array of the values (steps it takes for number to reach 0) as its own array within another array (which holds all the steps for all the numbers the program ran through)
if anyone can help with this i'd really appreciate it, thanks
var numArray = [];
function getStartNum(){
startNum = parseInt(prompt('Please enter a starting number greater than 0.'));
if(!isPosNum(startNum)){
alert("error! That is an incorrect value. Please renter an appropriate positive value.");
getStartNum();
} else {
numArray.push(startNum);
getRangeNum();
}
}
function getRangeNum(){
rangeNum = parseInt(prompt('Please enter a range value greater than 0.'));
if(!isPosNum(rangeNum)){
alert("error! That is an incorrect value. Please renter an appropriate positive value.");
getRangeNum();
} else {
collatz();
}
}
function isPosNum( number ) {
if (isNaN( number )) {
return false;
} else if (number < 0) {
return false;
} else if (number == 0) {
return false;
} else {
return true;
}
}
function collatz() {
//sets x to always be the value of the last element in the array
x = numArray[numArray.length-1];
//Sets y to the remainder of x
y = x % 2;
//if the value of y of 0, then the number is even and these calculations will be performed
if (x == 1) {
console.log('X has reached a value of 1');
createBar();
} else if ( y == 0) {
console.log('Number is even.');
z = x/2;
console.log('Value of z is equal to ' + z);
numArray.push(z);
console.log(numArray);
collatz();
} else if ( y !== 0) {
//If y is not equal to 0 then it is odd, and these calculations will be performed
console.log('Number is odd.');
z = (3 * x) + 1;
console.log('Value of z is equal to ' + z);
numArray.push(z);
console.log(numArray);
collatz();
}
}
function maxValueIndex() {
}
function createBar() {
var steps = numArray.length-1;
console.log('Number of steps taken to get to 1 is: ' + steps);
var p = document.createElement("p");
document.body.appendChild(p);
var first = numArray[0];
var output = document.getElementsByTagName("p")[0];
output.innerHTML = 'Number of steps taken for ' + first + ' to reach 1 is: ' + steps;
var g = document.createElement("div");
g.id = "graph";
document.body.appendChild(g);
for ( var i=0, n=numArray.length-1; i < n; i++) {
var line = document.createElement("p");
line.className = "line";
line.innerHTML = "|";
document.body.appendChild(line);
}
}
getStartNum();
You only need to add a function that iterate between startNum and startNum+rangeNum. In this iteration you can restart numArray with each increment of startNum and call the collatz function to calculate all the steps.
You can see the modification of your code running on:
https://jsfiddle.net/kqcebswv/
I hope this helps you.
If you need to do this generating an array of arrays you can do this:
collatzArray = [];
for (var i = startNum; i <= startNum + rangeNum; i++) {
collatzArray.push([i]);
}
then you can access each numArray iterating the collatzArray:
for (var i = 0; i < collatzArray.length; i++) {
numArray = collatzArray[i];
collatz();
}
but I think this solution si more complex.
I'm writing a program in Javascript that separates even and odd numbers, puts them into an array, adds the sum of numbers, and finds the average.
I'm having an issue not allowing zeros not to count. Because its adding to the array, and when the user types in 6+6, sum is 12, average is calculating to 4 because of the extra 0 in the array.
Is there anyway to not allow the zeros to count? Here is what I have so far..
var evenarray = [];
var oddarray = [];
var avgEven = 0;
var avgOdd = 0;
var isValid;
function numberFunction(){
do
{
var numbers = prompt("Please enter numbers. Enter empty string to exit.");
if(numbers % 2 == 0)
{
evenarray.push(numbers);
var sumEven = 0;
for (var i=0; i < evenarray.length; i++)
{
sumEven = sumEven + Number(evenarray[i]);
}
var avgEven = sumEven/evenarray.length;
//alert("even");
}
if(numbers % 2 !== 0)
{
oddarray.push(numbers);
var sumOdd = 0;
for (var i=0; i < oddarray.length; i++)
{
sumOdd = sumOdd + Number(oddarray[i]);
}
var avgOdd = sumOdd/oddarray.length;
//alert("odd");
}
//if(isNaN(numbers)){
//alert("Only numeric data only");
//}
}
while(numbers !== "");
Just do nothing when the number is actually 0:
if (numbers == 0)
{
}
else if(numbers % 2 == 0)
{
evenarray.push(numbers);
var sumEven = 0;
for (var i=0; i < evenarray.length; i++)
{
sumEven = sumEven + Number(evenarray[i]);
}
var avgEven = sumEven/evenarray.length;
}
else // only odds remain
{
oddarray.push(numbers);
var sumOdd = 0;
for (var i=0; i < oddarray.length; i++)
{
sumOdd = sumOdd + Number(oddarray[i]);
}
var avgOdd = sumOdd/oddarray.length;
}
You can do :
if(numbers % 2 == 0 && numbers !=0) ...
if(numbers % 2 != 0 && numbers !=0) ...
so that you don't do anything when numbers == 0;
It's a little strange to call your variable numbers instead of number.
your function should be,
function numberFunction(){
do
{
var numbers = prompt("Please enter numbers. Enter empty string to exit.");
if(numbers !=0 && !isNaN(numbers))
(numbers %2 == 0)? (evenarray.push(parseInt(numbers))) : (oddarray.push(parseInt(numbers)));
}while(numbers !== "");
for(var i = 0; i < evenarray.length; i++)
sumEven += evenarray[i];
for(var i = 0; i < oddarray.length; i++)
sumOdd += oddarray[i];
avgEven = sumEven / evenarray.length;
avgOdd = sumOdd / oddarray.length;
document.getElementById("even").innerHTML = evenarray.toString();
document.getElementById("sumEvenTotal").innerHTML = sumEven.toString(); //displays sum of even numbers.
document.getElementById("averageOdd").innerHTML = avgOdd; //displays average of odd numbers.
document.getElementById("averageEven").innerHTML = avgEven; //diplays average of even numbers.
document.getElementById("odd").innerHTML = oddarray.toString(); //displays all odd numbers that were entered.
document.getElementById("sumOddTotal").innerHTML = sumOdd.toString();
}
As you already have other answers with solutions to your particular issue, I would suggest a different approach. Think of the data you're manipulating: an array. Try to solve the issue only with data, no user input, no DOM manipulation; just data. This helps to separate concerns, and make your code easier to understand.
Since we're working with arrays, we can make use of some of the built-in JavaScript methods that are present in modern browsers, such as filter and reduce. These methods are in a way, alternatives to for loops, with some pre-defined behavior, and a callback function.
Now, let's think of the steps involved in solving your problem.
Get numbers from the user. We can represent this data as an array, as you were already doing.
We want all odd numbers, their sum and average.
We want all even numbers, their sum and average.
We display the data to the user.
In this solution I'm assuming you already have an array with the data, and will be focusing on points 2 and 3. Remember, think of data, user interaction shouldn't be mixed with your data logic. Instead of asking the user for a number on each loop, you could ask the user for a list of numbers directly; you avoid multiple prompts this way, and it lets you separate data and interaction nicely. Ideally you'd validate all user input to match your requirements.
// Helpers to work with numbers
var odd = function(x) {
return x % 2 === 0;
};
var even = function(x) {
return x % 2 !== 0;
};
var add = function(x, y) {
return x + y;
};
function solve(ns) {
// Solve the problem
// with odd or even numbers
var result = function(fn) {
var xs = ns.filter(fn); // odd or even
var sum = xs.reduce(add);
return {
numbers: xs,
sum: sum,
average: sum / xs.length
};
};
// Return an object
// with odd and even results
return {
odd: result(odd),
even: result(even)
};
}
var numbers = [1,2,3,4]; // from user input
var result = solve(numbers);
console.log(result.odd);
//^ {numbers: [2,4], sum: 6, average: 3}
console.log(result.even);
//^ {numbers: [1,2], sum: 4, average: 2}
I have developed this code with help from you guys here on stackoverflow. I have added an extra part to it where it compares two numbers from two different arrays, in this case offhire1 and pro2.
The problem is in my code where I have:
(offhire1[i].value > pro2[i].value)
It only allows me to contine if the numbers match i.e 100=100. But what I'm after is identifing any numbers that are greater than the value only 120 > 100. I have tested if the values are being passed and they are.
What is my mistake here can anyone suss it out.
function validateoffhire(form) {
var num1 = document.getElementById('num1');
var test2Regex = /^[0-9 ]+(([\,\.\- ][a-zA-Z ])?[a-zA-Z]*)*$/;
var accumulator = 0;
var num2 = num1.value;
var i=0;
var offhire1 = [];
var pro2 =[];
for(var i = 0; i < num2; i++) {
offhire1[i] = document.getElementById('offhire1' + i);
pro2[i] = document.getElementById('pro2' + i);
var offhire2 = offhire1[i].value;
// var pro3 = pro2[i].value;
if(!offhire2.match(test2Regex)){
inlineMsg('offhire1' + i,'This needs to be an integer',10);
return false;
}
else if (offhire1[i].value > pro2[i].value) {
alert("You entered: " + pro2[i].value)
inlineMsg('offhire1' + i,'You have off hired to many items',10);
return false;
}
else{
accumulator += parseInt(offhire2);
}
}
if(accumulator <= 0){
inlineMsg('num1' ,'You have not off Hired any items',10);
return false;
}
return true;
}
I'm not quite sure I follow you. If the numbers are the same, the statement won't match.
One issue in your code is that you're comparing strings, not numbers. You may want to change it to:
(parseInt(offhire1[i].value) > parseInt(pro2[i].value))