Understanding the modulus operator - javascript

I have some code that loops through a collection of list elements and a collection of colours. It makes sure each list element is designated to a colour.
I understand everything about this apart from the modulus operator. I get that it finds and uses the remaining number, but I cannot for the life of me understand what it is doing here?
var li = document.getElementsByTagName('li');
var colors = ["salmon", "teal", "orange", "grey", "blue"];
var colorsCount = colors.length;
for ( var i = 0; i < li.length; i++ ) {
li[i].style.backgroundColor = colors[ i % colorsCount ]; // why does this work?
}

Since there is (potentially) a larger number of items in the li array, this prevents i from being outside the bounds of the colors array, since i % colorsCount can never be over colorsCount.
For example, if we had 10 elements in li, and 5 colors, i % colorsCount would be:
i i % colorsCount Color
-------------------------------
0 0 salmon
1 1 teal
2 2 orange
3 3 grey
4 4 blue
5 0 salmon
6 1 teal
7 2 orange
8 3 grey
9 4 blue
More Information on Modulo Operations.

i % colorsCount will set the bound of the index to be between 0 and colorsCount-1, thus ensuring you never index past the end of the array.
Since mod is the remainder, the remainder can never be greater than the divisor (which in this case, is the length of the array).

Perhaps this snippet may help you understand:
var s = ''
for (var i = 0; i < 20; i ++) {
s += (i % 5) + ', '
}
console.log(s)
The result is:
0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
Note how the number resets to 0 every time it reaches 5. The % colors.length just makes sure the index never goes above the array's length.
A more descriptive way of understanding:
0 % 5: 0/5 = 0, remainder 0
1 % 5: 1/5 = 1/5, remainder 1
...
5 % 5: 5/5 = 1, remainder 0
6 % 5: 6/5 = 1 1/5, remainder 1
7 % 5: 7/5 = 1 2/5, remainder 2
...

It's cycling your colours. Because you only have a limited number of colours, and any number of possible list items, it makes sure that i will not overflow the bounds of your colors array.

The modulus operator returns the remainder of division. It allows you to loop through and reuse the colors array even though there are potentially less colors in the array than there are elements in your list to color.
If length is say 8,
5 % 1 == (5 / 1) = 0 remainder 1
5 % 2 == (5 / 2) = 0 remainder 2
5 % 3 == (5 / 3) = 0 remainder 3
5 % 4 == (5 / 4) = 0 remainder 4
5 % 5 == (5 / 5) = 1 remainder 0
5 % 6 == (5 / 6) = 1 remainder 1
5 % 8 == (5 / 7) = 1 remainder 2
5 % 7 == (5 / 8) = 1 remainder 3
As you can see, the remainders are what's returned by the mod operator, and they're always less than the length of the colors array.

why does i % colorsCount work?
What it does
This code cycles through colors. It does so using the modulus operator to ensure you're always within the bounds of the array.
How it does it
Modulus operation finds the remainder of division of one number by another.
In your case by taking i modulus the colorsCount:
0 % 5; // 0
1 % 5; // 1
1 % 5; // 2
3 % 5; // 3
4 % 5; // 4
5 % 5; // 0
8 % 5; // 3

The result of a modulus operation is the remainder after division of the left operand by the right operand.
So the line of code in question will always return some number between 0 and colorsCount-1.

You iterate from 0 until how many li elements you have. For this example, say 10.
You then look at the colors array and find the element for that iteration (i) and modulus by how many items are in the colors array.
In short, this is what's happening:
var colorsCount = 10;
1 % 10 = 1 // ... Access colors[1]; (teal)
2 % 10 = 2 // .... Access colors[2]; (orange)
3 % 10 = 3 // .... Access colors[3]; (grey)
4 % 10 = 4 // .... Access colors[4]; (blue)
5 % 10 = 5 // .... Access colors[5];
etc
If you are wondering why it will never access an element outside of the array, the answer is because as i becomes greater, the result becomes smaller.
For example, take iteration 8:
8 % 5 = 3
(Iteration 8, 5 elements in the array)
Therefore you are accessing colors[3];

Related

I want to filter only odd negative numbers from an array. Why does n % 2 === 1 not work, but n % 2 !== 0 does?

