positive/negative Modulo to get items in range - javascript
I looked at https://math.stackexchange.com/questions/519845/modulo-of-a-negative-number and Modulo operation with negative numbers but I still wonder how to use a negative modulo value to get items in a range.
Here is a simplified use case before my question bellow, I have a slideshow with 3 slides (slidesCount = 3):
slide indexes: 0 1 2
Now I would like to access the right slide from these numbers:
-2 -1 0 1 2 3 4
should match slide:
1 2 0 1 2 0 1
So with index % slidesCount I cover the cases:
0 1 2 3 4
but not negative values. -1 % 3 returns -1 so is slidesCount + index % slidesCount the correct expression if index is negative?
First of, is there a simpler/smarter way to write:
index = index % slidesCount + (index < 0 ? slidesCount : 0)
Now my question is for a slideshow of 3 visible items per slide,
where the last slide may have only one item (index 9 bellow) so from these numbers:
-3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
I want to match slides:
9 0 3 6 9 0
I hope the following diagram makes sense! Please help me get the correct equation out of it with minimum ifs:
-3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
|________| |______________________________________________|
|| || ||
|| Math.floor( i / visibleSlides )
Math.ceil(i / visibleSlides) || ||
|| || ||
\/ \/ \/
-1 0 1 2 3 4
|___| |_______________________| |___|
|| || ||
slidesCnt + i % visibleSlides i % visibleSlides || ??
|| || ||
\/ \/ \/
3 0 1 2 3 0
|| i * visibleSlides
\/
9 0 3 6 9 0
in the end, this is how I solved the problem:
// Prevents out of range.
// e.g. -1, -2, 12, 13
let newIndex = (index + slidesCount) % slidesCount
// Calculates how many items are missing on last slide.
// e.g. if 10 slides with 3 visible slides, 2 missing slides on last slide.
let lastSlideItems = slidesCount % visibleSlides || visibleSlides
let missingItems = visibleSlides - lastSlideItems
// If index is negative adjust by adding the missing slides.
newIndex += index < 0 ? missingItems : 0
// Always get the first item of the series of visible items.
// e.g. if index is 8 and 3 visible slides, newIndex will be 6.
newIndex = Math.floor(newIndex / visibleSlides) * visibleSlides
Related
Why and 1 ( &1) bitwise operation always return 0 or 1
I just started learning about bit wise operation and want to ask why and 1 ( &1) bitwise operation always return 0 or 1 .
0 & 0 === 0 0 & 1 === 0 1 & 0 === 0 1 & 1 === 1 therefore any number & 1 will always be either 0 or 1 in binary ... any number xxxxxxxxxxxxx0 or xxxxxxxxxxxxx1 where x can be 0 or 1 1 in binary is 00000000000001 so xxxxxxxxxxxxx1 & 00000000000001 == 00000000000001 xxxxxxxxxxxxx0 & 00000000000001 == 00000000000000
When you perform a & 1 it will always return 0 or 1 depending upon the the last binary digit of a. Rules: 0 & 0 = 0 0 & 1 = 0 1 & 1 = 1 For example: a = 5 //5 = 0101 b = a & 1 = 1 //(0101 & 0001) a = 6 //6 = 0110 b = a & 1 = 0 //(0110 & 0001)
This is a bitwise operation. Suppose you take 2 & 1. That would be 10 and 01 in binary. Bitwise AND will give 00. BitWise operations with 1 will give 1 or 0 always because 1 has only a significant unit's place in binary. So it cannot return any value other than a 0 or a 1.
This can be used to check if an integer is odd or even, returning a 0 for False and 1 for True. is_odd: 1 for odd , 0 for even odd = number & 1 is_even: 1 for even , 0 for odd even = number & 1 ^ 1
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)
What's computed by this code?
An interview question, What's computed by this code? (function(n){return (n && n*arguments.callee(n-1)) || 1;})(10); a) 10! b) Nothing, it's an infinite loop. c) 10 to the power of 10 d) 10!/10 e) The 10th Fibonacci number.
a) 10! meaning the factorial of 10 (mathematical expression for 10 x 9 x 8 x ... x 1) You can have a guess of the result with the successive calls: (function(n){return (n && n*arguments.callee(n-1)) || 1;})(1); 1 (function(n){return (n && n*arguments.callee(n-1)) || 1;})(2); 2 (function(n){return (n && n*arguments.callee(n-1)) || 1;})(3); 6 (function(n){return (n && n*arguments.callee(n-1)) || 1;})(4); 24 (function(n){return (n && n*arguments.callee(n-1)) || 1;})(5); 120 (function(n){return (n && n*arguments.callee(n-1)) || 1;})(10); 3628800 Then if you analyse the code : the function returns 1 if the input is 0. if the input is greater than 0 it returns the input multiplied the function called with n-1. More precisely, (n && n*arguments.callee(n-1)) is a boolean operation and it's return value is the last operand evaluated to true, which is the value of n*arguments.callee(n-1) each time n>0, and 1 instead (thanks to ||1). arguments.callee is a recursive call in javascript.
A simple way to analyze recursive calls is to write down a stack of all calls and then evaluate in popping order. [ 10 * (recurse with 10 - 1), 9 * (recurse with 9 - 1), 8 * (recurse with 8 - 1), 7 * (recurse with 7 - 1), 6 * (recurse with 6 - 1), 5 * (recurse with 5 - 1), 4 * (recurse with 4 - 1), 3 * (recurse with 3 - 1), 2 * (recurse with 2 - 1), 1 * (recurse with 1 - 1), 1 (recursion stops because 0 is falsey, therefore 1 will be returned) ] Then we take the stack and evaluate our way up: [ 10 * 362880 = 3628800, ..., 6 * 120 = 720, 5 * 24 = 120, 4 * 6 = 24, 3 * 2 = 6, 2 * 1 = 2, 1 * 1 = 1 1 = 1 <-- start here then work up ] From this, we can clearly see that the algorithm is a) 10!.
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
Understanding the modulus operator
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];