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"
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
[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).
f=proc{|n,b|(n<b ? "":f[n/b,b])+([*'0'..'9']+[*'a'..'z']+[*'A'..'Z'])[n%b]}
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.)
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
[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
.
f=->n,b{(n<b ? "":f[n/b,b])+[*?0..?9,*?a..?z,*?A..?Z][n%b]}
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"
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)}
]+[
's with ,
.
\$\endgroup\$
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
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
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" < +"'" <-":"<
@
{base{.9>39*+.74>58*48--}%''+}:f
f(){
dc<<<$2o$1p|perl -pe"y/A-Z/a-z/;s/ \d+/chr$&+($&<10?48:$&<36?87:29)/ge"
}
sysconf(_SC_BC_BASE_MAX)
returns 99 on my system, 16 is the minimum required.
\$\endgroup\$
dc
instead of bc
.
\$\endgroup\$
b‘ịØB
The case will be reversed (codegolf - CODEGOLF) because of Jelly built-in base characters string.
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"
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()}
вž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.
Old 8 bytes non-legacy 05AB1E answers (same I/O as above):
žhži«£Åв
- Try it online.вžK9݆sè
- Try it online.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)
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 │ RosettaCode │ FreePascal Wiki
at 0:00
, dang, perfect. \$\endgroup\$