16
\$\begingroup\$

Write the shortest function to convert an integer into a numeric representation given a radix between 2 and 62. e.g.:

to_string(351837066319, 31) => "codegolf"
\$\endgroup\$
4
  • 2
    \$\begingroup\$ From the example I gather that lower case letters come first, i.e. the digits in base 62 are 0-9,a-z,A-Z in that order? \$\endgroup\$
    – sepp2k
    Commented Feb 5, 2011 at 0:07
  • 1
    \$\begingroup\$ Yes, exactly, that's it. \$\endgroup\$ Commented Feb 5, 2011 at 18:20
  • \$\begingroup\$ at 0:00, dang, perfect. \$\endgroup\$
    – Adalynn
    Commented Aug 27, 2017 at 21:02
  • \$\begingroup\$ @Adalynn posted at 46 seconds after midnight (Zulu), so not that perfect. \$\endgroup\$ Commented Mar 16 at 11:13

20 Answers 20

5
\$\begingroup\$

Python - 86

from string import*
def t(n,r,s=''):
 while n:s=printable[n%r]+s;n/=r
 return s or'0'

Credit due to Hoa Long Tam for the string import trick

\$\endgroup\$
4
\$\begingroup\$

dc - 43 chars

[sb[58-]s_[lb~dZ39*+dB3<_9+rd0<xrP]dsxxk]sf

We can shorten this a little if we assume the stack contains only the two arguments.

[[58-]s_dSb~dZ39*+dB3<_9+SadLbr0<fLaPc]sf

As a standalone program, we only need 37 characters:

?o[58-]s_[O~dZ39*+dB3<_9+rd0<xrP]dsxx

Instead of using [39+]sz9<z, we simply use Z39*+, which will add 39 for a single digit number, and 78 for a double digit number. Instead of 113, we use B3 (AD also works).

\$\endgroup\$
4
\$\begingroup\$

Ruby 1.8 - 75 characters, with recursion.

f=proc{|n,b|(n<b ? "":f[n/b,b])+([*'0'..'9']+[*'a'..'z']+[*'A'..'Z'])[n%b]}

Without recursion

f=proc{|n,b|d=[*'0'..'9']+[*'a'..'z']+[*'A'..'Z'];s=d[n%b];s=d[n%b]+s while(n/=b)>0;s}

