Show the average of the 1-digit numbers entered - javascript

I have a problem with the following exercise:
Enter N number of numbers by prompt. Show the average of the 1-digit numbers entered. End the program with the word “exit"/"salir”.
I also have to do the average calculation with a function. Here's what I have:
let i;
var sum = 0;
var avg = 0;
var average = function(i) {
sum = sum + i;
avg = sum/(i+1);
}
do {
i = prompt("Ingrese un numero: ");
if ((i < 10) && (i > -10)) {
average(i);
}
} while (i !== "salir");
alert(`el promedio de los numeros de un solo digito es: ${avg}`);
I tried limiting the program by stating that the average function will only be executed for one digit numbers, but the problem is that this is giving me the total average of all the numbers entered not the average of only the 1 digit numbers.

You've succeeded in avoiding including multi-digit numbers from the sum and average. The problem isn't in that, it's here:
avg = sum/(i+1);
That's not how averages work. An average is the sum divided by how many values went into making that sum. (The number of numbers you added to sum.)
Keep track of how many numbers you added to sum, and use that count to calculate the average.
Side note: A couple of notes on the code, just for what they're worth:
Your code is currently relying on implicit conversion from string (what the user types in) to number (what you use with sum). Although it works in this example, I strongly recommend doing the conversion explicitly. My other answer here (also on SO) lists your various options for doing that.
You've used both let and var in your code. I suggest never using var, it has no place anymore in modern JavaScript. Use let if you need to let the variable's value change (as with sum), and const when you don't.
You're missing one ; (after the assignment statement assigning to average). (You can rely on Automatic Semicolon Insertion if you like [I don't recommend relying on it, but some others do], but whichever way you go, it's best to know the rules and then consistently do or don't include your ;.)
I suggest declaring your variables in the innermost scope you can declare them in. There's no reason for i to be global in your code, just make it local to the do-while loop body.
Obviously in a very simple exercise like this it's mostly fine, but I recommend not getting used to prompt and alert, they're relics from the 1990s and behave in very unusual (and sometimes problematic) ways compared to most functions in JavaScript.

var i;
var sum = 0;
var avg = 0;
var average = function(num) {
sum = sum + num;
i+=1
avg = sum/i;
}
var ans;
do {
ans = prompt("Ingrese un numero: ");
if ((ans < 10) && (ans > -10)) {
average(ans);
}
} while (ans !== "salir");
alert(`el promedio de los numeros de un solo digito es: ${avg}`);
Should remove this but will leave it here for any future visitors.

Related

Emojis to/from codepoints in Javascript