Write a function that returns only negative odd numbers from an array.
const arr = [4, -7, -6]
I first tried:
let negativeOdd = arr.filter(n => n % 2 === 1 && n < 0);
return negativeOdd;
result was an empty array. []. The answer should be [-5].
But when I replaced n % 2 === 1 with n % 2 !== 0, it workded. I am new to JS and was hopeing somenone could help me understand why this is happening. Thank you.
The modulo % operator in Javascript divides a number by a divisor (in this case 2), and returns the remainder.
-5 divided by 2 is -2.5, or -2 with a remainder of -1. 2 * -2 + -1 = -5
5 divided by 2 is 2.5, or 2 with a remainder of 1. 2 * 2 + 1 = 5
console.log(-5 % 2);
console.log(5 % 2);
A negative odd number gives
n % 2 === -1.
Just try it out. In the console, type
-5 % 2
There are different possible definitions of the modulus with respect to negative numbers. For some implementations, it's always true that 0 <= |a % b| < |b|; this is tantamount to always using the floor() function to find the integer quotient before computing the remainder. There are many languages with this interpretation, including Common Lisp and Python. You can get a negative value out of the % operator in these languages, but only if the divisor is negative; the sign of the dividend doesn't change the sign of the result.
In other languages, -|b| < |a % b| < |b|, and the sign of the result does depend on the sign of the dividend. This is equivalent to obtaining the integer quotient by rounding toward zero before taking the remainder; C is in this category (since C99; previous editions of the spec left it up to the implementation). So is Javascript, which is why -1 % 2 is not 1, but -1.
The first definition is often more useful, but easy to define in terms of the second:
const mod = (a,b) => (a % b + b) % b // mod(-1,2) is 1

Sum of Array of Odd numbers - JS

Given the triangle of consecutive odd numbers:
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
// Calculate the row sums of this triangle from the row index (starting at index 1) e.g.:
rowSumOddNumbers(1); // 1
rowSumOddNumbers(2); // 3 + 5 = 8
I tried to solve this using for loops:
function rowSumOddNumbers(n){
let result = [];
// generate the arrays of odd numbers
for(let i = 0; i < 30; i++){
// generate sub arrays by using another for loop
// and only pushing if the length is equal to current j
let sub = [];
for(let j = 1; j <= n; j++){
// if length === j (from 1 - n) keep pushing
if(sub[j - 1].length <= j){
// and if i is odd
if(i % 2 !== 0){
// push the i to sub (per length)
sub.push(i);
}
}
}
// push everything to the main array
result.push(sub);
}
// return sum of n
return result[n + 1].reduce(function(total, item){
return total += item;
});
}
My code above is not working. Basically I was planning to 1st generate an array of odd numbers less than 30. Next I need to create a sub array base on the length of iteration (j) that would from 1 - n (passed). Then finally push it to the main array. And then use reduce to get the sum of all the values in that index + 1 (since the index starts at 1).
Any idea what am I missing and how to make this work?
Most code problems involve some analysis first in order to spot patterns which you can then convert into code. Looking at the triangle, you'll see the sum of each row follows a pattern:
1: 1 === 1 ^ 3
2: 3 + 5 = 8 === 2 ^ 3
3: 7 + 9 + 11 = 27 === 3 ^ 3
... etc
So from the analysis above you can see that your code could probably be simplified slightly - I won't post an answer, but think about using Math.pow.
No need for any loops.
function rowSumOddNumbers(n) {
// how many numbers are there in the rows above n?
// sum of arithmetic sequence...
let numbers_before_n_count = (n - 1) * n / 2;
let first_number_in_nth_row = numbers_before_n_count * 2 + 1;
let last_number_in_nth_row = first_number_in_nth_row + 2 * (n - 1);
// sum of arithmetic sequence again...
return n * (first_number_in_nth_row + last_number_in_nth_row) / 2;
}

Using jQuery or JavaScript to find multiples and remainder of 2 numbers

Odd task, but I need to take a given integer, and first divide it by 5, whatever is left, divide by 3, and then show whatever remains.
For instance:
var fives = 19 / 5 = 3 remainder 4
var threes = 4 / 3 = 1 remainder 1
var ones = 1
var fives // 3
var threes // 1
var ones // 1
I can divide and see if it's a multiple, but I'm not sure how to do the conditional statement to pass it through the 2 operations and leave the remainders each time. The integers will always be positive numbers, no decimals.
To get the remainder of a division you have to devide, floor it and multiply it again. That result you have to substrate from your starting number.
Example:
Remainder of 19 / 5: 19 - floor(19 / 5)*5 = 19 - 15 = 4
in javascript code it's:
var remainderOf = (a,b)=>a-Math.floor(a / b)*b;
// calling it:
var result = remainderOf(19, 5); // 4
But the operation sequence: divide, floor, multiply substrate... is known as modulo operation. And you can use it in javascript with the %.sign:
var remainderOf = (a,b)=>a%b;
In your case it should be:
var startingNo = 19;
var remainderOfDevisionBy5 = startingNo % 5;
var remainderOfDevisionBy3 = remainderOfDevisionBy5 % 3;
alert(remainderOfDevisionBy3);
How about this:
var number = 19;
var fives = Math.floor(number / 5);
var threes = Math.floor(number % 5 / 3);
var ones = number % 5 % 3;