(both based on Dogbert's 1.9 solution.)

\$\endgroup\$
3
\$\begingroup\$

Python, 93 99

from string import *
d=digits+letters
def t(n,b):
 s=''
 while n>0:s=d[n%b]+s;n/=b
 return s or '0'

EDIT: " or '0'" added for empty string case

\$\endgroup\$
1
  • \$\begingroup\$ Fails when n = 0, returns an empty string when it should return '0'. Anyway +1 for the string trick \$\endgroup\$
    – Champo
    Commented Feb 5, 2011 at 3:52
2
\$\begingroup\$

dc, 61 chars

[sr[lr~rd0<x]dsxxk[39+]sa[58-]sb[d9<ad78<b48+anz0<p]dspxIP]sf

Run as:

dc -e'[sr[lr~rd0<x]dsxxk[39+]sa[58-]sb[d9<ad78<b48+anz0<p]dspxIP]sf' -e'351837066319 31 lfx'

or:

dc -f base.dc -e '351837066319 31 lfx'

Explanation: We take the number and base on the stack. sr saves the base in register r. The recursive function [lr~rd0<x]dsxx decomposes a number TOS into its digits in base register r. The first digit is always 0, removed from the stack by k (set precision, which by default is 0 also, so it's equivalent to a nop). Then, the recursive function [48+d57<ad122<banz0<p]dspx outputs each digit in ASCII, with the help of functions a ([39+]sa) and b ([58-]sb). IP outputs a newline. The function is stored in register f, and can be invoked by lfx.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ If you move 48+ to the end it saves two (57 and 122 both drop a character). Also a minor oversight is that as a function, you can't assume there is nothing else on the stack, but the problem would be removed if you merged the loops (which would also save a few characters). \$\endgroup\$
    – Nabb
    Commented Feb 7, 2011 at 22:17
2
\$\begingroup\$

Ruby - 72 70 59 chars

f=->n,b{(n<b ? "":f[n/b,b])+[*?0..?9,*?a..?z,*?A..?Z][n%b]}

Without recursion, 70 chars

f=->n,b{d=*?0..?9,*?a..?z,*?A..?Z;s=d[n%b];s=d[n%b]+s while(n/=b)>0;s}

Test

irb(main):080:0> f[351837066319, 31]
=> "codegolf"
irb(main):081:0> f[0, 31]
=> "0"
\$\endgroup\$
2
\$\begingroup\$

Burlesque, 4 bytes

peB!

Try it online!

Luckily a built-in in Burlesque

pe # Parse and push
B! # Convert base
\$\endgroup\$
2
\$\begingroup\$

Ruby 1.9 - 80 74 68

t=->n,b{d=*?0..?9,*?a..?z,*?A..?Z;s='';(s=d[n%b]+s;n/=b)while n>0;s}

With '0' for empty string, 95 89 82 characters:

t=->n,b,s=''{d=*?0..?9,*?a..?z,*?A..?Z;(s=d[n%b]+s;n/=b)while n>0;s.empty?? ?0: s}

Ruby 1.9 - unfortunately only works up to base 36:

t=->n,b{n.to_s(b)}
\$\endgroup\$
1
  • 2
    \$\begingroup\$ You can replace the ]+['s with ,. \$\endgroup\$
    – Nemo157
    Commented Feb 7, 2011 at 0:14
2
\$\begingroup\$

Python 2, 64 bytes

f=lambda n,b:n and f(n/b,b)+chr(n%b+48+(n%b>9)*39-n%b/36*58)or''

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Haskell, 109 characters

m=divMod
d(0,x)b=[f x]
d(r,x)b=f x:d(m r b)b
f=(!!)$['0'..'9']++['a'..'z']++['A'..'Z']
s x b=reverse$d(m x b)b
\$\endgroup\$
1
  • \$\begingroup\$ Feels a bit wrong suggesting golfs to something over 10 years old, but I may as well note that this can be shaved down a good 5 bytes, by factoring the whole d(m r b)b pattern into m (with a bit of help from the Applicative instance for functions), then using that to convert s to pointfree. \$\endgroup\$ Commented Jul 5, 2021 at 15:25
1
\$\begingroup\$

Befunge - 53 x 2 = 106 characters

Or 53 + 46 = 99 characters if you're willing to route other parts of your program through the bottom left.

11p01-\>:11g%\11g/:#v_$>:1+!#v_:45+`!#v_:75*`!#v_   v
       ^            <  ^,    $# +"0"  < +"'"   <-":"<

First place the number to be converted on the stack, then the radix and enter this function from the top-left going right. Will output the string for you (since Befunge doesn't support string variables) and leave from the bottom $ going down. Requires the (1,1) cell for radix storage.

E.g. for the example given put 351837066319 into the input and run:

&56*1+    11p01-\>:11g%\11g/:#v_$>:1+!#v_:45+`!#v_:75*`!#v_   v
                 ^            <  ^,    $# +"0"  < +"'"   <-":"<
                                       @
\$\endgroup\$
1
\$\begingroup\$

Golfscript - 32 chars

{base{.9>39*+.74>58*48--}%''+}:f
\$\endgroup\$
1
\$\begingroup\$

Bash, 79 chars

f(){
dc<<<$2o$1p|perl -pe"y/A-Z/a-z/;s/ \d+/chr$&+($&<10?48:$&<36?87:29)/ge"
}
\$\endgroup\$
8
  • \$\begingroup\$ BC_BASE_MAX is documented as being 16. I don't know what miracle makes the output right on the sample input, but it outputs garbage (i.e. non alphanum characters) for most other bases. \$\endgroup\$
    – J B
    Commented Feb 6, 2011 at 14:30
  • \$\begingroup\$ @J B: which bc are you using? GNU bc should work. sysconf(_SC_BC_BASE_MAX) returns 99 on my system, 16 is the minimum required. \$\endgroup\$
    – ninjalj
    Commented Feb 6, 2011 at 14:37
  • \$\begingroup\$ @J B: also note that previous revisions where buggy, I had just skimmed at the question requirements. \$\endgroup\$
    – ninjalj
    Commented Feb 6, 2011 at 14:39
  • \$\begingroup\$ bc 1.06. Now you mention it, I got the figure from the manpage, but misread it. 16 is the input base limit. The output base limit is 999. I did first try on an earlier version, let's see that again now. \$\endgroup\$
    – J B
    Commented Feb 6, 2011 at 14:53
  • 1
    \$\begingroup\$ I think this one outputs uppercase letters for bases 11-16 instead of lower case. You can save a few at the base conversion by using dc instead of bc. \$\endgroup\$
    – Nabb
    Commented Feb 7, 2011 at 8:58
1
\$\begingroup\$

Jelly, 5 bytes

b‘ịØB

Try it online!

The case will be reversed (codegolf - CODEGOLF) because of Jelly built-in base characters string.

How?

b‘ịØB - Link, input x & y
b     - Convert x to base y
 ‘    - Increment (because Jelly use based-1 indexing)
  ị   - List (string) indexing
   ØB - "0-9 A-Z a-z"
\$\endgroup\$
1
\$\begingroup\$

Go, 76 bytes

package m
import."math/big"
func e(n int64)string{return NewInt(n).Text(62)}

bonus decode:

package m
import."math/big"
func d(s string)int64{o,_:=NewInt(0).SetString(s,62)
return o.Int64()}
\$\endgroup\$
1
\$\begingroup\$

Japt, 9 bytes

Follows the example of the Jelly solution in reversing the casing.

;sVîEowi%

Try it

\$\endgroup\$
1
\$\begingroup\$

Stax, 5 bytes

VL(:B

Run and debug it

Same size packed, a custom base conversion.

\$\endgroup\$
0
\$\begingroup\$

Perl 5 -Minteger -ap, 52 bytes

do{$\=(0..9,a..z,A..Z)[$_%$F[1]].$\}while$_/=$F[1]}{

Try it online!

\$\endgroup\$
0
\$\begingroup\$

05AB1E (legacy), 8 7 bytes

вžLšRsè

-1 byte by switching to the legacy version of 05AB1E, where the switch_case builtin was one byte (it's in the new version).

Inputs in the order \$radix,number\$. Output as a list of characters.

Try it online.

Old 8 bytes non-legacy 05AB1E answers (same I/O as above):

Explanation:"

в        # Convert the second (implicit) input to base-(first implicit input) as list
 žL      # Push string "zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210"
   š     # Switch case: "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210"
    R    # Reverse it: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
     s   # Swap so the list is at the top
      è  # Index each into this string
         # (after which the resulting character-list is output implicitly)
žh       # Push constant string "0123456789"
    «    # Append
  ži     # Constant string "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
         #  "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
     £   # Only keep the first (implicit) input amount of characters from this string
      Åв # Convert the second (implicit) input to this custom base-"0-9a-zA-Z"
         # (which basically converts it to base-length, and indexes it into the string)
         # (after which the resulting character-list is output implicitly)

в        # Convert the second (implicit) input to base-(first implicit input) as list
 žK      # Push string "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789"
   9Ý    # Push list [0,1,2,3,4,5,6,7,8,9]
     †   # Filter all those characters to the front:
         #  "012346789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
      s  # Swap so the list is at the top
       è # Index each into this string
         # (after which the resulting character-list is output implicitly)
\$\endgroup\$
0
\$\begingroup\$

Pascal, 236 B

This function requires a processor supporting features of Extended Pascal as described by ISO standard 10206, in particular the string capabilities. Note, the golfed version is restricted to 98 digits. Furthermore, a character (here the sign) is always prepended.

type s=string(99);function f(n,b:integer):s;begin
f:=('- +')[ord(n>0)-ord(n<0)+2];n:=abs(n);repeat
f:=('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')[n mod b+1]+f;n:=n div b
until n=0;n:=length(f);f:=f[n]+f[1..n-1]end

Ungolf’d, annotated and reasonably good programming style:

    const
        { Number of binary digits required to write `maxInt` out. }
        maxIntBinaryLength = trunc(ln(maxInt) / ln(2)) + 1;
        { Known digits for `positionalNotation` function. }
        digit = '0123456789abcdefghijklmnopqrstuvwxyz' +
                          'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        { Characters for negative sign, no sign, and positive sign. }
        sign = '− +';
    
    type
        { For sorting purposes starts with `integer…` prefix. }
        integerNonNegative = 0‥maxInt;
        { A string capable of representing any integer plus a sign. }
        integerString = string(maxIntBinaryLength + 1);
        { Acceptable `base` for `positionalNotation` function. }
        radix = 2‥62;
    
    { Returns −1, 0, or +1 depending on the sign of the argument. }
    function signum(protected n: real): integer;
        begin
            signum ≔ ord(n > 0) − ord(n < 0)
        end;
    
    { Retrieve positional notation of a given integer in a given base. }
    function positionalNotation(
            protected n: integer;
            protected base: radix
        ): integerString;
        { Separate string to work with, and ensure non‑negative number. }
        function position(magnitude: integerNonNegative): integerString;
            begin
                position ≔ '';
                { This is just your run‑of‑the‑mill Horner’s method. }
                repeat
                begin
                    { Prepend a digit. Note, string indices are 1‑based. }
                    position  ≔ digit[magnitude mod base + 1] + position;
                    magnitude ≔ magnitude div base
                end
                until magnitude = 0
            end;
        begin
            { The algorithm is prepending digits, but the sign must be first. }
            positionalNotation ≔ sign[signum(n) + 2] + position(abs(n))
        end

Signum function PPCG challenge │ RosettaCodeFreePascal Wiki

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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