I have what I think surely is a really simple question for most of you. But I have some trouble to get my head around this for loop. What does the -1 in argument.length -1 stand for? Is it the last item? And the i-- that is for decrease by 1?
var plus = function() {
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2,2,3,657,5643,4465,2,45,6));
When you call arguments.length It will return you the number of elements with the last one accessed with arguments[arguments.length-1] because counting starts with 0.
(the First element is accessed like this arguments[0]).
Here is good documentation for Java but it is the same for JavaScript: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
And yes i-- decreases i for 1. It is different i-- and --i.
Using ++/-- After the Operand
When you use the increment/decrement operator after the operand, the value will be returned before the operand is increased/decreased.
Check out this example:
// Increment
let a = 1;
console.log(a++); // 1
console.log(a); // 2
// Decrement
let b = 1;
console.log(b--); // 1
console.log(b); // 0
When we first log out the value of a, or b, neither has changed. That’s because the original value of the operand is being returned prior to the operand being changed. The next time the operator is used, we get the result of the +1, or -1.
Using ++/-- Before the Operand
If you’d rather make the variable increment/decrement before returning, you simply have to use the increment/decrement operator before the operand:
// Increment
let a = 1;
console.log(++a); // 2
console.log(a); // 2
// Decrement
let b = 1;
console.log(--b); // 0
console.log(b); // 0
As you can see in the above example, but using ++ or -- prior to our variable, the operation executes and adds/subtracts 1 prior to returning. This allows us to instantly log out and see the resulting value.
The - 1 means to subtract 1 from arguments.length. i-- means to decrease i by 1.
You need to know two things here:
arguments is a object type so it has key-value pair of values you passed as a argument into a function. Furthermore, the arguments object is not an Array. It is similar to an Array, but does not have any Array properties except length.
The key of arguments always starts with 0 and ends with one value less than the length of arguments. See the example below the key ends at 8 so you do arguments.length - 1 so that you get 8 instead of 9.
And since you are looping considering the last value first in arguments you do --i.
var plus = function() {
console.log(arguments);
console.log(typeof arguments);
var sum = 0;
for (var i = arguments.length - 1; i >= 0; i--) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));
Alternatively, you can also do i++ as,
var plus = function() {
var sum = 0;
for (var i = 0; i <arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(plus(2, 2, 3, 657, 5643, 4465, 2, 45, 6));
Related
The solution that i've been working on so far:
function solution(elements) {
let numOfShifts;
let shift = shiftedArray(elements);
for(i = 0; i < shift.length; i++){
//Here is where i'm getting stuck... how do i continue through the loop even after the first false is returned
//until all arrays are checked for equality?
if(areEqual(shift[i])){
numOfShifts = i
}else return -1;
}
return numOfShifts;
};
function shiftedArray(array){
let shiftedArrays = [];
for(let i = array.length -1 ; i >= 1; i--){
// first element is simply a formula to create chunk 1
let firstElement = array.length - (i % array.length);
//the result of first element.
let chunk1 = array.slice(firstElement);
//the remaining numbers
let chunk2 = array.slice(0, firstElement);
//Copy of both chunks now merged and pushed into shifted arrays
shiftedArrays.push([...chunk1, ...chunk2]);
};
return shiftedArrays;
}
function areEqual(shift){
let sortedShift = [...shift].sort((a ,b) => {
return a - b
});
//takes in a single shift and does a deep check to see if the array is equal to sorted version
if(sortedShift.length === shift.length){
return sortedShift.every((element, index) => {
if(element === shift[index]){
return true;
}
return false;
})
}
}
console.log(solution([1,4,2,3]));
console.log(solution([[2, 3, 4, 5, 6, 7, 8, 9, 10, 1]]))
How do I keep the for loop running even after the first false is returned from the areEqual() function?
A side note: I understand that this could probably use some refactoring... like, I was working on this with someone earlier and they mentioned how I can simply shift the array by writing a helper function like shiftArray(arr){return arr.push(arr.pop())} but I don't get how that implementation would work considering that all that's returned is the value that was taken out of the array, not the new shifted array.
You may be doing too much work.
Say you have an array A of n integers, zero indexed.
Parse the array from index 0 to n mod n (so 0 twice). Count the number of pairs where the latter integer is less than the former, and store the first index where this happens.
If the count is 1 and the location is k (so A[k] < A[k-1]), then a cyclic shift of either -k or n-k will convert A to a sorted array. If the count is greater than 1 then there's no solution.
E.g., [4,5,0,1,2,3] -- we see k=2 is the only index which has a value below its predecessor, and a cyclic shift of -2 or 4 forms [0,1,2,3,4,5] which is sorted.
code:
function OneDecremented(num) {
num = num.toString()
var count = 0
for(i = 1; i < num.length; i++) {
if(num[i - 1] - num[i] === 1){
count++
}
}
return count
}
console.log(OneDecremented(9876541110))
so I'm struggling to understand two things:
what's the difference between i and num[i]
I don't understand how the calculation is happening inside the if statement, could someone break it down?
sorry if these questions sound too silly, I'm new to JS and couldn't really get my head around the arithmetic calculations. Thank you for you time.
That code is poorly written for few reasons, but most importantly, it leaks the i reference globally so, let's start with a better version:
function OneDecremented(num) {
var str = num.toString();
var count = 0;
for(var i = 1; i < str.length; i++) {
if(str[i - 1] - str[i] === 1)
count++;
}
return count;
}
Strings, in modern JS, can be accessed like arrays, and the index returns the char at the index position:
if(str[i - 1] - str[i] === 1)
// is the same as
if ((str.charAt(i - 1) - str.charAt(i)) === 1)
Once retrieved each char, the code does an implicit "char to number" conversion, thanks to the - operator, but if it was a + instead, it would've concatenated the two chars as string instead (so, be careful).
It's always better to be explicit, but if you know how - works, it does the job for this task.
The loop starts from 1, and it checks that the char at i - 1, which is in the first iteration the char at index 0, minus the current char, is 1, meaning the current char is one less the previous.
When that's the case, the counter sums up.
Andrea and Mitya already nailed it.
The next step could be switching to a first class based approach like using a specific Array method such as reduce.
Such an approach, if implemented correctly, usually improves readability/maintainability of code and allows for better code-reuse.
For the example provided by the OP one could write two functions, the actual method, which gets the count and the above mentioned first class reducer functionality. Since reduce is a standard way of how arrays can be processed the arguments-precedence of the reducer/callback is well specified too ...
[/* ... */].reduce(function(accumulator, currentValue, currentIndex, currentlyProcessedArray) {
// implement reducer/aggregation/accumulator logic here.
// the return value serves as the
// new `accumulator` value within
// the next iteration step.
// thus, always return something! ... e.g ...
return (accumulator + currentValue);
});
function aggregatePrecursorAndDecrementedSuccessorCount(count, char, idx, arr) {
const precursorValue = Number(arr[idx - 1]);
const incrementedCurrentValue = (Number(char) + 1);
const isValidCount = (precursorValue === incrementedCurrentValue);
return (count + (isValidCount ? 1 : 0));
//return (count + Number(isValidCount)); // cast boolean value to either 1 or 0.
}
function getPrecursorAndDecrementedSuccessorCount(int) {
return String(int) // - assure/typecast always a/into string value.
.split('') // - split string value into an array of single characters.
.reduce(aggregatePrecursorAndDecrementedSuccessorCount, 0);
}
console.log(getPrecursorAndDecrementedSuccessorCount(9876541110));
.as-console-wrapper { min-height: 100%!important; top: 0; }
what's the difference between i and num[i]
i is the iteration key, i.e. 0, 1, 2 etc, for as many characters are in the stringified number. num[i] is the character at the index i in the string, i.e. num[i] where i is 0 == 9 (the character in the string at index 0).
I don't understand how the calculation is happening inside the if statement, could someone break it down?
That says: If the calculation of the number at index i-1 of the string, minus the current number being considered (at index i in the string) minus is 1, then increment count.
Step by step for the actual number used:
9 - has no previous character; calculation (undefined - 9) does not equate to 1
8 - previous char is 9; (9 - 8) == 1; increment count
7 - ditto
6 - ditto
5 - ditto
4 - ditto
1 - previous char is 4; calculation (4 - 1) does not equate to 1
1 - previous char is 1; calculation (1 - 1) does not equate to 1
1 - ditto
0 - previous char is 1; (1 - 0) == 1; increment count
I'm having a hard time with this problem here:
Write a function named sumEvery5th that accepts a non-negative integer n and returns the sum of the integers divisible by 5 from 1 to n, including n itself. Use a for loop.
This is what I have so far:
var sumEvery5th = function(n){
let sum = 0;
for(let i = 1; n % 5 == 0; i++){
sum+ i
};
return sum;
}
I feel like I'm really close. Thanks for the help in advance.
You can start your loop at 5, since 1, 2... are not divisible by 5. And instead of i++, you can directly go 5 by 5, until i is greater than n:
var sumEvery5th = function(n) {
let sum = 0;
for (let i = 5; i <= n; i += 5) {
sum += i;
};
return sum;
}
console.log(sumEvery5th(10)); // 5 + 10 = 15
console.log(sumEvery5th(18)); // 5 + 10 + 15 = 30
First I think you should understand how a for loop works.
var sumEvery5th = function(n){
let sum = 0;
for(let i = 1; n % 5 == 0; i++){
sum+ i
};
return sum;
}
What you are doing, step by step, is:
Declaring a variable i with value 1.
Dividing n by 5 and taking the remainder value and comparing it with 0. In case it's true, you are skipping the code block inside the for and moving towards the return sum; line.
(In case you haven't skipped the code block in step 2) Run the code block with the new i value.
(In case you haven't skipped the code block in step 2) Incrementing the i value.
Go back to step 2.
Usually your for condition will depend in the variable declared in step 1. What you want to do is run the for code block n times.
For that, you need to change your condition from n % 5 == 0 to i <= n. This will make sure to run the code block while your i is less or equal than n, starting with a value of 1.
Now, inside your code block you add your divisible by 5 logic, checking against i value.
for(let i = 1; i <= n; i++){
if (i%5 == 0) sum += i;
};
Now let's say I called sumEvery5th(5).
Declare a variable i with value 1.
Check if i (1) is less than or equal n (5).
Go inside the code block.
Check if i%5 is 0.
It's not.
Increment i, now i = 2.
Check if i (2) is less than or equal n (5).
...And so on, until i = 6, and in that case the code block is skipped and the program will continue its course.
Ps.: There are ways to improve the performance of this algorithm, but now that you understand your for loop a bit better I'll leave it to you :)
var sumEvery5th = function(n){
let sum = 0;
for(let i = 1; i <= n; i++){
if (i % 5 === 0) {
sum += i;
}
}
return sum;
}
I am writing a function that takes a number and returns the factorial of it. It works, but why do you have to "-1" on the first parameter of the second for() statement?
var firstFactorial = function(num){
var numBreakdown = [];
var total = 1;
for(var i = 1; i <= num; i++){
numBreakdown.push(i);
}
for(var y = numBreakdown.length-1; y > 0; y--){
total *= numBreakdown[y]
}
console.log(total);
return total;
}
firstFactorial(7);
This is because, in the array, index (position) of the last element is always one less than the length. And you have to start you operation from the last element which is on length-1 index.
This is your array with all the seven elements and their index..
numBreakdown=[1,2,3,4,5,6,7]
| | | | | | |
index:0,1,2,3,4,5,6
You can see to access the element 7 you have to use numBreakdown[6] or numBreakdown[length-1], here length=7 or numBreakdown[y] where y=length-1.
Ryan explained the reasoning behind the -1 well in the comments above:
Array indexes go from 0 to one less than the length. ['first', 'second', 'third'] has indexes 0, 1, and 2. Not sure why you would store the numbers to multiply in an array, though; you can just multiply total in the first place.
As for the factorial function, most of it is unnecessary, including the use of arrays to store the factors of the factorial. See the alternative implementation below.
function factorial (n) {
if (n < 0) throw new TypeError('`n` must be non-negative')
var result = 1
while (n > 1) result *= n--
return result
}
console.log(factorial(0)) //=> 1
console.log(factorial(1)) //=> 1
console.log(factorial(7)) //=> 5040
If you would like any further clarification or have questions about the above code, feel free to ask!
Should add all the natural numbers below 1000 that are multiples of 3 or 5.
var sum = _.reduce( _.range(1, 1000), function(x, n) {
if (n % 3 == 0 || n % 5 == 0) { return x+=n; }
}, 0);
I expect the output to be 233168 but I get NaN.
For some reason sum is not accepting the initialized value of 0. However if I preface this with var sum = 0; then it works and returns the proper output of 233168
Why doesn't it accept the initialized value?
The problem is the reducing function returns undefined when the conditional fails .. thus x evaluates to undefined (the last return value) in the subsequent invocation .. and undefined + a number is .. well, NaN.
Also, reduce is being used incorrectly; it should carry its own state. Compare it with:
var sum = _.reduce( _.range(1, 1000), function(x, n) {
// Add n to the tally if it is a valid multiple..
// (the returned value is used as the *next* value of x)
if (n % 3 == 0 || n % 5 == 0) { return x + n; }
// ..or simply return the current tally.
else { return x; }
}, 0);
Note that the sum variable was not assigned from within the reducing function (it would have been overwritten by the outside assignment anyway). This keeps reduce a pure operation, not withstanding the occasional abuse of a mutable memo, truer to its functional roots.