JavaScript - Project Euler #5 -- efficiency

This is for Project Euler, problem #5.
The task is to find the smallest number evenly divisible by numbers 1-20. My code seems to work on 1-18, but at 19 my browser starts timing out. This leads me to believe my code is just inefficient.
How can I mitigate this?
function divisible(a){
counter = 0;
result = 2;
while (counter < a){
for (var x = 0; x <= a; x ++){
if (result % x === 0){
counter ++;
}
}
if (counter != a){
counter = 0;
result ++;
}
}
return result;
}
divisible(20)
Basically, you want the least common multiple of 1,...,20.
I would implement lcm by using gcd, which can be implemented using the fast Euclidean algorithm.
function gcd(a, b) {
return b === 0 ? a : gcd(b, a%b); // Euclidean algorithm
}
function lcm(a, b) {
return a * b / gcd(a, b);
}
function divisible(a){
var result = 1;
for(var i=2; i<=a; ++i)
result = lcm(result, i);
return result;
}
divisible(20); // 232792560
Yup, inefficient. You would need to change the algorithm. The most efficient I can think of is to factorise all the numbers from 2 to 20 (with factors and counts: e.g. 18 is 3 * 3 * 2, or twice 3 and once 2, for final { 3: 2, 2: 1 }); then find the maximum for each factor, and multiply them together.
An abbreviated example: the least number that is divisible by 18 and 16:
18: { 3: 2, 2: 1 }
16: { 2: 4 }
maximums of factor repetitions: { 3: 2, 2: 4 }
result: 3^2 * 2^4 = 144
Factorising numbers from 2 to 20 is easy; if you don't know how to do it, there are many possible algorithms, you can see the Wikipedia article on integer factorisation for ideas.
another option with brute force and modulo rest-classification
this problem can be solved with a simple common modulo rest class characteristics.
look at the numbers from 1 to 20 and divide it into two groups and find some unique common attributes between them.
1 2 3 4 5 6 7 8 9 10
we are building a division with the same reminder members
1 divides all
2 divide 4,8 -->>8 important
3 divide 6,9 but 6 doesnt divide 9 evenly--> 6,9
5 divide 10-->> 10 important
that leaves us with 6,7,8,9,10 to check if there is any number from 1 that can divide this with rest 0.
the trick is if 2,4,8 divides a number let say 16 with the same reminder then we don't have to check if 2,4 divides 16, we check only 8.
11 12 13 14 15 16 17 18 19 20
here we can do the same from about with factors of the numbers from above and we will be left with
11 12 13 14 15 16 17 18 19 20
NB: we know that the last number that has to divide the number is 20,
so that means either the solution will be a number ending with 0 or is
one of the factors of 20, so we build factors of 20 and check if 11 12
13 14 15 16 17 18 19 can divide it then we are done.
int start = 20;
while (start % 11 != 0 || start % 12 != 0 | start % 13 != 0 || start % 14 != 0 ||
start % 15 != 0 || start % 16 != 0 || start % 17 != 0 || start % 18 != 0 || start % 19 != 0 )
{
start += 20;
}
console.log(start)
The same idea applies analogue to the first deduction I made to make the
problem seems smaller.
//smallest number divisible by all numbers from 1 to 10
int a = 10;
while (a % 6 != 0 || a % 7 != 0 | a % 8 != 0 || a % 9 != 0 )
{
a += 10;
}
console.log(a)
//smallest number divisible by all numbers from 1 to 5
int i = 5;
while (i % 3 != 0 || i % 4 != 0)
{
i += 5;
}
console.log(i)

Javascript random min max doesn't work

