JavaScript function won't run twice with different inputs - javascript

I'm trying to make this function run twice with two different inputs, but it only runs once.
the code:
const data1dolphins = 44 + 23 + 71;
const data1Koalas = 65 + 54 + 49;
const data2dolphins = 85 + 54 + 41;
const data2Koalas = 23 + 34 + 27;
function calcAverage(data, dataValue) {
const scoreAverage = data * dataValue
return scoreAverage;
}
const data1DolphinsAverage = calcAverage(data1dolphins, 3)
const data1KoalasAverage = calcAverage(data1Koalas, 3)
const data2DolphinsAverage = calcAverage(data2dolphins, 3)
const data2KoalasAverage = calcAverage(data2Koalas, 3)
function checkWinner(avgTeamOne, avgTeamTwo) {
if (avgTeamOne >= (avgTeamTwo * 2)) {
console.log(`team one won with average score of : ${avgTeamOne}, while team two lost with average score of : ${avgTeamTwo}`)
} else if (avgTeamTwo >= (avgTeamOne * 2)) {
console.log(`team two won with average score of : ${avgTeamTwo}, while team one lost with average score of : ${avgTeamOne}`)
}
// console.log('testing round')
}
console.log('before')
checkWinner(data1DolphinsAverage, data1KoalasAverage)
console.log('middle')
checkWinner(data2DolphinsAverage, data2KoalasAverage)
console.log('after')
the output:
before
team one won with average score of : 540, while team two lost with average score of : 252
middle
after

Have you tried an else statement?
function checkWinner (avgTeamOne,avgTeamTwo){
if(avgTeamOne >= (avgTeamTwo*2)) {
console.log(`team one won with average score of : ${avgTeamOne}, while team two lost with average score of : ${avgTeamTwo}`);
} else if (avgTeamTwo >= (avgTeamOne*2)){
console.log(`team two won with average score of : ${avgTeamTwo}, while team one lost with average score of : ${avgTeamOne}`);
} else { <<
console.log("neither of these things happened."); <<
} <<
}
I find it a bit hard to see your purpose, as you didn't provide values for data1dolphins, data1Koalas, data2dolphins, or data2Koalas, but I'm guessing that this is the fix that you need.

the function ran fine after adding an else statment:
const data1dolphins = 44+23+71;
const data1Koalas = 65+54+49;
const data2dolphins = 85+54+41;
const data2Koalas = 23+34+27;
function calcAverage (data,dataValue){
const scoreAverage = data * dataValue
return scoreAverage;
}
const data1DolphinsAverage = calcAverage(data1dolphins,3)
const data1KoalasAverage = calcAverage(data1Koalas,3)
const data2DolphinsAverage = calcAverage(data2dolphins,3)
const data2KoalasAverage = calcAverage(data2Koalas,3)
function checkWinner (avgTeamOne,avgTeamTwo){
if(avgTeamOne >= (2*avgTeamTwo)) {
console.log(`team one won with average score of : ${avgTeamOne}, while team two lost with average score of : ${avgTeamTwo}`)
} else if (avgTeamTwo >= (2*avgTeamOne)){
console.log(`team two won with average score of : ${avgTeamTwo}, while team one lost with average score of : ${avgTeamOne}`)
}else {
console.log('none of the above')
}
}
console.log('before')
checkWinner(data1DolphinsAverage, data1KoalasAverage)
console.log('middle')
checkWinner(data2DolphinsAverage, data2KoalasAverage)
console.log('after')

Related

Waterpay calculator else if statements

