13
\$\begingroup\$

You probably do know that the different reputation levels on Stack Exchange are formatted differently when seen from the questions page / a post. There're all the rep-formatting rules:

  • if a user has 1 to 999 (one to three digits) rep, it's left as-is.
  • if a user has 1000 to 9999 rep (four digits), it receives the comma as a separator: 9,999
  • if a user has 10000 to 99999 rep (five digits), it's shortened and rounded. I.e., 16741 rep is formatted as 16.7k, notice the dot separator unlike the comma for the lower rep (previous point).

    1. 16750 will already result 16.8k (since this seems to be fixed)

    2. 16941 results in 16.9k, 16950 rounds up to 17k, as well as does 17014, for example.

    3. 99941 rounds to 99.9k, 99950 rounds to 100k (this is something I actually hate with the rep-rounding on SE, because 100,000 is such a milestone, and 99950 is nowhere near).

  • If a user has 100000 to 999999 rep, it's rounded this way:

    1. 100100 rounds down to 100k, 100500 rounds up to 101k. The thing is, the rounding is done, but the decimal part is stripped (unlike the four-digits rep).

    2. 100450 rounds down to 100k, no step to round 450 to 500. Nor does 100499 - it's still 100k.

    3. 279843 rounds up to 280k, and 399999 rounds to 400k.

As input, you're given the raw reputation, and output it as formatted.

You can consider that input won't receive any invalid numbers / non-numbers, or numbers with leading zeros, i.e. 0001234.

Because Jon Skeet doesn't seem to be reaching 1,000,000 soon, your code must be as short as possible you don't need to handle the rep greater than one million (i.e. no special cases for 999500 and above).

\$\endgroup\$
  • 7
    \$\begingroup\$ "Because Jon Skeet doesn't seem to be reaching 1,000,000 soon" [citation needed] \$\endgroup\$ – Milo Brandt Jan 12 '16 at 19:20
  • \$\begingroup\$ @Milo Easy - he earned 93k for 2015. He has 163,685 left until 1,000,000, so this way it will take him more than 1,5 years (almost 2, I'd say). With this, you should also take into account that his yearly rep is decreasing with each year, since 2011. 2011: 134.7k, 2012: 131.8k, 2013: 116.8k, 2014: 104.3k, 2015: 94.3k. \$\endgroup\$ – nicael Jan 12 '16 at 20:08
  • \$\begingroup\$ A long explanation, but all in all, it's just the way rounding is usally done \$\endgroup\$ – edc65 Jan 12 '16 at 21:04
  • \$\begingroup\$ @Edc See this answer by Peter Taylor. \$\endgroup\$ – nicael Jan 12 '16 at 21:22
  • 2
    \$\begingroup\$ I think the explanation could be shortened by saying "If the rep is in the range 10000 to 994999 (both inclusive), it is rounded to 3 significant figures using the half-up rule, divided by 1000, and displayed with . for a decimal point and with a suffixed k; subject to the caveat that if the third significant figure is 0 and is to the right of the decimal point then the value is displayed only to 2 significant figures." The specific cutoffs could then be moved to a single list of test cases at the end of the post, which is more convenient for copy-pasting into a test framework. \$\endgroup\$ – Peter Taylor Jan 12 '16 at 22:05
4
\$\begingroup\$

Japt, 50 48 bytes

First attempt; there may be a better method.

U<A³?U:U<L²?Us i1', :(U<1e5?Ue2n)r /A:Ue3n)r)+'k

Try it online!

How it works

          // Implicit: U = input integer, A = 10, L = 100
U<A³?U    // If U is less than A³ (10³ = 1000), return U.
:U<L²?    // Else, if U is less than L² (100² = 10000), return:
Us i1',   //  U.toString, with a comma inserted at position 1.
:(        // Else, return:
U<1e5?    //  If U is less than 1e5:
Ue2n)     //   U * (10 to the power of -2), 
r /A      //   rounded and divided by 10.
:Ue3n)r)  //  Else: U * (10 to the power of -3), rounded.
+'k       //  Either way, add a "k" to the end.
          // Implicit: output last expression
\$\endgroup\$
7
\$\begingroup\$

JavaScript (ES6), 76 68 bytes

x=>x<1e4?x.toLocaleString():(x<1e5?(x/1e2+.5|0)/10:(x/1e3+.5|0))+"k"

Another first attempt. Thank goodness for that handy .toLocaleString(), the shortest alternative I could find is 21 bytes longer...

This separates thousands by either , or ., depending on what country you live in. For five two bytes more, you can make it always use a comma:

x=>x<1e4?x.toLocaleString`en`:(x<1e5?(x/1e2+.5|0)/10:(x/1e3+.5|0))+"k"
\$\endgroup\$
  • \$\begingroup\$ Your locale works fine for you, but here in Italy I get 1.234 (dot instead of comma) \$\endgroup\$ – edc65 Jan 12 '16 at 20:48
  • \$\begingroup\$ @edc65 Now that's a problem I never thought I would run into with a code golf. Does it work now? \$\endgroup\$ – ETHproductions Jan 12 '16 at 20:51
  • \$\begingroup\$ Perfect. Really I didn't think that was doable. And I tried just 'en' and it seems to work too \$\endgroup\$ – edc65 Jan 12 '16 at 21:01
  • \$\begingroup\$ I don't think you need to adjust for locale, because it doesn't need to be portable. \$\endgroup\$ – geokavel Jan 12 '16 at 21:13
  • 1
    \$\begingroup\$ Basically, if it works on your computer, I think it's good enough. \$\endgroup\$ – geokavel Jan 12 '16 at 21:16
3
\$\begingroup\$

JavaScript (ES6), 71

Beating @ETHProductions while he does not see my hint. He saw it.

x=>x<1e3?x:x<1e4?(x+='')[0]+','+x.slice(1):(x/1e3).toFixed(x<99950)+'k'

Test

f=x=>x<1e3?x:x<1e4?(x+='')[0]+','+x.slice(1):(x/1e3).toFixed(x<99950)+'k'

function test() { n=+I.value, O.textContent = n + ' -> ' + f(n) }

test()
<input id=I type=number value=19557 oninput=test()>
<pre id=O></pre>

Test

\$\endgroup\$
  • 1
    \$\begingroup\$ Perhaps you should update your "beating ETHproductions" line...? \$\endgroup\$ – Conor O'Brien Jan 12 '16 at 22:30
  • \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ done. \$\endgroup\$ – edc65 Jan 12 '16 at 22:43
2
\$\begingroup\$

ES6, 68 62 bytes

x=>x<1e4?`${x}`.split(/(?=...)/)+"":x.toPrecision(3)/1e3+"k"

Edit: Saved 6 bytes when I realised that ["1", "001"] stringifies to "1,001".

Edit: Saved 2 bytes to fix @Mwr247's comment!

\$\endgroup\$
  • \$\begingroup\$ 16950 gives 16.9k instead of 17k \$\endgroup\$ – Mwr247 Jan 13 '16 at 6:02
  • \$\begingroup\$ @Mwr247 Thanks, the fix saves me two more bytes! \$\endgroup\$ – Neil Jan 13 '16 at 8:37
1
\$\begingroup\$

Python 2.7, 58 bytes

lambda x:['%.3g'%((x+.5)/1e3)+'k','{:,}'.format(x)][x<1e4]

I had to use (x+.5) to deal with the 16950->17k case..

\$\endgroup\$

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.