Visualize a large int

19

3

Convert a large int (e. g. 1234567890) into a string containing the usual decimal prefixes k, M, G, T, etc. for kilo, mega, giga, tera, etc. The result shall be groups of three digits, interspersed by the prefixes (e. g. 1G234M567k890), so that it is easy to glance the order of magnitude of the number without counting the digits.

It shall work for numbers of all digit counts up to 15. Only non-negative numbers are allowed as input.

More test cases:

0 → 0
123 → 123
1234 → 1k234
1000 → 1k000
1000000000 → 1G000M000k000

Alfe

Posted 2019-10-11T10:31:12.383

Reputation: 307

@Arnauld Look at my example result. It contains several prefixes, but if the number is small, it could also contain one or even none (for numbers below 100000 and below 1000). – Alfe – 2019-10-11T10:45:48.503

Can I take the input as a string, since my language supports integers only up to 2^32? – Galen Ivanov – 2019-10-11T10:53:45.140

1you don't even need peta, because 15 digits is only up to tera. 123T 456G 789M 012k 345 – Dorian – 2019-10-11T10:54:03.123

2@GalenIvanov If the language cannot handle integers up to 15 digits, the input can be a string representation of the number in decimal format. – Alfe – 2019-10-11T11:00:50.390

4So a block of 0s should still display? E.g., 1000234 -> 1M000k234 – Veskah – 2019-10-11T14:29:54.570

4can we get more than 1 test case? – aaaaa says reinstate Monica – 2019-10-11T19:07:08.617

The number shall be displayed completely, just interspersed with the correct prefixes to ease orientation. I will add more test cases. – Alfe – 2019-10-11T23:19:58.097

4"easy to glance the order of magnitude". I personally find 1G000M000k000 much harder to parse than 1 000 000 000 – Eric Duminil – 2019-10-13T19:16:27.940

@EricDuminil I agree. That's why in practice I would use ᵏᴹᴳᵀ as markers instead. I find a 1ᵀ002ᴳ289ᴹ732ᵏ929 way better to read than the same with ASCII letters. And if the colour for the letters also is set to something unobtrusive (grey, for instance), this effect is even improved. This fancy Unicode thing brought me some criticism in my own answer, though (Python3 below). – Alfe – 2019-10-14T08:39:50.133

Answers

9

JavaScript (ES6), 64 bytes

Takes input as a string.

f=(n,i=0,[d,t]=n.split(/(...)$/))=>t?f(d,i+1)+['kMGT'[d&&i]]+t:d

Try it online!

How?

The regular expression /(...)/$ matches the last three digits of the integer, or nothing at all if there are less than 3 digits remaining.

Because there's a capturing group, these digits -- if present -- are included in the output of the .split() method.

Examples:

'123456789'.split(/(...)$/) // --> [ '123456', '789' '' ]
'123'.split(/(...)$/))      // --> [ '', '123' ]
'12'.split(/(...)$/))       // --> [ '12' ]
''.split(/(...)$/))         // --> [ '' ]

Commented

f = (                 // f is a recursive function taking:
  n,                  //   n = input
  i = 0,              //   i = index of next prefix
  [d, t] =            //   d = either the leading digits without the last 3 ones,
                      //       or all remaining digits if there are less than 3
    n.split(/(...)$/) //   t = last three digits (or undefined)
) =>                  //
  t ?                 // if t is defined:
    f(d, i + 1) +     //   append the result of a recursive call with d and i + 1
    ['kMGT'[d && i]]  //   append the prefix if d is defined, or an empty string otherwise
    + t               //   append the last 3 digits
  :                   // else:
    d                 //   stop recursion and return the remaining digits

Arnauld

Posted 2019-10-11T10:31:12.383

Reputation: 111 334

56 bytes: f=(n,i=0)=>n.replace(/.+(?=...)/g,d=>f(d,i+1)+'kMGT'[i]) – tsh – 2019-10-15T08:19:12.430

@tsh I think this is different enough to be posted as a new answer. – Arnauld – 2019-10-15T08:42:54.777

4

05AB1E, 15 14 bytes

R3ô"kMGTP"øSR¦

Try it online!

Thanks to Kevin Cruijssen for -1 byte

R       reverse input
3ô      split it into groups of 3 digits
"kMGTP" push the prefixes
ø       zip the groups of numbers with them
S       split to a list of characters
R       reverse again
¦       drop the first element
        implicitly print

Dorian

Posted 2019-10-11T10:31:12.383

Reputation: 1 521

