I'm a new student who's learning Javascript for the first time. This time I'm trying to better grasp the concepts of converting numbers into strings, storing them in arrays, converting them back to numbers, and adding.
In this assignment, I'm trying to write a function that takes the individual digits of a number and adds them together.
So for example, the function would take (95) and return 14. Or given (135), would return 9.
Here's what I got so far:
var addDigits = function(num) {
var newNum = num.toString();
newNum = newNum.split('');
var sum = 0;
var thirdNum = newNum.forEach(function(x) {
parseInt(x);
sum + x };
};
I'm fully aware that is not very good code, but could anyone give me any tips? Should I be using parseInt or Number?
You're pretty close. Few things though. array.forEach doesn't return anything. It's used for creating side effects (increasing sum would be considered a side effect of the function you're passing into the forEach). So setting the forEach to a variable doesn't accomplish anything. parseInt does return something, so you need to set it to a variable. And you also want to increase sum by the parsed integer plus the sum you already have. You can look into the += operator for that if you wish. Last, you need to return a value from the function itself! As it is, if you did var added = addDigits(123), added would be undefined. So finish it off with a return statement.
After you've got the grasp of that, I'd suggest looking into array.reduce to replace array.forEach since it's perfect for a problem such as this.
var addDigits = function(string) {
newNum = string.split('');
var sum = 0;
for(var i = 0 ; i < newNum.length ; i++) sum += parseInt(newNum[i]);
return sum;
};
console.log(addDigits("1234"));
Maybe this will be better:
function getDigitsSum(number) {
var charArray = (number + '').split('');
var sum = 0;
charArray.forEach(function(item) {
sum += parseInt(item)
})
return sum;
}
Number() performs type conversion, whereas parseInt() performs parsing.
What is the difference between parseInt() and Number()?
In this situation, it doesn't make a difference since the strings are proper integers.
Here's how I would do it.
var addDigits = function(num) {
var newNum = num.toString().split('');
var sum = newNum.map(Number).reduce((prev, curr) => prev + curr);
return sum;
};
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Assuming your input will always be an integer string, consider the following function:
var addDigits = function(strInt) {
var int = function(x) {
return parseInt(x,10) //10 is the radix
}
return strInt.split('').map(int).reduce(function(a,b){return a+b});
}
The function tied to var int will ensure that the provided integer string be parsed into its corresponding base 10 integer (notice the difference in type, which can be validated with Javascript's built-in typeof() function). The return will first .split the string, .map the int function against every value within the given string, and then apply whatever function you have within .reduce against an accumulated value - in this case, simply adding against each member of the array.
Related
I would like to know how I can sum an algebraic sum.
For example, I have a function with two parameters:
function sumAlga(paramA, paramB) {
return paramA + paramB;
}
How I should do it for algebraic sum in JavaScript?
Incorrect Code
As "don't angry me" has said in the comments, you have return paramA + paramBM not return paramA + paramB so that should fix that (assuming that was an unintentional typo, correct me if we're wrong).
More than two arguments
To accomplish this with any number of parameters you could do the following,
function algebraicSum() {
var sum = 0;
for (var i = 0; i < arguments.length; ++i) {
sum += arguments[i];
}
return sum;
}
Usage
algebraicSum(1,2,3,4) = 10;
algebraicSum(1,-2,3) = 2;
you can try something like this:
var age_child = parseInt(10);
var age_gap = parseInt(10);
alert(age_child+age_gap);
Unlike Java or C, which are strongly typed languages, Javascript is smart and hence is also called a weakly typed language. You don't have to specify the data-type of your variable while declaring it. but in this case, you should specify the data type to match with your operations.
The main purpose is to have a function which could be used as callback for Array#reduce, for example.
An array with values could be summed by taking the function and a start value of zero (this is necessary, if an empty array or an array with only one item is supplied).
function add(a, b) {
return a + b;
}
console.log([1, 2, -5].reduce(add, 0));
console.log([1].reduce(add, 0));
console.log([].reduce(add, 0));
The following code uses an arrow function, which has some differences to the standard function, but is sometimes shorter.
const add = (a, b) => a + b;
console.log([1, 2, -5].reduce(add, 0));
console.log([1].reduce(add, 0));
console.log([].reduce(add, 0));
This is my assignment:
By now you should have worked with the length property of strings, e.g. "hello".length. Your task is to write a function called stringLength that accepts a string as a parameter and computes the length of that string; however, as you may have guessed, you are not allowed to use the length property of the string!
Instead, you'll need to make use of the string method called slice.
For our purposes, we can consider slice as taking one argument -- the index to begin slicing from, and returns a new string starting from that index onwards.
This is what I tried:
function stringLength(string){
var count = count++;
if(string.slice(0)){
return count}
return stringLength(string.slice(0,-1))
}
console.log(stringLength("game"))
I am trying to slice each character of the string back to start index, index 0, and then accumulate my count variable. I do not understand why my count variable is not accumulating.
An iterative proposal.
function stringLength(string) {
var count = 0;
while (string) {
string = string.slice(1);
count++;
}
return count;
}
console.log(stringLength("game"));
A recursive proposal.
function stringLength(string) {
return string ? 1 + stringLength(string.slice(1)) : 0;
}
console.log(stringLength("game"));
Hmm i tried to write code in the same format that you did.
function stringLength(str, count){
if(!str.slice(0)){
return count;
}
return stringLength(str.slice(0,-1), ++count)
}
console.log(stringLength("game", 0))
I'll point out the mistakes in your original code so that its easy to understand.
The recursion base case was incorrect. string.slice(0) will return
true if the string is non-empty, so use !string.slice(0)
The count value was not initialized and it wasn't being passed down
the recursion.
Your count variable is a separate variable for each function invocation, so it will always get the same value and not keep incrementing.
You could use this:
function stringLength(string){
return string ? 1 + stringLength(string.slice(0,-1)) : 0;
}
console.log(stringLength("game"))
A bit shorter would be to take out the first character instead of the last:
return string ? 1 + stringLength(string.slice(1)) : 0;
You really should try to figure it out yourself. Otherwise, are you really learning the subject?
function stringLength(string) {
if(!string) return 0;
var length = -1;
while(string.slice(length) !== string) --length;
return -length;
}
A variation taking into account your odd definition of slice():
function stringLength(string) {
var length = 0;
while(string.slice(length) !== "") ++length;
return length;
}
I guess you could try to use recursion like this:
function stringLength(string) {
if (string) {
return 1 + stringLength(string.slice(1))
} else return 0
}
function stringLength(string) {
var len = 0;
while (string) {
string = string.substring(1);
len++;
}
return len;
}
console.log(stringLength("boss"));
this works as well.
I am trying to write a code that converts a Binary into string, i take solutions step by step, my first step is add charcodes then use fromCharcode, I don't know if this is possible but on this is my code:
function binaryAgent(str) {
var x = str.split(' ').map(function (item) { // split with space
return item.split(''); //split every character
});
var fg = [];
for(var i=0; i<x.length; i++) {
var f = x[i].reduce(function (toArray,item){
debugger;
var rightPattern = [128,64,32,16,8,4,2,1]; // i want to create this array on every iteration
var op = rightPattern.shift(); // on every iteration, shift a value from rightPattern, this is for binary pattern
if(item=='1'){ // if item is 1,i think it doesn't matter if it's string or num, I care for 0 and 1 only, push the variable op, shifted from array
return toArray.push(op); // push it on the initial value,
}
}, []); // []<-- initial array.
return x;
}
}
binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");
I checked this with debugger and I have observed that: ON every iteration, my rightPattern array is set to undefined again and reset, I also cannot use push and I have this error, TypeError: Cannot read property 'push' of undefined
on MDN, there is an example using concat() method so i tried to push Array.prototype.reduce()
I'd write your function like this:
function binaryAgent(encoded) {
return encoded.split(' ').map(function(bytestr) {
return String.fromCharCode(parseInt(bytestr, 2));
}).join('');
}
Converting binary representation into numbers is, well, an old task, and it's already solved for you. Even if you want to write your own implementation for studying purposes, it's better to abstract it (so that you can replace parseInt(bytestr, 2) line - but leave the rest of the code intact.
One possible reduce-using approach (not the most performant, mind you, but employing a pretty common technique):
function parseBinary(str) {
return str.split('').reduce(function(acc, el) {
return acc * 2 + +el;
}, 0);
}
That is, you don't have any 'pre-filled' arrays of powers of 2; instead your accumulator is multiplied by 2 at each reducer step, adding the current digit. As + operator is overloaded, you should convert the digit operand into a number (the easiest way is applying unary plus - +).
Answering the question given in the comments: you can easily convert any number to binary, octal or hex format by calling toString() on it, with a passed argument treated as a radix. But here's a function for it:
function toBinary(num, reslen) {
var res = '';
while (num || res.length < reslen) {
res = (num & 1) + res;
num >>= 1;
}
return res;
}
first of all - in your reduce function - if item wont be equal to one - in the next iteration toArray will be undefined.
you need to always return a value in the reduce function in order for the first argument (the accumulator) to be defined
should be something like that -
if (item == 1) {
toArray.push(op);
}
return toArray;
other than that as I understand your code - the rightPattern var should be outside the reduce function but inside the for loop.
In CoffeeScript, I like to use destructuring assignments when returning functions with multiple return values. It makes it clearer what is being returned, versus returning an array.
For instance, returning an array from a function in JavaScript:
function getSumAndDiff(firstNumber, secondNumber) {
var sum = firstNumber + secondNumber
var difference = firstNumber - secondNumber
return [sum, difference]
}
var values = getSumAndDiff(10, 5)
var sum = values[0]
var difference = values[1]
While in CoffeeScript, returning an object from a function:
getSumAndDiff = (firstNumber, secondNumber) ->
sum = firstNumber + secondNumber
difference = firstNumber - secondNumber
{sum, difference}
{sum, difference} = getSumAndDiff(10, 5)
However, the problem is that the CoffeeScript method replaces any existing variables called sum and difference. So if I ran this function multiple times in succession, then they would keep overwriting the previous one.
There are several ways of resolving this, of course, such as simply by assigning the returned variables to other names each time, like so:
{sum, difference} = getSumAndDiff(10, 5)
sum1 = sum
difference1 = difference
{sum, difference} = getSumAndDiff(11, 6)
sum2 = sum
difference2 = difference
But is there a cleaner way of doing it? Or, is perhaps the best solution to simply return an array when I need to run a function like this multiple times in a row? Or would closures make sense, or is that too much excessive code? I'm just wondering if there's something I'm perhaps missing, because I figure there's got to be a cleaner way of doing this, especially with CoffeeScript? Or maybe my general approach to this is flawed, such as I should instead only have one return value per function instead, to simplify things?
What you have now...
Ok, I get the point now. When you write:
getSumAndDiff = (firstNumber, secondNumber) ->
sum = firstNumber + secondNumber
difference = firstNumber - secondNumber
{sum, difference}
The function getSumAndDifference returns an associative array (well, an object) having for key the name of the variables and for value their content. This is only syntactic sugar equivalent to:
{ 'sum': sum, 'diff': diff }
That associative array is the value returned and you then use object destructing to get back the various fields of interest:
{sum, difference} = getSumAndDiff(10, 5)
Once again this is only syntactic sugar around:
_obj = getSumAndDiff(10, 5)
sum = _obj['sum']
diff = _obj['diff']
... now, for some alternatives
1) Aliased object destructuring
First, as you explained yourself, you can use "aliased" object destructing to get back the values as an other name:
{sum:x, diff: y} = getSumAndDiff(10, 5)
This will set x to the same value as field sum of the returned object. And y as the same value as the field diff.
Syntactic sugar around:
_obj = getSumAndDiff(10, 5)
x = _obj['sum']
y = _obj['diff']
As a side note, notice again how {sum,diff} was in fact a shortcut to write {sum: sum, diff: diff}
2) Array destructuring
An other, somehow simpler alternative, is not to return an object but an array (more formally, a numerically indexed array) :
getSumAndDiff = (firstNumber, secondNumber) ->
sum = firstNumber + secondNumber
difference = firstNumber - secondNumber
[sum, difference] ## <-- array [ ... ] not object { ... }
With that syntax, sum and diff are returned as the item of index 0 and 1 resp. of an array. From caller side, you might then use array destructuring to extract those values:
[sum, diff] = getSumAndDiff(10, 5)
As the array is numerically indexed, you don't have to bother about field names. So you can write that too:
[x, y] = getSumAndDiff(10, 5)
[sum2, diff2] = getSumAndDiff(10, 5)
...
Okay, so I figured it out. I know that my question wasn't the clearest. Really, I was looking for a way to simplify my code, rather than finding an exact solution to an exact problem.
I realize now that since CoffeeScript's destructuring assignments are really just objects being passed from the return value to the global scope, basically, then I can just "rename" the variables on the spot by passing it to a different variable. (Not the greatest explanation... see examples below.)
For instance, return { test } really just means return { test: test } (which I knew before, but eventually forgot that it meant that).
So, rather than having {sum, difference} = getSumAndDiff(10, 5), I can instead do {sum: sum2, difference} = getSumAndDiff(10, 5).
This results in sum2 being set, rather than sum, which would replace sum if it has been set before, by calling the same function, for instance.
Just one of the quirks of using CoffeeScript, I guess! (Primarily the { test } means { test: test } notation.)
var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
return sum / arguments.length;
}
When I try to call this like:
var average = avg(2,3,5);
average; // It works fine;
But how do I call it without assigning to a variable?
If anybody can give any suggestion it will be delightful..Thanks.
You'd simply call it like this:
avg(2, 3, 5);
If you want to see the result, put it in an alert call:
alert( avg(2, 3, 5) );
You don't need to put the result from calling the function in a variable, you can do whatever you like with it.
For example, use it as the value in an alert:
alert(avg(2,3,5));
You can use it in another expression:
var message = "The average is " + avg(2,3,5);
You can use it directly in another call:
someFunction(avg(2,3,5));
You can even throw the result away by not doing anything with it, even if that's not useful in this specific situation:
avg(2,3,5);
If you don't put the result into a variable or in a compatible context, this function cannot output anything, which makes it difficult to use unless you make it output the result. Try this :
var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
var retvalue = sum / arguments.length;
consoloe.log("avg: "+retvalue);
return retvalue ;
}
Then it may help you to see whenever the function is called or not.
You need to understand the concept of expressions.
Every expression as a whole represents one value. An expression can be made up of multiple subexpressions that are combined in some manner (for example with operators) to yield a new value.
For instance:
3 is an expression (a literal, to be specific) that denotes the numeric value three.
3 + 4 is an expression, made up of two literal expressions, that as a whole yields the value 7
When you assign a value to a variable – as in var average = – the right hand side of the =-operator needs to be an expression, i.e. something that yields a value.
As you have observed, average will have been assigned the value five. It thus follows, that avg(2, 3, 5) must itself be an expression that evaluated to the value 5.
average itself is an expression, denoting the current value of said variable.
The most important thing to take away from this is, that avg() is in no way connected to var average =. avg() stands on its own, you can just think it like an ordinary value such as 5 (there are other differences of course).
If you have understood the concept of expressions and values, it should be clear that if you can do
var average = avg(2,3,5);
average; // It works fine;
You can also do
avg(2,3,5);