├── index.js ├── license ├── package.json ├── readme.md └── table.png /index.js: -------------------------------------------------------------------------------- 1 | module.exports = function wrap(m, n) { 2 | return n >= 0 ? n % m : (n % m + m) % m 3 | } 4 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Brandon Semilla 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wrap-around", 3 | "version": "0.1.0", 4 | "description": "Wrap numbers within a certain range", 5 | "keywords": ["wrap", "around", "range"], 6 | "files": ["index.js"], 7 | "license": "MIT", 8 | "author": "Brandon Semilla (https://github.com/semibran)", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/semibran/wrap-around.git" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # wrap-around 2 | ![table of values](table.png) 3 | 4 | Restricts a number `n` to the interval `0 <= n < m` by "wrapping it around" within said range. 5 | ```js 6 | const wrap = require('wrap-around') 7 | var result = {} 8 | for (var m = 3, n = -3; n < 9; n++) { 9 | result[n] = wrap(m, n) 10 | } 11 | ``` 12 | 13 | Some possible uses of this function include: 14 | - restricting an index to valid array indices 15 | ```js 16 | index = wrap(array.length, index) 17 | ``` 18 | - selecting items from the end of a list (Python-style!) 19 | ```js 20 | > var array = ['foo', 'bar', 'baz'] 21 | > array[wrap(array.length, -1)] 22 | 'baz' 23 | ``` 24 | - wrapping the player around the screen in a game of Pac-Man, Snake, etc. 25 | ```js 26 | hero.position = [wrap(width, x), wrap(height, y)] 27 | ``` 28 | 29 | ## usage 30 | [![NPM](https://nodei.co/npm/wrap-around.png?mini)](https://www.npmjs.com/package/wrap-around) 31 | 32 | ### Why not just use `n % m`? 33 | While the modulo operator wraps positive values with ease (it's actually used internally by the `wrap` function), it takes a bit more setup to handle negative values correctly. Consider the following example, in which `%` fails to provide the desired result: 34 | ```js 35 | > -1 % 3 36 | -1 37 | 38 | > wrap(3, -1) 39 | 2 40 | ``` 41 | 42 | ### What about loops? 43 | Using loops for this kind of thing is a handy way of demonstrating what exactly this function does - `wrap(m, n)` produces the same result as two loops forcing a number between the desired range. 44 | ```js 45 | while (n < 0) n += m 46 | while (n >= m) n -= m 47 | ``` 48 | 49 | Unfortunately, they're also 300x slower. :grimacing: 50 | ```md 51 | # wrap 100000 times 52 | ok ~4.7 ms (0 s + 4696167 ns) 53 | 54 | # loop 100000 times 55 | ok ~1.36 s (1 s + 359910028 ns) 56 | ``` 57 | 58 | So at the end of the day, you're better off avoid loops for "wrapping" numbers in production code. Use the modulo `%` operator for positive numbers or `wrap-around` if you plan on handling negative numbers. 59 | 60 | ## license 61 | [MIT](https://opensource.org/licenses/MIT) © [Brandon Semilla](https://git.io/semibran) 62 | -------------------------------------------------------------------------------- /table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/semibran/wrap-around/607c63ab8fec67a365133b0c67b8b32ee9e01649/table.png --------------------------------------------------------------------------------