2You can change the JJ to S (which implicitly flattens) to output as a list of characters instead of a string, which is allowed when a string output is asked by default. (You could add a J in the footer if you want to pretty-print it.) – Kevin Cruijssen – 2019-10-11T11:03:49.970

As you noticed above, P is not required. – Arnauld – 2019-10-11T11:25:52.147

1I know, but I can't remove it, because the code would cut off the number after 12 digits. It builds a list that looks like this: ["P1", "T234", "G567", "M890", "k123"]. Then it deletes the first letter. When I remove the "P", it can't fill the "P1" string. – Dorian – 2019-10-11T11:41:14.840

4

Python 2, 57 bytes

f=lambda s,p="":s and f(s[:-3],p[1:]+"kMGT")+s[-3:]+p[:1]

Try it online!

Takes input as a string. If the output may have a trailing space, we can avoid some workarounds and save 3 bytes.

54 bytes

f=lambda s,p=" kMGT":s and f(s[:-3],p[1:])+s[-3:]+p[0]

Try it online!

One potentially-useful observation is that the string format '{:,}'.format puts commas in the places we want to insert letters:

'{:,}'.format(1234567) == "1,234,567"

However, I haven't found a short enough way to use this.

xnor

Posted 2019-10-11T10:31:12.383

Reputation: 115 687

Yep, shortest format version I got so far: 76 bytes

– movatica – 2019-10-13T16:35:44.823

4

Brachylog, 17 bytes

↔ġ₃;"
kMGT"↔z₀cc↔

Input as a string, returns through output the result, with a trailing newline :)
Explanation:

            More or less a translation of Jelly answer:
↔           Reverse input string
 ġ₃         Group into triples, excluding last group with length in range (0,3]
   ;        Pair those groups with:
    "
kMGT"       A string containing a newline followed by the symbols in reverse order
     ↔      Reverse the pair so the string comes before the list of digit triplets
      z₀    Zip the pair until the smallest list is depleted
        cc  Concatenate the zipped lists together, then concatenate the strings together
          ↔ Reverse the result

Try it online

IFcoltransG

Posted 2019-10-11T10:31:12.383

Reputation: 191

Looks like we have a new Brachylog user :) – Fatalize – 2019-10-15T06:52:04.377

@Fatalize What gave you that idea? :) You created a nice language, but I wouldn't have found it without that bounty on another question. It'd be harder if I didn't already know a bit of Prolog, of course. – IFcoltransG – 2019-10-16T07:09:03.697

The idea to create Brachylog? Well I started participating to this site with Prolog, because I though it would be fun and different. Then people started creating new golf languages in the second half of 2015, which gave me the insipiration to make a shorthand version of Prolog – Fatalize – 2019-10-16T07:11:45.500

3

Perl 5 (-p), 40 bytes

y/ kMG/kMGT/while s/\d\K((\d{3})+$)/ $1/

Try it online!

Grimmy

Posted 2019-10-11T10:31:12.383

Reputation: 12 521

3

Jelly, 14 bytes

13 if input formatted as a string is acceptable for languages which can handle large integers (remove and quote the argument)

ṾṚs3żFtṚʋ“kMGT

A full program accepting the non-negative number as a command line argument which prints the result

Try it online!

How?

ṾṚs3żFtṚʋ“kMGT - Main Link: integer         e.g. 12345
Ṿ              - un-evaluate the integer         ['1', '2', '3', '4', '5']
 Ṛ             - reverse                         ['5', '4', '3', '2', '1']
  s3           - split into chunks of three      [['5', '4', '3'], ['2', '1']]
         “kMGT - literal list of characters      ['k', 'M', 'G', 'T']
        ʋ      - last four links as a dyad  i.e. f([['5', '4', '3'], ['2', '1']], ['k', 'M', 'G', 'T'])
    ż          -   zip                           [[['5', '4', '3'], 'k'], [['2', '1'],'M'], ['G'], ['T']]
     F         -   flatten                       ['5', '4', '3', 'k', '2', '1','M', 'G', 'T']
      t        -   trim (from either side)       ['5', '4', '3', 'k', '2', '1']
       Ṛ       -   reverse                       ['1', '2', 'k', '3', '4', '5']
               - implicit (smashing) print       12k345

Jonathan Allan

Posted 2019-10-11T10:31:12.383

Reputation: 67 804

2

PHP, 67 65 bytes

for(;''<$d=$argn[-++$i];)$r=$d.' kMGT'[$i%3==1?$i/3:5].$r;echo$r;

Try it online!

Loops on input digits from right to left and concatenates each digit to $r variable in reversed order. When we are on 4th, 7th, etc... digit, the respective prefix is concatenated to $r as well. Output has a trailing space.