In a hybrid Android/Cordova game that I am creating I let users provide an identifier in the form of an Emoji + an alphanumeric - i.e. 0..9,A..Z,a..z - name. For example
🙋‍️Stackoverflow
Server-side the user identifiers are stored with the Emoji and Name parts separated with only the Name part requiried to be unique. From time-to-time the game displays a "league table" so the user can see how well they are performing compared to other players. For this purpose the server sends back a sequence of ten "high score" values consisting of Emoji, Name and Score.
This is then presented to the user in a table with three columns - one each for Emoji, Name and Score. And this is where I have hit a slight problem. Initially I had quite naively assumed that I could figure out the Emoji by simply looking at handle.codePointAt(0). When it dawned on me that an Emoji could in fact be a sequence of one or more 16 bit Unicode values I changed my code as follows
Part 1:Dissecting the user supplied "handle"
var i,username,
codepoints = [],
handle = "🙋‍️StackOverflow",
len = handle,length;
while ((i < len) && (255 < handle.codePointAt(i)))
{codepoints.push(handle.codePointAt(i));i += 2;}
username = handle.substring(codepoints.length + 1);
At this point I have the "disssected" handle with
codepoints =  [128587, 8205, 65039];
username = 'Stackoverflow;
A note of explanation for the i += 2 and the use of handle.length above. This article suggests that
handle.codePointAt(n) will return the code point for the full surrogate pair if you hit the leading surrogate. In my case since the Emoji has to be first character the leading surrogates for the sequence of 16 bit Unicodes for the emoji are at 0,2,4....
From the same article I learnt that String.length in Javascript will return the number of 16 bit code units.
Part II - Re generating the Emojis for the "league table"
Suppose the league table data squirted back to the app by my servers has the entry {emoji: [128583, 8205, 65039],username:"Stackexchange",points:100} for the emoji character 🙇‍️. Now here is the bothersome thing. If I do
var origCP = [],
i = 0,
origEmoji = '🙇‍️',
origLen = origEmoji.length;
while ((i < origLen) && (255 < origEmoji.codePointAt(i))
{origCP.push(origEmoji.codePointAt(i);i += 2;}
I get
origLen = 5, origCP = [128583, 8205, 65039]
However, if I regenerate the emoji from the provided data
var reEmoji = String.fromCodePoint.apply(String,[128583, 8205, 65039]),
reEmojiLen = reEmoji.length;
I get
reEmoji = '🙇‍️'
reEmojiLen = 4;
So while reEmoji has the correct emoji its reported length has mysteriously shrunk down to 4 code units in place of the original 5.
If I then extract code points from the regenerated emoji
var reCP = [],
i = 0;
while ((i < reEmojiLen) && (255 < reEmoji.codePointAt(i))
{reCP.push(reEmoji.codePointAt(i);i += 2;}
which gives me
reCP = [128583, 8205];
Even curioser, origEmoji.codePointAt(3) gives the trailing surrogate pair value of 9794 while reEmoji.codePointAt(3) gives the value of the next full surrogate pair 65039.
I could at this point just say
Do I really care?
After all, I just want to show the league table emojis in a separate column so as long as I am getting the right emoji the niceties of what is happening under the hood do not matter. However, this might well be stocking up problems for the future.
Can anyone here shed any light on what is happening?
emojis are more complicated than just single chars, they come in "sequences", e.g. a zwj-sequence (combine multiple emojis into one image) or a presentation sequence (provide different variations of the same symbol) and some more, see tr51 for all the nasty details.
If you "dump" your string like this
str = "🙋‍️StackOverflow"
console.log(...[...str].map(x => x.codePointAt(0).toString(16)))
you'll see that it's actually an (incorrectly formed) zwj-sequence wrapped in a presentation sequence.
So, to slice emojis accurately, you need to iterate the string as an array of codepoints (not units!) and extract plane 1 CPs (>0xffff) + ZWJ's + variation selectors. Example:
function sliceEmoji(str) {
let res = ['', ''];
for (let c of str) {
let n = c.codePointAt(0);
let isEmoji = n > 0xfff || n === 0x200d || (0xfe00 <= n && n <= 0xfeff);
res[1 - isEmoji] += c;
}
return res;
}
function hex(str) {
return [...str].map(x => x.codePointAt(0).toString(16))
}
myStr = "🙋‍️StackOverflow"
console.log(sliceEmoji(myStr))
console.log(sliceEmoji(myStr).map(hex))

How can I make this Google Apps Script loop efficiently?

I'm making an script that increases the value of a cell by 0.01 until it matches the value of another cell (gets the value, pass through a formula than see if the other cell value matches). The problem is that it takes too long to execute. It was very simple to do on excel, but I don't know how to program in G-Apps Script (neither js).
I guess it's taking too long because it runs on the cloud. There is anyway I can solve it?
Here the code so far:
function Calculate() {
var ss = SpreadsheetApp.getActive();
var vF = ss.getSheetByName('magic').getRange('C31').getValue();
ss.getSheetByName('magic').getRange('C32').setValue(0);
var vE = ss.getSheetByName('magic').getRange('C32').getValue();
var vP
for(vE=0;vE != vP;vE+=0.01){
ss.getSheetByName('magic').getRange('C32').setValue(vE);
var qParc = vF - vE;
ss.getSheetByName('magic').getRange('C3').setValue(qParc);
vP = ss.getSheetByName('magic').getRange('F3').getValue();
}
Thanks in advance!
More likely it's running "too long" because vE != vP is never false, because the kind of floating point used by JavaScript (IEEE-754 double-precision binary floating point, used by most programming languages) is inherently imprecise. Famously, 0.1 + 0.2 is not 0.3 (it's 0.30000000000000004). As a result, it's unreliable to use == or != (or === or !==) with possibly-fractional numbers. (You're okay if they're integers, provided they're not really big ones.)
There probably isn't any need for a loop if you want to update a value to make it match another. Just take the difference and add that to the one you're updating.
But if you do need the loop, replace != with <.
for (vE = 0; vE < vP; vE += 0.01) {
You're also repeating a lot of operations, perhaps expensive ones, there. Once you have the object for (say) a sheet or cell, remember that object reference and reuse it:
function Calculate() {
var ss = SpreadsheetApp.getActive();
var magic = ss.getSheetByName('magic');
var c32 = magic.getRange('C32');
var c3 = magic.getRange('C3');
var f3 = magic.getRange('F3');
var vF = magic.getRange('C31').getValue();
var vE, vP, qParc;
for (vE = 0; vE < vP; vE += 0.01) {
c32.setValue(vE);
qParc = vF - vE;
c3.setValue(qParc);
vP = f3.getValue();
}
}
(I also removed an unnecessary var vE = c32.getValue(); from that, since you immediately overwrite vE with 0 at the beginning of the loop. I just added the declaration to the var declaring vP and, now, qParc.)

How to write and call functions in javascript with for loops?

I am working on writing code for a course and need to figure out why the code output is not executing properly. I am very new to coding, this is a beginner assignment so all help and explanations are greatly appreciated.
The output should look like this:
Output:
How many times to repeat? 2
Stats Solver execution 1 ====================
give a number 10.10203
give a number 20
give a number 30
give a number 40
give a number 50
sum: 150.10203
average: 30.020406
max: 50
min: 10.10203
ratio: 4.94
Stats Solver execution 2 ====================
give a number 3.21
give a number 2.1
give a number 1
give a number 5.4321
give a number 4.321
sum: 16.0631
average: 3.21262
max: 5.4321
min: 1
ratio: 5.43
done ====================
Here is the code:
"use strict";
function myMain() {
var num = Number(prompt("give a number of times to repeat, must be 0 or greater"));
var count = num;
for (var a=0; a<=num; a++) {count++;}
alert("Stats Solver execution " + num + " ===================");
if (num===0){alert("done ==================="); return;}
wall()
alert("done ===================");
}
function wall(){
var num1 = Number(prompt("provide a number"));
var num2 = Number(prompt("provide a second number"));
var num3 = Number(prompt("provide a third number"));
var num4 = Number(prompt("provide a fourth number"));
var num5 = Number(prompt("provide a fifth number"));
var sum = (num1+num2+num3+num4+num5);
alert("sum: " + sum);
var avg = (sum/5);
alert("average: " + avg);
var max = (Math.max(num1,num2,num3,num4,num5));
alert("max: " + max);
var min = (Math.min(num1,num2,num3,num4,num5));
alert("min: " + min);
var ratio = (max/min);
alert("ratio: " + Math.floor(ratio*100)/100);
}
myMain();
Well you really aren't very far off at all. Actually your solution has all the code you need just some of it is in the wrong place. I would have posted this as a comment but as this is a new work account I can't actually post comments so here is a full solution with the explanations.
Your wall function, while annoying with all the alerts is actually correct and doesn't need any adjustments. With that said you might want to play with parseInt and parseFloat to make sure you are getting valid numbers but I am assuming that is outside of the scope of the assignment.
Now on to your main function.
var num = Number(prompt("give a number of times to repeat, must be 0 or greater"));
This is ok and will prompt the user for a number, once again you might want to test that you got a valid number using the aforementioned links.
var count = num;
for (var a=0; a<=num; a++) {count++;}
alert("Stats Solver execution " + num + " ===================");
if (num===0){alert("done ==================="); return;}
wall()
alert("done ===================");
This is where things start to fall apart a bit and where i think you are having problems. So I will break this down line for line and explain what each line is doing and you can compare that to what you think its doing.
var count = num;
Nothing crazy here, you are just creating another variable to hold the value in the num variable. Slightly redundant but not really a big deal.
for (var a=0; a<=num; a++) {count++;}
This is the line that appears to have given you the most confusion. This is the actual loop but inside the body of the loop { .... } nothing is being done except 1 is being added to count (count++). If I am understanding the assignment correctly, inside this loop is where you need to call your wall function after alerting the 'Stats Solver execution .....' stuff. All you need to do is move your function call inside this loop.
if (num===0){alert("done ==================="); return;}
wall()
alert("done ===================");
This part is clearly you a little lost and just trying things to get it to work, don't worry even after 12+ years of development i still write code like this ;). You really don't need this as the actual call to wall() will work fine for you.
I am bored and am waiting on work so for the sake of being a complete answer here is an example of how your code should look. Please don't just hand this in rather try and actually understand the difference between what i wrote and what you did because these are some very basic concepts that if you gloss over will make your life much harder down the road. Always feel free to ask, thats how people learn.
function myMain(){
// get the number of repetitions from the user and cast as a number
var num = Number(prompt('Please enter the number of times to repeat'));
// loop from 0 to the number the user provided - 1 hence the <
for (var i = 0; i < num; i++){
// alert the iteration of the loop, you will notice i add 1 to num when we alert it; this is because it starts at 0 so the first time it displays it would show 'Stats Solver execution 0 ======' instead of 'Stats Solver execution 1 ======'
alert('Stats Solver execution ' + (num + 1) + ' ===============');
// call your wall function
wall();
// go back to the top of the loop
}
// alert that we are done.
alert('done===============')
}
// your wall function goes here
// call your myMain function to kick everything off
myMain();
Just for fun you might want to look at console.log instead of alert to not make it such an annoying process with all the popups.
If i missed anything or you are confused about anything don't hesitate to ask and i'll do my best to answer.

Show all numbers from 1 to n increasing from 1 to 1 where n is entered by the user at a prompt

I´m learning javascript, so please be gentle with me.
About my question above, this is the code I made, the difficult part for me is related to the prompt, if the task were "show all the numbers from 1 to 10 using a while", I know how to do it.
var x = Number(prompt("Ingrese un número"));
var contador = 1;
while (contador <= x) {
console.log(contador + x);
contador++;
}
If you want to show number from 1 to user entered number then why you add x in console log try below code it will show 1 to x,
var x = Number(prompt("Ingrese un número"));
var contador = 1;
while (contador<=x) {
console.log(contador);
contador++;
}
If u need using while do this:
var x = Number(prompt("Ingrese un número"));
var contador = 1;
while (contador<=x) {
console.log(contador++); //return number and increase it for next loop
}
But the best and fastest solution is this:
var x = Number(prompt("Ingrese un número"));
for(var i = 1; i <= x; i++)
console.log(i);
I think you've understood the while part.
Here is what the prompt part does:
prompt creates a prompt window (like an alert window) which asks for user input. The user input, by default, is a string.
So we we need to convert it into a number. we use Number(someStrongValue) to convert this user input to a number.
Number("1") == 1
Number("a") == NaN
If you didn't convert the string to a number, you may end up with an infinite loop, or the loop may not even run.
If the user enters a string in prompt, Number will return NaN.
and any number < NaN is false. Hence, your loop won't run (and no infinite loop)
You can read more about prompt here: https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt

how to generate unique ID character using letters a-z

Here is a little challenge, I hope it will be useful for others too.
Task is to obtain an ID character from alphabets of english language. a-to-z
My solution currently allows ID (words) of 26 diff length (max possible). with 90 possible words.
I know this can be increased if we pick random characters after single character IDs are obtained (done with.) (But) I am finding it hard to figure out how to manage NOT hitting a combination already found (ID has to be unique). As we see it takes a long time if it starts finding the same combinations over and over. this probability increases as we obtain more and more ID-combinations.
Here is my code and fiddle to test and check:
fiddle
code:
html
<p>
start
</p>
jquery:
function addto(t) {
$("p").append("<b>" + t + "</b>");
}
global_ID_array = [];
lowerAlpha = "abcdefghijklmnopqrstuvwxyz";
var myIDlength = 1;
function getIDChar (){
do {
var myIDchar = lowerAlpha.substr(0, myIDlength);
lowerAlpha = lowerAlpha.replace(myIDchar,'');
if (lowerAlpha.length < myIDlength){
lowerAlpha = "abcdefghijklmnopqrstuvwxyz"; //reset
myIDlength++;
}
} while (global_ID_array.indexOf(myIDchar) > -1)
global_ID_array.push(myIDchar);
addto(myIDlength+':'+global_ID_array.length+',');
}
do{
getIDChar();
}while (myIDlength < 26);
addto('<br \>myIDlength='+myIDlength);
addto('<br \>global_ID_array last val='+global_ID_array[global_ID_array.length-1]+'<p>');
To get started, instead of thinking about the IDs in terms of letters, think about it in terms of numbers.
Since there are 26 possible characters, each character can be considered as a digit of a base-26 numeric system, with a == 0, and z == 25. The problem now boils down to generating a number and converting it to base-26 using the alphabets as digits. Since the ID length is 26 characters, we can generate up to 26^26 unique IDs.
Now, to make sure that the ID generated is unique (up to 26^26 generated IDs), we need to find a way to generate a unique number every time. The simplest way to do this is to initialize a counter at 0 and use it to generate the ID. Every time an ID is done generating, increment the counter. Of course, this is a very deterministic generation algorithm, but you could use a seeded random number generator that guarantees the uniqueness of random numbers generated in a range.
The algorithm may look as follows:
n = random(0, 26^26 - 1)
id = "a" * 26
// chars[i] is the character representing the base-26 digit i;
// you may change/shuffle the list as you please
chars = ['a', 'b', 'c', ..., 'y', 'z']
for i in 0..26 {
// Get the character corresponding to the next base-26 digit of n (n % 26)
id[26 - i] = chars[n % 26]
n /= 26
}

Categories

Resources