I've been going over this question now for a couple of days and I'm still no closer to getting it right or understanding as to how to get it to run properly.
This is the current code I have:
let waterPay = prompt("Please enter the amount of water you use to get a price you need to pay, thank you!");
if (waterPay < 6000) {
console.log("The number is below 6000");
console.log (waterPay / 1000); //The outcome of this must be saved as a different let
console.log (waterPay * 15.73);// outcome of the above times by this amount
}
else if (waterPay > 6000 && waterPay <= 10500) {
console.log("The number is between 6000 and 10500");
}
else if (waterPay > 10500 && waterPay <= 35000) {
console.log("The number is between 10500 and 35000");
}
else if (waterPay > 35000) {
console.log("The number is above 35000");
}
What my code needs to do is take an input from the user stating how many litres of water they use, you can see in the code that depending on the amount of litres they use it should print out how much they owe.
The table above states that the first 6 000 litres will cost R15.73 per kilolitre.
Next, water consumption above 6 000 litres but below 10 500 litres will be
charged at R22.38 per kilolitre. Therefore, a household that has used 8000
litres will pay R139.14 (15.73 x 6 + 22.38 x 2). The table carries on in this
manner.
Im battling to figure out how I should go about working this out. Any help would be appreciated.
The data structure needed is something that pairs rates with usage thresholds. The last threshold is effectively infinite, to catch any usage above the highest. The logic is to find() the right rate object and multiply that rate tier's rate by the usage.
let rateData = [{
upTo: 6000,
rate: 15.73
},
{
upTo: 10500,
rate: 22.38
},
{
upTo: 35000,
rate: 34.0. // made this one up, not in the OP
},
{
upTo: Number.MAX_SAFE_INTEGER,
rate: 50.0. // made this one up, not in the OP
}
];
function rateDatumForUsage(usage) {
return rateData.find(r => usage <= r.upTo);
}
function costForUsage(usage) {
const rateDatum = rateDatumForUsage(usage);
return usage * rateDatum.rate;
}
console.log(`The cost of using 5000 units is (15.73*5000) ${costForUsage(5000)}`)
console.log(`The cost of using 10000 units is (22.38*10000) ${costForUsage(10000)}`)
console.log(`The cost of using 100000 units is (50*100000) ${costForUsage(100000)}`)
Total cost should be calculated by steps.
This means that, for example, if the first 10 liters cost USD 2, the following 10 liters (from 10 to 20) cost USD 1 and from 20 cost will be USD 0.5, then the total cost for 30 liters will be: 10*2 + 10*1 + 10*0.5 = 35.
This can only be achieved generically by looping. Here is the code:
const steps = [
6000,
10500,
35000
];
const rates = [
10,
20,
30
];
function calculate(used) {
let output = 0;
for (let i = 0; i < steps.length; i++) {
if (used >= steps[i]) {
output += steps[i] * rates[i];
} else {
output += (used - (steps[i - 1] || 0)) * rates[i];
break;
}
}
return output;
}
console.log(calculate(3000));
console.log(calculate(6000));
console.log(calculate(9000));
console.log(calculate(50000));

How to fix infinite while loop and create functions

I am trying to make a paycheck program, that utilizes functions and while loops.
In this program, I have to create two functions, one for validating the pay rate and hours, and then one for the calculations.
In addition, I have to have the first function pass the hours and pay rate to the calculation function, and then pass it back to the first function. When I try to run the program with the first function, it seems that if I enter a pay amount under 7.25, it enters an infinite loop.
Here is the code
<script>
function payValidate(x)
{
if(isNaN(payRate) || payRate < 7.25 || payRate > 20)
{
return false;
}
else
{
return true;
}
}
function hoursValidate(x)
{
if(isNaN(hours) || hours < 1 || hours > 60)
{
return false;
}
else
{
return true;
}
}
var grossPay;
var withHolding;
var netPay;
var message;
var payRate = parseInt(prompt("Enter pay rate"));
var payRateOK = payValidate(payRate);
while(!payRateOK)
{
payRate = parseInt(prompt("Invalid pay rate. Enter pay rate again"));
payRateOk = payValidate(payRate);
}
var hours = parseFloat(prompt("Enter hours worked"));
var hoursOK = hoursValidate(hours);
while(!hoursOK)
{
hours = parseFloat(prompt("Invalid hours. Enter hours again"));
hoursOK = hoursValidate(hours);
}
grossPay = payRate * hours;
if(grossPay <= 300)
{
withHolding = grossPay * 0.10;
}
else
{
withHolding = grossPay * 0.12;
}
netPay = grossPay - withHolding;
var message = "Pay Rate: $" + payRate.toFixed(2) +
"\nHours Worked: " + hours +
"\nGross Pay $" + grossPay.toFixed(2) +
"\nWithholding $" + withHolding.toFixed(2) +
"\nNet Pay $" + netPay.toFixed(2);
alert(message);
</script>
You're creating a new variable payRateOk (notice the lower case k) instead of writing to payRateOK, the variable you check in the while loop. So payRateOK will never change, and the loop will execute infinitely.
var payRateOK = payValidate(payRate); // In here you have used "payRateOK"
while(!payRateOK)
{
payRate = parseInt(prompt("Invalid pay rate. Enter pay rate again"));
payRateOk = payValidate(payRate); // In here you have used "payRateok"
}
payRateOK != payRateOk there for you have to use same name for that
other thing is payRate is a float variable. you should use var payRate = parseFloat instead of var payRate = parseInt.
you have used hours as int type there for var hours = parseFloat should be var hours = parseInt

Divide / Hand out random amount

