7 ms·
[min, num, max].sort()[1]
by tobr 6y ago
[min, num, max].sort()[1]
- tosh 6y agosort() on JavaScript arrays sorts alphabetically (unless you pass a compareFunction) https://stackoverflow.com/questions/21019902/why-cant-javascript-sort-5-10-1 https://stackoverflow.com/questions/21019902/why-cant-javasc... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- tobr 6y agoVery good point. I thought of it more as pseudocode.
- tosh 6y agoimho a very elegant solution and probably works in most languages, I was surprised by JavaScript's behaviour myself
- 1-more 6y agoFor a real fun headscratcher consider [ '9', '10', '11', '12', '13' ].map(parseInt)
- yboris 6y agoThank you for this exercise! I figured it out! [ROT 13] spoiler: cnefrVag frpbaq nethzrag vf onfr, znc frpbaq nethzrag vf vaqrk va neenl. 10 vf gur frpbaq nethzrag, vaqrk 1. cnefrVag(10, 1) unf vyyrtny onfr [0] https://rot13.com/ https://rot13.com/
- tgb 6y agoWait, really? I just had to double-check my one JS project for bugs and either I used to know this gotcha or I got lucky. My sort()-ing needed to handle NaNs carefully so I was already using custom comparators.
- yesbabyyes 6y agoGood point, for those who need to implement a slick compareFunction for numbers, Math.sign is great: [min, num, max].sort((a, b) => Math.sign(a - b))[1] An entirely different alternative is poor man's match: switch (true) { case num > max: return max; case num < min: return min; default: return num; }
- recursive 6y agoWhy sign though? I always write my sorts like this. .sort((a, b) => a - b)
- TimTheTinker 6y ago"lexicographically" is a better descriptor than "alphabetically", since it's sorting by UTF-8 code point value.
- edflsafoiewq 6y agoIt sorts by UTF-16 code unit.
- TimTheTinker 6y agoOf course, my bad.
- unoti 6y ago[min, num, max].sort()[1] I really love this! I’m not sure whether to laugh, cry, or applaud, but I love how it makes me feel all those emotions at the same time.
- vortico 6y agoThis is also nice because it gracefully handles the case where `max < min`.
- rags2riches 6y agoIt's not always graceful to say that 1 is both less than 0 and greater than 2.
- vortico 6y agoNot sure what you mean. If I want to clamp 1 between 2 and 0, the most reasonable answer is 1, which is correctly returned by this code.
- resu_nimda 6y agoHe's saying that, if you have explicitly defined a max and min such that max < min, it is not graceful for the computer to produce a result as though those values were swapped. In other words, garbage in should produce garbage out. The array implementation sidesteps this by not semantically defining a max and min, instead sorting three arbitrary numbers.
- vortico 6y agoWhy do you prefer to leave undefined behavior?
- resu_nimda 6y agoI'm not sure what you mean. The behavior of the max() and min() functions is perfectly well defined. The terms "maximum" and "minimum" are well defined. If I were using those terms I would likely consider the case where max < min to be an error, or have some other meaning, like an empty range. If I wanted it to automatically flip the values to ensure a sensible range is defined, I would probably use "a" and "b" or "endpoint1" and "endpoint2" or something, because "max" has now become "max or min," which is not the same.
- throwawaw 6y agoI love this one.
- gridlockd 6y agoThis is why computers are slow.
- secondcoming 6y agoNo. Just things written by web devs. (Shots fired)
- saagarjha 6y agoI was curious how slow this would be, and here is what JavaScriptCore made of this code: function clamp(n, min, max) { return [min, n, max].sort((a, b) => a - b)[1]; } for (var i = 0; i < 10000000; i++) { clamp(Math.random() | 0, Math.random() | 0, Math.random() | 0); } However, I was pretty disappointed when it seemed to be calling sort each time :( Perhaps I profiled it incorrectly? jsc's profiling data shows that it never hit FTL and nothing ever got inlined. The bytecode for DFG and Baseline is identical: Compilation clamp#CChm91-1-Baseline: arg0: predicting OtherObj arg1: predicting BoolInt32 arg2: predicting BoolInt32 arg3: predicting BoolInt32 [ 0] enter [ 1] get_scope loc4 [ 3] mov loc5, loc4 [ 6] check_traps [ 7] mov loc11, arg2 [ 10] mov loc12, arg1 [ 13] mov loc13, arg3 [ 16] new_array loc10, loc11, 3, 3 [ 22] get_by_id loc7, loc10, 0 [ 27] new_func_exp loc9, loc4, 0 [ 31] call loc7, loc7, 2, 16 [ 37] get_by_val loc6, loc7, Int32: 1(const0) [ 42] ret loc6 Compilation clamp#CChm91-2-DFG: arg0: predicting OtherObj arg1: predicting BoolInt32 arg2: predicting BoolInt32 arg3: predicting BoolInt32 [ 0] enter [ 1] get_scope loc4 [ 3] mov loc5, loc4 [ 6] check_traps [ 7] mov loc11, arg2 [ 10] mov loc12, arg1 [ 13] mov loc13, arg3 [ 16] new_array loc10, loc11, 3, 3 [ 22] get_by_id loc7, loc10, 0 [ 27] new_func_exp loc9, loc4, 0 [ 31] call loc7, loc7, 2, 16 [ 37] get_by_val loc6, loc7, Int32: 1(const0) [ 42] ret loc6
- agumonkey 6y agonever thought of clamp as precompiled sort
- seanwilson 6y agoIt's cute but if you used this in an innerloop (like a game, simulation or graphics code where 'clamp' is used often), it'll generate a ton of garbage as well as potential slowdown for no good reason.
- tobr 6y agoThis should be completely obvious, but largely irrelevant to the topic at hand. The linked tweet talks about how difficult it is to remember the order of the terms when you implement clamp a certain way; I just wanted to point out that with a different solution, the order surprisingly doesn’t matter at all.
- seanwilson 6y agoI don't think it's obvious though - many people have never optimised for garbage collection so I thought it was worth pointing out. I still found your approach interesting and it's rare there's a perfect approach so don't take it to heart.