I am trying to make a simple program for a tabletop game that calculates damage. So I want to use random between two integers with a couple of percentage stuff to calculate damage.
The problem is random doesn't work for me. It doesn't matter what numbers I set as min or max, it always starts from 0 to the number before max.
<script>
function showDiv() {
var armor = document.getElementById('armortype').value;
var damage = document.getElementById('dmgtype').value;
var min = document.getElementById('mindmg').value;
var max = document.getElementById('maxdmg').value;
document.getElementById('result').style.display = "block";
for (var i=0;i<100;i++)
{
var dmg_done = Math.floor(Math.random()*max+min+1);
document.getElementById('test').innerHTML += " " + dmg_done;
}
}
</script>
So for min = 3, max = 6 I get the following 100 numbers:
3 1 2 2 0 2 2 1 2 2 3 3 4 0 1 1 2 2 5 2 3 5 3 3 3 4 0 0 5 2 3 0 4 0 2 1 0 5 4 1 0 5 5 4 2 1 2 4 5 1 5 1 0 4 3 5 2 1 4 3 1 1 5 1 4 2 1 0 3 3 3 4 3 4 5 4 2 0 2 4 5 0 3 1 2 5 0 1 5 1 2 2 1 4 0 0 0 1 4 2
So it doesn't matter that min is 3, it randomizes from 0 and there is not even a single 6 in the result.
Demo:
http://jsfiddle.net/zprr6/
You want to utilize it as such:
var dmg_done = Math.floor(Math.random() * (max - min + 1) + min);
The reason it starts at 0, is because the Math.random function produces a float from 0-1 (as many JS functions and features do).
So, by telling it to start at max - min + 1, ie 4, it avoids using the 0 as a starting value.
Try replacing Math.floor(Math.random()*max+min+1) with Math.floor(Math.random() * (max - min + 1) + min)
So why don't you try calculating random like this
function getRandom (min, max) {
return Math.random() * (max - min + 1) + min;
}
Edit: to add to the comment
var valOne = $("#input-1").val(),
valTwo = $("#input-2").val();
$("#button").click(function() {
$("#answer-input").val(getRandom(parseInt(valOne), parseInt(valTwo)));
);
Found the problem. both min and max were used as strings, not numbers. So I just parsed them as ints like this:
var min = parseInt(document.getElementById('mindmg').value);
var max = parseInt(document.getElementById('maxdmg').value);
and it works flawlessly now
Try
Math.floor((Math.random() * (max+1-min))+min);
max+1 - so that the maximum is include, and +min so that the min is respected
Test case
var max = 6;
var min = 3;
var result = "";
for(var i=0;i<100;i++)
{
result += Math.floor((Math.random()*(max+1-min))+min) +",";
}
console.log(result);
results (5 runs)
3,4,5,6,6,4,5,6,3,5,5,3,5,5,6,6,5,4,5,5,4,5,6,6,6,5,6,3,4,3,5,3,6,6,6,3,6,3,5,6,5,4,6,6,6,5,5,4,3,5,6,6,3,6,6,3,6,5,6,5,6,5,3,3,5,6,6,4,5,5,4,3,5,4,4,4,3,5,4,5,5,3,3,4,4,6,3,3,3,4,4,3,6,3,4,4,3,3,4,6,
6,5,4,3,6,4,4,6,4,4,5,5,3,4,6,4,4,3,4,6,6,5,3,6,4,5,4,6,5,4,4,3,5,6,4,3,5,5,3,5,4,3,6,4,3,3,3,4,6,5,6,3,5,5,6,6,6,5,5,6,5,6,5,4,5,4,4,5,3,6,3,3,6,5,6,3,5,3,6,3,5,6,3,4,5,4,3,5,3,5,3,5,3,5,3,5,3,5,5,6,
3,3,6,5,5,3,3,4,3,5,6,4,3,3,6,3,6,6,3,4,5,5,5,4,4,6,6,3,3,3,5,4,4,3,6,6,5,5,5,4,4,4,5,3,6,3,5,4,5,6,3,6,5,3,3,4,5,4,6,3,4,6,3,6,3,4,6,5,3,6,3,5,6,5,6,4,5,4,3,6,4,4,3,4,6,3,5,5,3,6,6,6,5,6,6,4,3,6,3,4,
4,4,3,6,4,6,4,3,5,4,5,3,4,5,6,6,6,3,4,4,4,4,4,4,5,6,4,4,6,6,5,5,5,3,6,3,5,4,6,5,5,4,5,4,5,4,3,3,5,4,6,5,5,4,4,6,6,6,3,4,6,6,3,6,5,5,4,6,6,4,3,4,6,3,5,6,4,3,5,6,3,4,3,6,6,6,6,3,3,4,4,4,6,6,4,3,6,5,4,3,
4,5,3,6,3,4,5,4,4,5,5,3,3,6,6,4,6,4,5,5,3,5,5,5,3,6,3,5,4,5,5,6,6,4,4,5,3,3,4,5,5,5,4,6,5,4,5,4,5,6,6,3,3,3,4,3,4,6,5,3,5,5,3,3,5,6,3,5,6,3,6,3,5,5,5,6,3,6,4,3,4,5,5,3,6,6,6,6,4,5,6,5,3,4,4,3,4,6,3,6,
On an additional note, getting the value of a textbox always returns a string, so the following (min and max) are both strings
var min = document.getElementById('mindmg').value;
var max = document.getElementById('maxdmg').value;
I would check that they are actually numbers, and cast them, before using them in the Math, something like
var min = +(document.getElementById('mindmg').value);
var max = +(document.getElementById('maxdmg').value);
putting the + at the front will casue a number cast IF IT CAN, if it can't, it will be NaN (Not a Number), so before you use, check that they are not NaN. Nan can easily be checked, as nothing equala Nan not even Nan so something like
if(min === min && max === max)
{
//... all good to use con..
}
will check that they are actually numbers as Nan will never equal NaN but 3 will always equal 3

Categories