4 ms·
Show HN: Aimless.js – the missing js randomness library
- nonethewiser 3y agoI was using faker in our codebase at work to generate some random data. I wanted to pick one of a few status codes. I was surprised to see that faker.random was deprecated and the random sample was moved into different datatypes. But the array datatype was deprecated so now there is no random sample from array in faker, seemingly. They say "Use your own function to build complex arrays." Isn't that what faker is all about? Maybe there is good reason for this. I'm not real familiar with this space. It's not so hard to implement something yourself. But I suspect the description of "missing js randomness library" may have some merit.
- damienwebdev 3y agoI'm one of the maintainers of Faker, so hopefully I can help remedy any situation we inadvertently created. https://fakerjs.dev/api/helpers.html#arrayelement https://fakerjs.dev/api/helpers.html#arrayelement I believe is what you're looking for. The issue, as I recall, is that all of Faker is random, so what does it mean to have a `random` module namespace. We moved it out of a hope for improved clarity.
- nonethewiser 3y agoOh shit, youre right. Thanks for that. I think I saw that method but didnt realize it is implicitly random (like an idiot)
- jasonjmcghee 3y agoI think seeded randomness is wildly underused. It's much more often the case I was deterministic randomness rather than based on my system clock. It's nice to see aimless.js support it. Crazy to me that `Math.random` doesn't accept a seed as an optional param.
- quickthrower2 3y agoYes, the obvious case is machine learning, so that you can make changes and run your program again, and it uses the same batches as so forth. Another case are unit tests with random-generated cases. At a minimum you want to know the seed of the last run and have that reported. On CI system you would want it to be deterministic. Where you want there not to be a seed is in crypto, or possibly a game like poker or even tetris.
- explaininjs 3y agoI’d argue that in poker you must use seeded randomness — but everyone has to contribute to the random “pool”. This is the only way I know of to have effectively random values with zero trust.
- gmac 3y agoAgreed. That’s why I did this (although the Mersenne Twister is probably a rather outdated way to go): https://github.com/jawj/mtwist https://github.com/jawj/mtwist
- sebstefan 3y agoI was really surprised when I discovered JS didn't have seeded randomness I had to make one myself and I never thought it'd be something I'd ever need to do
- paddw 3y agoCool project! Might be nice to include a random permutation method.
- tantalor 3y agointSequence(min, max, engine) Returns an array with all integers between min and max in random order.
- shhsshs 3y agoconst randomPermutation = arr => intSequence(0, arr.length - 1).map(i => arr[i]) console.log(randomPermutation(['a', 'b', 'c'])
- chriscavs 3y agoI believe sequence will accomplish what you're looking for here const randomSeq = sequence([1,2,3]) // could return [3,1,2], [2,3,1], etc.
- re 3y ago"The missing JS randomness library" is a provocative subtitle. :) Have you compared your project to Random.js? https://www.npmjs.com/package/random-js https://www.npmjs.com/package/random-js There's also Rando.js but that project also appears to use a biased algorithm.
- EarthLaunch 3y agoThanks for mentioning others. The main thing I love about OP's library is the simple, clear naming. A lot of complexity has been solved for me. Looking at random-js, the barrier to entry is higher. I've looked at randomness libraries and that's the feeling they gave me: That I would need to learn how randomness works, rather than just calling a function for what I want; a random int, a weighted random. Cmd+F "weighted" doesn't find anything on both of those projects' readmes. There's a tradeoff for simplicity, but in many cases I'll take it. This is the iPhone of randomness and that's what I needed to feel comfortable using it rather than rolling my own.
- quickthrower2 3y agoI was thinking "if there is one feature JS doesn't have, it is a missing library"
- chriscavs 3y agoThanks for the comment! Yes it is a bit of a provocative title hahaha. i don't believe my library can be compared to random-js, since the goals of each are very different. random-js wants to provide the "engine" that replaces Math.random. I want to provide a library of utilities that are engine-agnostic. you can pull in random-js and use their engines to power aimless.js, as an example.
- EarthLaunch 3y agoA while back there was a post about a randomness bug in Asheron's Call, the "Wi flag" [0]. I posted a comment there and was offered helpful answers about doing weighted randomness [1]. This library seems to solve that problem and half a dozen others! Like: Reading code with functions named for their purpose is better than a string of arithmetic operations in most cases. Thank you for sharing this! Will use in my game! [2] const weightedDiceRoll = weighted( [1,2,3,4,5,6], [1,1,1,1,1,10] ) // will return 6 much more often than the other options 0: https://news.ycombinator.com/item?id=34742505 https://news.ycombinator.com/item?id=34742505 1: https://news.ycombinator.com/item?id=34742985 https://news.ycombinator.com/item?id=34742985 2: https://github.com/Suncapped/babs https://github.com/Suncapped/babs
- chriscavs 3y agothanks for the comment, i'm happy you like it!
- vore 3y agoThis is not a uniform distribution: const randIntRange = (i, j, engine = defaultEngine) => { const min = Math.ceil(i) const max = Math.floor(j) return Math.floor(engine() * (max - min + 1)) + min } If you assume engine() outputs, say, 64 bits of entropy, any number range that is not an even factor of 2^64 will exhibit intermittent bias where the numbers are rounded. The only correct way to do this is to do rejection sampling: generate an integer x with log2(max - min) bits and if x >= max - min retry until you do: function randBelow(n) { const nbits = Math.ceil(Math.log2(n)); while (true) { const x = getRandBits(nbits); if (x < n) { return x; } } } function randIntHalfOpenRange(min, max) { return min + randBelow(max - min); } function randIntRange(min, max) { return randIntHalfOpenRange(min, max + 1); } The primitive you want for building distributions on is not to generate a floating point number between 0.0 and 1.0, but to generate an integer of at most x bits.
- vore 3y agoAdditionally, the shuffle function (sequence.js) has quadratic complexity due to repeated copying of the input array. You could get a vast performance improvement by copying the input array and running the standard Fisher–Yates shuffle over it: it will both run in linear time and will not thrash cache as much.
- chriscavs 3y agothanks for bringing this to my attention, I will be sure to check this out
- chriscavs 3y agoThank you for the comment! I am aware of this issue, and am working to address in v1.1.0. The context you provide here is very helpful for me. I've opened an issue on github for this: https://github.com/ChrisCavs/aimless.js/issues/2 https://github.com/ChrisCavs/aimless.js/issues/2
- winrid 3y agoWhether or not my code will run is all the randomness I need.
- nailer 3y ago> The default engine uses crypto.getrandomvalues() when available, with a fallback of Math.random(). Thumbs up. Carry on.