# Convert a string of ASCII characters to base-3 equivalents

Task similar to this one. Take a string of ASCII characters and convert it to base-3 equivalents separated by a space.

For example:

Hello, world!


Should be converted to

02200 10202 11000 11000 11010 01122 01012 11102 11010 11020 11000 10201 01020


The output should only contain numbers with the same number of digits. Which separator to use is up to you.

This is a code-golf challenge so the shortest solution wins.

• @Fmbalbuena ASCII Feb 20 at 0:18
• So for ABC can the input be 2102 2110 2111 (no zero padding)? Please clarify in the challenge, maybe with a couple more examples. Also, how strict is the output format? Do we really need to use a space as separator? Can there be another separator between the digits? Feb 20 at 0:23
• Are the leading zeros in the output necessary? Why the strict output requirement (space separated rather than site default which would allow a list of lists etc...)? Feb 20 at 0:25
• @Fmbalbuena Those are site defaults. If the challenge author decides on spaces only, that's perfectly fine. Feb 20 at 0:48
• @JonathanAllan Yes. Feb 20 at 1:33

# MATL, 3 bytes

3YA


Uses newline as separator. Try it online!

### Explanation (by @Sundar R)

YA is a single function, corresponding to Matlab's dec2base (convert from decimal to some base). By default it takes two arguments: an array with the numbers to convert and the base to convert to. Since only the second argument (3) is specified here, the input is implicitly used as the first argument.

The cool part is that this is automatically applied to the whole input (which is a char array), the results collected into a char matrix, and when things don't line up, 0's are automatically prepended to make them have the same width.

• ok this is this is insanely short, what does the Y and A do though? Feb 20 at 2:35
• @DialFrost YA is a single command dec2base (convert decimal to some base) that takes two arguments - the number to convert and the base to convert to. Since we've specified only the second argument (3) here, the input is automatically prepended as the first argument. Feb 20 at 11:58
• The cool part is that its automatically applied to the whole input (which is seen as a char array), the results collected into a matrix, and when things don't line up, 0's are automatically prepended to make them have the same width. Feb 20 at 12:00
• @SundarR Thanks! Your comments describe what the code does so well that I incorporated them into the answer (with proper credit); I hope you don't mind Feb 20 at 17:01

# Python 3,  70 66  62? 66 bytes