Lets say I have 8 people and 5000 apples.
I want to hand out all the apples to all 8 people so i have no apples left.But everyone should get a different amount
What would be the best way to give them all out?
I started of with this:
let people = 8
let apples = 5000
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
while (people--) {
// last person get the rest
let x = people ? getRandomInt(0, apples) : apples
// subtract how many apples i got left
apples -= x
console.log(`Giving person ${people + 1} ${x} apples (got ${apples} left)`)
}
But the thing I don't like about this is that the last person get very few apples (sometimes less then 5 apples) and the first person gets way more then the others
If you need random yet 'balanced' results each time, you need to prioritize either balance - or randomness. Here's one possible solution following your 'widestGap' requirement:
function randomDeltas(length, widestGap, remToGet) {
// widestGap >= length * 2 - 1
let deltas = [];
let sum = 0;
let start = 0;
let origLength = length;
while (length--) {
start += 1 + Math.floor(Math.random() * widestGap);
deltas.push(start);
sum += start;
}
let rem = sum % origLength;
let correction = remToGet - rem;
if (correction !== 0) {
sum -= deltas[0];
deltas[0] += correction;
if (deltas[0] >= deltas[1]) {
deltas[0] -= origLength;
}
else if (deltas[0] < deltas[1] - widestGap) {
deltas[0] += origLength;
}
sum += deltas[0];
}
return {
deltas,
sum
};
}
function randomDistinctDistribute(apples, people) {
let rem = apples % people;
let { deltas, sum } = randomDeltas(people, people * 2 - 1, rem);
let div = (apples - sum) / people;
let distribution = [];
while (deltas.length) {
distribution.push(div + deltas.shift());
}
return distribution;
}
console.log(randomDistinctDistribute(5000, 8));
console.log(randomDistinctDistribute(2500, 6));
Here the idea is to randomize the deltas (to make sure that gap never becomes big), then apply those deltas to divisor.
Here's the original (deterministic) approach to get balanced distribution with distinct values:
function distinctDividents(apples, people) {
let distribution = [];
let div = Math.floor(apples / people);
let rem = apples % people;
if (people % 2) {
distribution.push(div);
people--;
}
let half = people / 2;
let i = 1;
while (i <= half) {
distribution.push(div - i);
distribution.unshift(div + i);
i++;
}
if (rem) {
distribution[0] += rem;
}
return distribution;
}
console.log(distinctDividents(5000, 8));
Think I figure it out. Was just a little tweeking.
let x = people ? getRandomInt(0, Math.floor(apples / people)) : apples
let people = 8
let apples = 5000
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
while (people--) {
// last person get the rest
let x = people ? getRandomInt(0, Math.floor(apples / people)) : apples
// subtract how many apples i got left
apples -= x
console.log(`Giving person ${people + 1} ${x} apples (got ${apples} left)`)
}
Still which nobody got less then 100 apples or more then 1000 but this will do. Otherwise it get just more complex. the next day i may only have 2500 apples and 6 people...

Shortest way to compare your score to three ranges in jQuery