for(;''<$d=$argn[-++$i];) // loop on input digits from right to left, $d is current digit and $i is incremental (1, 2, ...)
  $r=$d                   // concatenate current digit to beginning of $r
  .' kMGT'                // string of prefixes, first item is space for first digit and causes a trailing space in output
    [$i%3==1?$i/3:5]      // if $i is 1, 4, 7, etc... concatenate letter at index of $i/3 (1/3=0.33, 4/3=1.33, 7/3=2.33, etc...)
                          // PHP uses integer part of decimal indexes, so 1.33 will return the letter at index 1
                          // for any other $i, use index 5 which doesn't exist and is equal to an empty string
  .$r;                    // concatenate $r itself to the end, so everything will be in reversed order of reading (which itself is in reversed order of input)
echo$r;                   // output $r when the loop is finished

A schematic example for how an output is created for input of 1234:

| Current Digit | Concatenation | $r    |
|---------------|---------------|-------|
| 4             | 4             | 4     |
| 3             | 3             | 34    |
| 2             | 2             | 234   |
| 1             | 1k            | 1k234 |

Night2

Posted 2019-10-11T10:31:12.383

Reputation: 5 484

2

Icon, 76 71 bytes

procedure f(s)
k:=0
s[i:=*s-2to 2by-3:i]:="kMGT"[k+:=1]&\z
return s
end

Try it online!

Takes input as a string.

Galen Ivanov

Posted 2019-10-11T10:31:12.383

Reputation: 13 815

2

JavaScript (Node.js), 55 bytes

f=(n,i=0)=>n.replace(/.+(?=...)/,d=>f(d,i+1)+'kMGT'[i])

Try it online!

tsh

Posted 2019-10-11T10:31:12.383

Reputation: 13 072

2

Poetic, 485 bytes

honestly
i lived my life
i faced a boatload of brutal challenges
i desire a day of bliss-i want badly to forget a day where things backfire
i desire a day-i covet a week-and of course i want solitude around everyone
i desire a day-i crave a year-finding no faults i seem to create everyday
i desire a day-i plead,i pray-for an answer i need,i should deserve
fea-r-s,smea-r-s
really,i have a stupid aim
oh world,why was i on earth
o,i suggest venus
o,i deserve a way i go to space
by-by

Try it online!

Poetic is an esolang I made in 2018 for a class project. It's basically brainfuck with word-lengths instead of symbols.

The point of the language is to allow for programs to be written in free-verse poetry. It was fun to write this one (though usually two consecutive ones would be written as 11-letter words; it was hard to golf this poem and make it sound interesting!).

This poem is equivalent to the following brainfuck program, which others are more than welcome to golf:

,[>>->,]<<<<<<<<<<[<++>-----]<+++++<<<<<<<<[<+>---]<--------<<<<<<<<[<+>-------]<--<<<<<<<<[<+>---]<-<<<<<<<-[+[<+<<<]>>>-]>[.>[.[+]]>>]

JosiahRyanW

Posted 2019-10-11T10:31:12.383

Reputation: 2 600

1

Red, 85 bytes

func[n][p: copy"kMGT"parse reverse n[any[3 skip ahead skip insert(take p)]]reverse n]

Try it online!

Takes the input as a string.

Galen Ivanov

Posted 2019-10-11T10:31:12.383

Reputation: 13 815

1

APL+WIN, 46 bytes

Prompts for integer as a string

∊(n/m),¨(n←3>+/¨' '=¨m←((3/⍳5)⊂¯15↑⎕))/'TGMk '

Try it online! Courtesy of Dyalog Classic

Graham

Posted 2019-10-11T10:31:12.383

Reputation: 3 184

1

PowerShell, 81 73 71 69 64 bytes

($a=$args)|%{$r=$a[--$i]+' kMGT'[$j+5*!$k]+$r;$j+=$k=!($i%3)}
$r

Try it online!

Takes argument as a splatted string.

mazzy

Posted 2019-10-11T10:31:12.383

Reputation: 4 832

1

Gema, 88 characters

\A=@subst{?=\@push\{p\;?\};TGMk }
*=@reverse{@subst{<d3>=\$p\$1\@pop\{p\};@reverse{$0}}}

Boring double reverse approach, but looping in Gema would be painfully long.

Sample run:

bash-5.0$ echo -n '1234567890' | gema '\A=@subst{?=\@push\{p\;?\};TGMk };*=@reverse{@subst{<d3>=\$p\$1\@pop\{p\};@reverse{$0}}}'
1G234M567k890 

