22
\$\begingroup\$

Imagine this short function to clamp a number between 0 and 255:

c = n => n > 0 ? n < 255 ? n : 255 : 0

Is this the shortest possible version of a clamp function with JavaScript (without ES.Next features)?

P.S: Not sure if it's relevant but, the 0 and 255 are not random, the idea is to clamp a number as an 8-bit unsigned integer.

\$\endgroup\$
  • 2
    \$\begingroup\$ Hi and welcome to PPCG! Just to be clear, any answer you receive here will not necessarily be a good idea to use in anything except for code golfing. Aside from that, if you care about what version / environment it has to work in you might want to specify it. \$\endgroup\$ – FryAmTheEggman Mar 5 at 23:09
  • 1
    \$\begingroup\$ Oh, I'm well aware. I've updated the question a bit. Thank you :) \$\endgroup\$ – Ricardo Amaral Mar 5 at 23:12
  • 2
    \$\begingroup\$ I don't know JS, but one way to clamp is to sort [0,n,255] and take the middle element -- might that be shorter? \$\endgroup\$ – xnor Mar 5 at 23:26
  • 1
    \$\begingroup\$ @xnor Unfortunately, the JS sort() method uses a lexicographical comparison by default, so that would require an explicit callback. (Something like that.) \$\endgroup\$ – Arnauld Mar 5 at 23:30
  • 5
    \$\begingroup\$ @Arnauld Wow, that's pretty silly. But it looks like it would be longer even if the sort was numerical. \$\endgroup\$ – xnor Mar 5 at 23:34
23
\$\begingroup\$

20 bytes

For reference, this is the original version without whitespace and without naming the function:

n=>n>0?n<255?n:255:0

Try it online!


19 bytes

We can save a byte by inverting the logic of the ternary tests and using n>>8 to test whether \$n\$ is greater than \$255\$. Because of the bitwise operation, this will however fail for \$n\ge 2^{32}\$.

n=>n<0?0:n>>8?255:n

Try it online!


19 bytes

This one returns \$false\$ instead of \$0\$ but works for \$n\ge 2^{32}\$.

n=>n>255?255:n>0&&n

Try it online!


18 bytes

By combining both versions above, we end up with a function that works for \$256-2^{32}\le n<2^{32}\$ and returns \$false\$ for \$n<0\$.

n=>n>>8?n>0&&255:n

Try it online!

Commented

n =>          // n = input number
  n >> 8 ?    // if n is greater than 255 or n is negative:
    n > 0 &&  //   return false if n is negative
    255       //   or 255 otherwise
  :           // else:
    n         //   return n unchanged

(This is a fixed revision of the code proposed by @ValueInk in the comments.)


17 bytes

We can go a step further by limiting the valid input range to \$-2^{24}< n\le 2^{24}\$:

n=>n>>8?-n>>>24:n

Try it online!

Commented

n =>          // n = input number
  n >> 8 ?    // if n is greater than 255 or n is negative:
    -n >>> 24 //   non-arithmetic right-shift of -n by 24 positions
  :           // else:
    n         //   return n unchanged
\$\endgroup\$
  • \$\begingroup\$ Why stop there? If you're extremely liberal with what counts as a 0 (as JavaScript tends to do) you can always go for n=>n>>8?255:n>0&&n for 18 bytes, since false can be coerced to 0 and this will make all negative numbers evaluate to false \$\endgroup\$ – Value Ink Mar 5 at 23:39
  • 1
    \$\begingroup\$ @ValueInk If you don't test \$n<0\$ beforhand, n>>8 will be truthy for any negative input. \$\endgroup\$ – Arnauld Mar 5 at 23:41
  • \$\begingroup\$ Very nice, thank you so much! \$\endgroup\$ – Ricardo Amaral Mar 6 at 10:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.