I have the following code:
function display_message() {
var low = data.result[0].max; //returns 30
var medium = data.result[1].max; // returns 60
var high = data.result[2].max; // returns 100
// mypoints are 67 for example
if(mypoints > low) {
if(mypoints > medium) {
alert('You got a high score');
} else {
alert('You got a medium score');
}
} else {
alert('You got a low score');
}
}
This code works fine. I compare my average score to the standard low / medium / high score.
Low score: 0-30 points
Medium score: 31-60 points
High score: 61-100 points
My question though is how to make my code a bit prettier? I am not sure if the code is considered as clear and efficient.
Any opinions would be much appreciated, thank you
There is no need for the if else with low, just check from smallest to highest.
if (mypoints <= low) {
//low msg
} else if (mypoints <= medium) {
//medium msg
} else {
//high msg
}
or you can go the opposite direction and check for the highest first with greater than
You could use a condition without nested conditions.
if (mypoints > medium) {
alert('You got a high score');
} else if (mypoints > low) {
alert('You got a medium score');
} else {
alert('You got a low score');
}
Here, we iterate over the various values that make up the score range. The loop will iterate over each score range in turn, meaning you need to have the lowest score first and highest score last. We then save score name against myscore to be alerted out at a later point.
This approach allows for expandability - you can add as many score ranges in the middle without having to add any more if/else blocks.
let data = {result: [{max: 30}, {max: 60}, {max: 100}]},
mypoints = 67;
function display_message() {
let score_range = {
low: data.result[0].max, //returns 30
medium: data.result[1].max, // returns 60
high: data.result[2].max // returns 100
},
myscore = 'fail';
for (var score in score_range) {
if (score_range.hasOwnProperty(score)) {
if (mypoints > score_range[score]) {
myscore = score;
}
}
}
alert('You got a ' + myscore + ' score!');
}
display_message();
You could store the messages in an array, and find the correct index like so:
function display_message() {
var low = 30,
medium = 60,
rank;
mypoints = 67; // for example
rank = ['low', 'medium', 'high'][+(mypoints > low) + +(mypoints > medium)];
console.log('You got a ' + rank + ' score');
}
display_message();
The magic is in the unary plus operator which converts booleans returned by comparisons to 0 or 1 accordingly. It's also easy to include more rankings if needed.
mypoints < low ? alert("you get low score") : (mypoints < medium ? alert("you get medium score") : alert("you get high score"))
You can use the switch statement
function display_message() {
var low = data.result[0].max; //returns 30
var medium = data.result[1].max; // returns 60
var high = data.result[2].max; // returns 100
switch (true) {
case mypoints > medium:
alert('You got a high score');
break;
case mypoints > low:
alert('You got a medium score');
break;
default:
alert('You got a low score');
}
}
You can create a function which takes the score and an array as an argument with the different levels and their names {"score": 30, "text": "You got a low score"} and then just loop that and output what is closest to what you sent in and return the matching text.
Example:
var myScore = 50,
scoreIntervals = [{
"score": 30,
"text": "Low score"
},{
"score": 60,
"text": "Average score"
},{
"score": 100,
"text": "High score"
}];
function evaluateScore(score, scoreIntervals) {
var output = scoreIntervals[scoreIntervals.length - 1].text;
$.each(scoreIntervals, function(key, val) {
if(score <= val.score) {
output = val.text;
return false;
}
});
return output;
}
console.log(evaluateScore(myScore, scoreIntervals));

JS game Crowns and Anchors: error in outcome

I'm having trouble understanding the outcome of a game I have developed with the help of the book 'Learning JavaScript' by Ethan Brown.
Here is the code:
//helper functions for randomizing
function rand(x,y){
return x + Math.floor((y-x+1)*Math.random());
}
function getFace(){ return ['crown','heart','spade','club','diamond','anchor'][rand(0,5)]; }
//the game
function crownsAndAnchors(){
console.log('Let\'s play Crowns and Anchors!');
let rounds = 0;
let funds = 50;
while( funds > 1 && funds < 100 ){
rounds ++;
console.log(`Round: ${rounds}`);
let totalBet = 7;
let bets = { crown: 0, heart: 0, spade:0, club:0, diamond:0, anchor:0 };
if (totalBet == 7){
totalBet = funds;
console.log('You pulled out 7p, your lucky number! Bet all on heart');
bets.heart = totalBet;
}else{
//distribute totalBet randomly
}
funds = funds - totalBet;
console.log('\tBets: ' + Object.keys(bets).map(face => `${face} ${bets[face]}p`).join(' || ') + ` (total: ${totalBet} pence)`);
const hand = [];
// roll the dice
console.log("_______________rolling the dice ____________")
for (let i = 0; i < 3; i++) {
hand.push(getFace());
}
console.log(`\tHand: ${hand.join(', ')}`);
//check for winnings
let wins = 0;
for (let i = 0; i < hand.length; i++) {
let face = hand[i];
if (bets[face] > 0) wins = wins + bets[face];
}
funds = funds + wins;
console.log(`\tWinnings: ${wins}`);
}
console.log(`\nEnding Funds: ${funds}`);
}
crownsAndAnchors();
I have hard-coded variable totalBet to be 7 to easily monitor final outcome. For example, if two out of three die outcomes are heart than the Ending Funds should be 150, correct?
However, when I run the code (Node v7.6.0) this is what I am returned:
Let's play Crowns and Anchors!
Round: 1
You pulled out 7p, your lucky number! Bet all on heart
Bets: crown: 0p || heart: 50p || spade: 0p || club: 0p || diamond: 0p || anchor: 0p (total: 50 pence)
_______________rolling the dice ____________
Hand: heart, heart, club
Winnings: 100
Ending funds: 100
I know I'm somehow updating funds incorrectly I just cannot figure out why.
Thank you so much in advance!!!
The line
funds = funds - totalBet;
is setting funds to 0, then later you get two wins of 50 added to it to give you 100.
If you eliminate that line where funds = funds - totalBet, then you get the 150 you are expecting.
Or move that line to after the dice roll and only execute it if you did not win anything.

Categories

Resources