Try it online!

manatwork

Posted 2019-10-11T10:31:12.383

Reputation: 17 865

1

C (clang), 65 62 bytes

f(char*n,z){for(;z--;z%3||printf(L" kMGT"+z/3))putchar(*n++);}

Try it online!

Taking a char array as input.

Saved 3 thanks to @ceilingcat

C (clang), 68 bytes

f(n,s){!s|n&&f(n/10,s+1)+printf(s%3?"%d":"%d%c",n%10," kMGT"[s/3]);}

Try it online!

Taking an int as input

Recursive function which first call itself and outputs after.

f(n,s) // Idk if it's acceptable or if I have to wrap with a g(n){f(n,0);}
{
!s| // to allow 0 value calls
n&& // when n=0 exit recursion 
f(n/10,s+1)+printf(
s%3?"%d":"%d%c" // select format string
,n%10, // digit to print
" kMGT"[s/3]);} // if second format selected add character

AZTECCO

Posted 2019-10-11T10:31:12.383

Reputation: 2 441

1

Bash, 83 bytes

a=('' k M G T)
s=
(($1>99))&&s=${1: -3}
echo `$0 ${1:0:-3} $[$2+1]`${s:-$1}${a[$2]}

Try it online! (link shows 82 bytes, but uses function recursion instead of $0-recursion)

Nice little recursive solution.

Bash doesn't like invalid string indexing, which both helps (gives us our exit condition for free) and hurts (we have to have separate logic for when our number has n != 0 mod 3 digits).

GammaFunction

Posted 2019-10-11T10:31:12.383

Reputation: 2 838

1

Perl 6, 39 bytes

{flip [~] <<''k M G T>>Z~.flip.comb(3)}

Try it online!

nwellnhof

Posted 2019-10-11T10:31:12.383

Reputation: 10 037

0

Python3, 89 83 bytes 65 chars

(or 65 bytes, if you use just ASCII, but I fancy the Unicode superscript small letters)

f=lambda n,p='ᵏᴹᴳᵀ':len(n)<4 and n or f(n[:-3],p[1:])+p[0]+n[-3:]

Try it online!

Python3, 89 bytes:

import re;print(''.join(sum(zip(re.findall('..?.?',str(x)[::-1]),'kMGT.'),()))[::-1][1:])

Try it online!

I didn't try to shorten this dramatically. See it as an incentive to beat me :) This is my first challenge in this forum; by now I understand the asker isn't supposed to post an answer right away. Next time I will wait a little longer before doing it. But since I couldn't really undo the post (deleting the post leaves it visible to too many people anyway), I saw no use in even trying to.

Alfe

Posted 2019-10-11T10:31:12.383

Reputation: 307