for c in input():print(*[ord(c)//d%3for d in b'Q    '],sep='')


(Code contains unprintable bytes inside the b'...')

A full program accepting input from STDIN that prints the result using a newline separator (with a trailing newline).

Try it online!

...but 66 if we need to handle multi-line strings (since input() only reads one line:

lambda s:[print(*[ord(c)//d%3for d in b'Q   '],sep='')for c in s]


An unnamed function that prints the answer.

Try it online!

• sigh i took to long to come up with this answer Feb 20 at 1:36
• @DialFrost I thought I might not get there since I spent a while golfing the other Python answer. Feb 20 at 1:38
• ok now ur hacking @JonathanAllan 62 bytes!!!! how (Nice use of unprintable chars) Feb 20 at 2:14
• link for 2nd code? and im pretty sure the 2nd on is 64 bytes??? Feb 20 at 2:19
• @DialFrost - added. There are unprintable characters in there. Feb 20 at 2:22

# Jelly, 9 bytes

All-ASCII jelly code to boot...

Ob3Uz0ZUK


A full program accepting a string that prints the result.

Try it online!

### How?

Ob3Uz0ZUK - Main Link: list of characters
O         - ordinals
b3       - to base three
U      - upend (reverse each)
z0    - transpose with filler of zero
Z   - transpose
U  - upend (reverse each)
K - join with spaces
- implicit, smashing print


# Charcoal, 14 bytes

⪫ＥＳ⭆◧⍘℅ι³¦⁵Σλ


Try it online! Link is to verbose version of code. Explanation:

  Ｓ             Input string
Ｅ              Map over characters
ι        Current character
℅         ASCII code
⍘  ³       Convert to base 3
◧     ⁵     Left pad to length 5
⭆            Map over characters and join
λ   Inner character
Σ    Numeric value if any
⪫               Join with spaces
Implicitly print


12 bytes to print as a list:

ＵＢ0←Ｅ⮌Ｓ⮌⍘℅ι³


Try it online! Link is to verbose version of code. Explanation:

ＵＢ0


Set output to zero fill.

←Ｅ⮌Ｓ⮌


Output the strings upside-down and reversed (which right-justifies them) given by...

⍘℅ι³


... converting the ASCII codes to base 3.

# Python 3, 71 bytes

import numpy
for i in input():print(numpy.base_repr(ord(i),3).zfill(5))


Try it online!

-30 thanks to Jonathan Allan, I'm lazy to golf another code

Prints numbers separated by newlines

If you really need space as a separator then here is the code:

# Python 3, 176 bytes

import numpy
m=input()
y=m[:-1]
u=lambda x:"0"*(5-len(x))+x
for i in y:print(u(str(numpy.base_repr(ord(i),base=3))),end = " ")
print(u(str(numpy.base_repr(ord(m[-1]),base=3))))


Try it online!

• print(numpy.base_repr(ord(i),3).zfill(5)) saves 30. Feb 20 at 0:57
• This only saves 1, Can you show me the full code? Feb 20 at 1:05
• TIO (also, use @ to notify :)) Feb 20 at 1:15
• (Actually it shouldn't need @ since I am the only one who commented - just got notified after 10 mins :/) Feb 20 at 1:17
• @JonathanAllan Thanks Feb 20 at 1:21

# Factor, 38 34 bytes

[ [ 3 >base "%05s "printf ] each ]


Try it online!

• [ ... ] each For each code point in the input string,
• 3 >base convert it to base 3
• "%05s "printf and print it with leading zeros to a length of five, followed by a space.

# Vyxal, 9 bytes

C3τvṅ5∆Z⁋


Uses newline as the separator.

C3τvṅ5∆Z⁋
C            Convert to ASCII codepoint
3τ          Convert each character to base 3
vṅ        Join by nothing, because to-base returns a list of digits
5∆Z     Pad with 5 zeros (because that's the max length of an ASCII char)
⁋    Join by newlines


Try it Online!

It will probably get 9 bytes soon, because of a bug (to-base doesn't support vectorization)
Lyxal epic speed bug fix done

Actually, 8 bytes with flag, but j is very buggy

# R, 63 59 bytes

function(s)write(rep(utf8ToInt(s),e=5)%/%3^(4:0)%%3,1,,,"")


Try it online!

Nothing clever, but a straightforward implementation in R is shorter than anything else that I can think of so far...
To avoid the penalty of defining a base-conversion function to use on each character, we repeat each character value 5 times, and then use vectorized integer division (%/%) and modulo (%%) to calculate all the base-3 digits. Then, by lucky co-incidence, the write function splits its output data into a column width of 5 by default.

# Javascript (Node.js), 62 59 bytes

f=

x=>[...x].map(t=>(t.charCodeAt()+243).toString(3).slice(1))

console.log((f+'').length);
console.log(f("Hello World!")+'');

Try it online!

-3 thanks to @tsh

• I believe you don't need the +''.
– tsh
Feb 21 at 6:28

# BQN, 20 bytes

{'0'+3|⌊𝕩÷3⋆⌽↕5}¨-⟜@


Anonymous function that takes a string and returns a list of strings. Run it online!

If a list of lists of digits is an acceptable output format, then it's 16 bytes:

{3|⌊𝕩÷3⋆⌽↕5}¨-⟜@


### Explanation

{'0'+3|⌊𝕩÷3⋆⌽↕5}¨-⟜@
-⟜@  Subtract '\0' from each character, converting to list of charcodes
{               }¨      Map this function to each charcode:
↕5          Range(5)
⌽            Reverse
3⋆              3 to the power of each
𝕩÷                Divide the argument by each
⌊                  Floor
3|                   Mod 3
'0'+                     Convert digits to characters by adding '0'


# GeoGebra, 74 50 bytes

Zip(Take(ToBase(a,3),2,6),a,TextToUnicode("")+243)


Insert string input between the "". (I guess this is allowed) Output is a list of strings padded to 5 digits. (This is also allowed by OP)

Uses the " add $$\3^5\$$ " idea from @DLosc's answer.

Try It On GeoGebra!

# Burlesque, 14 bytes

)**m{3B!5'0P[}


Try it online!

)**     # Map ord
m{      # Map
3B!    # To base 3
5'0P[  # Pad to length 5 using "0"s
}


# APL+WIN, 22 bytes

Prompts for ASCII string. Index origin = 0

(⍕¨(⊂5⍴3)⊤¨⎕av⍳⎕)~¨' '


Most of the bytes are taken by formatting the output.

# Husk, 11 bytes

m(↑_5ṁsΘB3c


Try it online!

5 bytes (m(B3c) to calculate the base-3 representation of each ASCII character, but then 6 more bytes to format the output: prepend a zero (Θ), get string representation of digits (s), flatten together (ṁ), and take the last 5 elements (↑_5).

If it's acceptable for the base-3 digits to be space-separated (and the groups to be newline-separated), then we could do it in 10 bytes: m(w↑_5ΘB3c.
If we insist on space-separating the non-separated base-3 digits (exactly as in the example), it'll cost 12 bytes: wm(↑_5ṁsΘB3c.

# Haskell, 72 64 62 bytes

unwords.map(\c->show.(mod3).div(fromEnum c)=<<[81,27,9,3,1])


Try it online!

• Saved 8+2 Bytes thanks to @ovs suggestions.

Couldn't find any golfy way for the list of powers of 3: tried (3^)<$>[4,3..0] with no gains. • concatMap show$ can be shortened to show=<<.
– ovs
Feb 21 at 7:57
• Now you can combine =<< and <\$> to a single =<<.
– ovs
Feb 21 at 9:41
• @ovs thanks for walking me through the golfing process, so much appreciated Feb 21 at 10:19

# C (gcc), 72 bytes

i;f(char*s){for(;*s;++s,putchar(32))for(i=243;i/=3;)putchar(48+*s/i%3);}


Try it online!

• Suggest s+=printf(" ") instead of s++,putchar(32) Feb 21 at 22:31

# Pip, 15 bytes

S3E5+A_TB3MaJ:s


Attempt This Online!

Or, using the -s flag to do the output formatting, 12 bytes:

S3E5+A_TB3Ma


Attempt This Online!

### Explanation

Pip doesn't have any padding builtins as of this writing, so we do the following instead: Add $$\3^5\$$ to each codepoint; convert to base 3, resulting in a 6-digit number that always has a leading 1; and slice off the first digit.

S3E5+A_TB3MaJ:s
a     ; First command-line argument
M      ; Map this function to each of its characters:
A_          ;   ASCII code of the character
3E5+            ;   Add 3 to the 5th power
TB3       ;   Convert to base 3
S                ;   Suffix containing all but the first character
J:   ; Join the resulting list on
s  ; Space


# 05AB1E (legacy), 9 bytes

Ç3Bí0ζøí»


Output is newline delimited.

Try it online.

Explanation:

Uses the legacy version of 05AB1E because it can zip/transpose on list of strings, whereas the new 05AB1E version requires a matrix of characters. This would be 10 bytes in the new version by replacing B with в and adding a J (join) before the ». If any amount of leading 0s is valid, this could be 9 bytes as well in the new version of 05AB1E with Ç3BZ°+€¦» or Ç3BZj»ð0:.

Ç          # Convert the (implicit) input-string to a list of codepoint integers
3B        # Convert each integer to a base-3 string
í       # Reverse each string
ζ     # Zip/transpose; swapping rows/columns,
0      # using a 0 as trailing filler for unequal length rows
ø    # Zip/transpose back
í   # Reverse each string back
»  # Join the strings with newline delimiter
# (after which the result is output implicitly)


# Java (JDK), 80 bytes

s->s.chars().forEach(c->System.out.printf("%05d ",new Long(Long.toString(c,3))))


Try it online!

• Use (deprecated) new Long(String) instead of Long.valueOf(String) to save 4 more bytes Feb 25 at 18:00

# APL, 21 Chars, 39 Bytes

{∊6↑¨,⌿⍕¨(5⍴3)⊤⎕UCS⍵}


(5⍴3)⊤⎕UCS⍵ converts input to base 3 ASCII code in five digits.

,⌿⍕¨ converts the digits to characters and joins them together.

6↑¨ pads space in between (also results in a trailing space) and ∊ builds the final output.

Try it online!