1It is fine to answer your own challenge, but normally, authors wait for a while (I'd say a week) to give others a chance. – Adám – 2019-10-11T10:53:41.667

3

Taking input in a variable is not allowed. Typically, answers are either functions with the relevant number of arguments, or full programs using STDIN / STDOUT. For more detailed rules, see Default for Code Golf: Input/Output methods.

– Arnauld – 2019-10-11T11:39:15.643

@Alfe, as the maximum length to handle is known, you could just pad the input up to a multiple of 3 ≥ 15, then split to groups from left, without reversing twice: Try it online! Just hint, it still violate the IO rule.

– manatwork – 2019-10-11T12:23:53.910

Or the same pad & trim idea without reversing, but with a for loop over hardcoded list: Try it online!

– manatwork – 2019-10-11T12:51:36.040

@Arnauld Thanks for the clarification, but that leaves me with the option to replace the str(x) by input(), effectively even skipping the conversion to string (and adding a byte). How should we pass in a number in code-golf? Always via reading from stdin and converting it to int afterwards? – Alfe – 2019-10-11T23:29:03.970

@Alfe See the golfing rules summary for Python.. Your first function is fine as a standalone. If you use Python 2, its input can take in a number or string. For functions, you can also generally assume whichever kind you prefer.

– xnor – 2019-10-12T01:24:34.937

1Your answer doesn't follow your own spec; just leave it at kGMT instead of your fancy Unicode. Especially because the default scoring is bytes not characters. – Sanchises – 2019-10-13T06:54:18.103

You can remove the space after the 4, like: len(n)<4and – Reinstate Monica – 2019-10-15T17:37:20.747

0

Python 2, 84 74 bytes

i=input();o=""
for x in"kMGT ":o=(i,x+i[-3:])[len(i)>3]+o;i=i[:-3]
print o

Try it online!

Previous version for 84 bytes

i=input()[::-1];o=""
for x in"kMGT ":o+=(i,i[0:3]+x)[len(i)>3];i=i[3:]
print o[::-1]

Try it online!

  • Reverse the input
  • Step through backwards in threes appending prepending the next letter
  • Reverse and print

Not sure that this is the most efficient approach but it's the best I can come up with at the moment.

ElPedro

Posted 2019-10-11T10:31:12.383

Reputation: 5 301

0

JavaScript (V8), 71 bytes

Takes input as number

b=(a,l=10e11,x=0,c=a/l|0)=>(l-1)?(c?c+'TGMk'[x]:'')+b(a%l,l/1000,x+1):c

Try it online!

RetekBacsi

Posted 2019-10-11T10:31:12.383

Reputation: 1

0

Retina 0.8.2, 31 bytes

r`\B...
,$.'$&
T`9630,`TGMk_`,.

Try it online! Explanation:

r`\B...

Match groups of three digits starting from the end but ensure that there is at least one more digit before the match.

,$.'$&

Prefix each match with a marker comma and the number of digits after the match (0 for the last match, then 3, 6 and 9 respectively).

T`9630,`TGMk_`,.

Replace the marker and following number with the appropriate suffix.

Neil

Posted 2019-10-11T10:31:12.383

Reputation: 95 035

0

Python 2, 72 bytes

f=lambda n,p=' kMGT':(n>M and f(n/M,p[1:])or'')+`n%M+M`[-3:]+p[0]
M=1000

Try it online!

Chas Brown

Posted 2019-10-11T10:31:12.383

Reputation: 8 959

001G234M567k890 is not the correct output. But I also thought about a recursive solution! – Alfe – 2019-10-11T23:41:08.230

@Alfe: "The result shall be groups of three digits...". 001 is a group of three digits; 1 is not a group of three digits. – Chas Brown – 2019-10-12T01:50:38.500

… as available. The digits 00 in your example are invented and not part of the input. – Alfe – 2019-10-14T08:32:01.373

0

Zsh, 53 bytes

a=kMGT
for z y x (${(Oas::)1})s=$x$y$z$a[i++]$s
<<<$s

Try it online!

(s::) splits the stirng, Oa reverses the characters. Zsh arrays and strings are 1-indexed, so $a[0] on the first iteration substitutes nothing.

GammaFunction

Posted 2019-10-11T10:31:12.383

Reputation: 2 838

0

Haskell, 99 bytes

f n=concatMap(\(a,b)->a++b)$reverse$zip(reverse<$>chunksOf 3(reverse$show n))(["","k","M","G","T"])

Try it online!

The function f takes a number, converts it into a string and splits it backwards into chunks of 3 characters, e.g.

reverse<$>chunksOf 3(reverse$show 1234) == ["234","1"] 

it then zips the list of chunks with the list of magnitue identifieres ["","k","M","G","T"]. Then the list is reversed and with concatMap converted to one string. It uses the function chunksOf from the package Data.List.Split

Ackdari

Posted 2019-10-11T10:31:12.383

Reputation: 101

0

Forth (gforth), 84 bytes

: f s" kMGT" bounds <# do
1000 /mod tuck if
0 # # # d. i c@ hold then loop
0 #s #> ;

Try it online!

A function that takes a number from the stack, and returns a string as (address, length) pair, which is the standard representation for a string in Forth. Produces lots of garbage under the returned string, and a few zeros on stdout.

Forth has a dedicated set of facilities for customized number-to-string formatting, and this challenge seemed to be the right place to showcase it.

On the golfing perspective, I found that do .. if .. then loop (test and ignore the rest of the body) is shorter than begin .. while .. repeat (test and break simple loop) or do .. if leave then .. loop (test and break counted loop).

How it works

: f ( n -- addr len )
  s" kMGT"            \ Create a local string "kMGT"; gives its address and length
  bounds              \ Convert (addr, len) to (addr+8*len, addr)
  <#                  \ Initialize the buffer for number-to-string conversion
  do                  \ Loop; i = addr .. addr+8*len; stack=(n)
    1000 /mod         \   Calculate n%1000 and n/1000
    tuck if           \   Stack=(n/1000 n%1000); if n/1000 is nonzero...
      0 # # # d.      \     emit three digits from n%1000 and discard it
      i c@ hold       \     emit the next char of "kMGT"
    then              \   End if
  loop                \ End loop
  0 #s                \ Emit all the remaining digits
  #>                  \ Finish conversion; push addr/len of the result string
;                     \ End function

Bubbler

Posted 2019-10-11T10:31:12.383

Reputation: 16 616