Aliens have settled on earth and strangely enough, their alphabet is the exact same as ours. Their language is also very similar to ours with some very distinct and easy to compute differences.


Take a string and output the alien's language equivalent. The translation works as such:

Swap all the vowels in the word with the corresponding:

  Vowel |   With
   a    |   obo
   e    |   unu
   i    |   ini
   o    |   api
   u    |   iki

You may also write another translator to translate Alien->English, this is optional however.


Input: Shaun
Output: Shoboikin

Input: Java
Output: Jobovobo

Input: Hello, World!
Output: Hunullapi, Wapirld!

If the vowel is capitalized then you capitalize the first letter..

Input: Alan
Output: Obolobon

Input: Australia
Output: Oboikistroboliniobo


  • Standard loopholes apply
  • Must work for text that contains new lines
  • You can either write a function, lambda, or full program

    Capingrobotikilobotiniapins apin wrinitining thunu runuvunursunu trobonslobotapir!

  • \$\begingroup\$ I'm not sure what You may also write another translator to translate Alien->English is supposed to mean. Can we write the reverse translator instead of the regular one? \$\endgroup\$ – Dennis Sep 16 '16 at 15:22
  • 4
    \$\begingroup\$ Maybe it's just me, but it's not obvious to me that also carries this meaning here. Anyway, I'm not sure how this is a rule if it's not part of the actual task. \$\endgroup\$ – Dennis Sep 16 '16 at 15:55
  • \$\begingroup\$ @Dennis You're being a bit punudobontinic, but I've edited it to make it clearer. \$\endgroup\$ – Shaun Wild Sep 16 '16 at 16:14
  • 2
    \$\begingroup\$ Why the requirement for newlines? In my opinion, this is unnecessary and doesn't add anything to the main point of the challenge. \$\endgroup\$ – Adnan Sep 16 '16 at 16:53
  • 1
    \$\begingroup\$ Can the input contain any ASCII character or only a subset. E.g., will there ever be numbers in the input? \$\endgroup\$ – Riley Sep 16 '16 at 19:05

26 Answers 26


Haskell, 100 91 bytes

(>>= \x->last$[x]:[y|(z:y)<-words"aobo eunu iini oapi uiki AObo EUnu IIni OApi UIki",z==x])
  • 5
    \$\begingroup\$ Hoboskunull surely \$\endgroup\$ – jk. Sep 16 '16 at 14:32

TI-Basic, 173 + 59 + 148 = 380 bytes

Hopefully the aliens use TI-83/84 calculators ;)

Main Program, 173 bytes

BONUS: Keep second or third line depending on whether your want a normal or reverse translator.

"@a~obo@A~Obo@e~unu@E~Unu@i~ini@I~Ini@o~api@O~Api@u~iki@U~Iki@→Str2    <-- English to Alien
"@obo~a@Obo~A@unu~e@Unu~E@ini~i@Ini~I@api~o@Api~O@iki~u@Iki~U@→Str2    <-- Alien to English
If "@"=sub(Str2,I-1,1

Subprogram (prgmQ), 59 bytes:

Repeat Str9=Ans+Str8

Subprogram (prgmR), 148 bytes:

If X

P.S. ~ represents token 0x81 and @ represents token 0x7F, learn more here.

P.P.S. Part of why these programs have a high byte count is because sub(, inString(, length(, and all lowercase letters are two bytes each...

  • \$\begingroup\$ I think you mixed up prgmR and prgmQ in your code headlines once? \$\endgroup\$ – Byte Commander Sep 17 '16 at 0:01
  • \$\begingroup\$ Yes, thanks for catching that @ByteCommander :) \$\endgroup\$ – Timtech Sep 17 '16 at 13:31

Perl, 56 bytes

Includes +1 for -p

Give input on STDIN


#!/usr/bin/perl -p

Works as shown, but replace the \xXX escapes by the actual character to get the claimed score

  • 1
    \$\begingroup\$ +1 Upvoted just for the Alien avatar. Just kidding, the solution is nice, also. \$\endgroup\$ – Chaotic Sep 16 '16 at 22:24
  • 1
    \$\begingroup\$ Jesus christ.. Perl at its best, ladies and gents. \$\endgroup\$ – Priidu Neemre Sep 17 '16 at 14:05

sed 89

  • \$\begingroup\$ Does this work for input that contains newlines? \$\endgroup\$ – Jordan Sep 16 '16 at 16:12
  • \$\begingroup\$ @Jordan It does. sed reads "one line at a time". So it will process everything up to the first newline, print that, print a newline, then start over if there is more text. \$\endgroup\$ – Riley Sep 16 '16 at 16:20
  • \$\begingroup\$ Ah, of course. 👍🏻 \$\endgroup\$ – Jordan Sep 16 '16 at 16:25
  • \$\begingroup\$ @Jordan That wasn't a rule when I wrote this, but it ended up working anyway. \$\endgroup\$ – Riley Sep 16 '16 at 16:26

Python, 99 95 93 bytes

lambda s:"".join(("ouiaiOUIAI bnnpkbnnpk ouiiiouiii"+c)["aeiouAEIOU".find(c)::11] for c in s)

On ideone.com...

Pretty simple. Just take the index we find each character at in the vowel list and use it to pull the three characters we need. If it's not found, .find() returns -1 so just stick the current character on the end of the string. The spaces are necessary so any letter "a" doesn't include the added c. The translated vowels are grouped by letter order (the first letter of every translation, then the second, then the third).

  • \$\begingroup\$ Wow, nice creative approach. I'm impressed :) \$\endgroup\$ – Byte Commander Sep 17 '16 at 0:03
  • 1
    \$\begingroup\$ You can remove the space in ["aeiouAEIOU".find(c)::11] for \$\endgroup\$ – acrolith Sep 21 '16 at 22:30

05AB1E, 28 27 20 bytes


Try it online!


žÀ                    # the string "aeiouAEIOU"
  .•₅%~≠#ùÛãú•        # the string "obounuiniapiiki"
              3ô      # split in pieces of 3
                D™«   # concatenate with a title-case copy
                   ‡  # transliterate
  • 2
    \$\begingroup\$ Ini lapivunu gapilfining! \$\endgroup\$ – Shaun Wild Sep 16 '16 at 11:57
  • \$\begingroup\$ @BasicallyAlanTuring: Took me way too long to translate that in my head. I think I need a reverse translator :P \$\endgroup\$ – Emigna Sep 16 '16 at 11:59
  • 2
    \$\begingroup\$ Go for it, shouldn't be too hard :P \$\endgroup\$ – Shaun Wild Sep 16 '16 at 12:03
  • \$\begingroup\$ Scary, I think it says I love golf. \$\endgroup\$ – datagod Sep 16 '16 at 14:58
  • \$\begingroup\$ I've changed my question which makes you answer invalid. This must work with new lines \$\endgroup\$ – Shaun Wild Sep 16 '16 at 15:31

PHP , 91 Bytes


Python, 129 bytes

lambda s:"".join([str,str.capitalize][ord(l)<91]({"a":"obo","e":"unu","i":"ini","o":"api","u":"iki"}.get(l.lower(),l))for l in s)

See it running on ideone.com

Here's a more nicely formatted version:

lambda s: \
        [str, str.capitalize][ord(l) < 91](
            {"a":"obo", "e":"unu", "i":"ini", "o":"api", "u":"iki"}
            .get(l.lower(), l)
    for l in s)

The most interesting parts are { ... }.get(l.lower(), l) which tries to look up the letter stored in l converted to lower case in the dictionary and either returns the translated version (if found), or else the original letter,
and [str, str.capitalize][ord(l) < 91]( ... ) which checks whether the original letter was a capital letter (ASCII code point lower than 91) and then either calls the str() function with the letter as argument (if it wasn't a capital letter, does nothing) or the str.capitalize() function (converts the first letter of the argument string to upper case).


C (gcc), 150 141 136 134 bytes

a;i;e(char*n){for(char*v=" AEIOUIAI",*t;i=*n++;printf(&a))t=index(v,i-i/96*32),a=t?t-v:0,a=a?v[a+3]|L" 潢畮楮楰楫"[a]<<8|i&32:i;}

Try it online!

Based on the answer by @algmyr and -8 thanks to @ASCII-only

Less golfed version

  for(char*v=" AEIOUIAI",*t;i=*n++;printf(&a))
    a=a?v[a+3]|L" 潢畮楮楰楫"[a]<<8|i&32:i;
  • \$\begingroup\$ 149? a;l;i;e(char*n){for(char*v=" AEIOU",*t;i=*n++;printf("%c%c%c"+4*!a,(a?" OUIAI"[a]:i)|i&32," bnnpk"[a]," ouiii"[t=index(v,i-32*l),a=t?t-v:0]))l=i>96;} \$\endgroup\$ – ASCII-only Feb 25 '19 at 1:58
  • \$\begingroup\$ maybe also 149: a;l;i;e(char*n){for(char*v="AEIOU",*t;i=*n++;printf("%c%c%c"+4*!a,(a?" OUIAI"[a]:i)|i&32," bnnpk"[a]," ouiii"[t=index(v,i&95),a=t&&t-v<5?t-v+1:0]));} \$\endgroup\$ – ASCII-only Feb 25 '19 at 2:01
  • \$\begingroup\$ 144: a;l;i;e(char*n){for(char*v=" AEIOU",*t;i=*n++;)printf("%c%c%c"+4*!a,a?" OUIAI"[a]|i&32:i," bnnpk"[a]," ouiii"[t=index(v,i-i/96*32),a=t?t-v:0]);} \$\endgroup\$ – ASCII-only Feb 25 '19 at 2:02

Batch, 215 bytes

@echo off
set s=
if "%t%"=="" echo(%s%&exit/b
set c=%t:~0,1%
for %%a in (obo.a unu.e ini.i api.o iki.u Obo.A Unu.E Ini.I Api.O Iki.U)do if .%c%==%%~xa set c=%%~na
set s=%s%%c%
set t=%t:~1%
goto l

Takes input on STDIN. Processing character-by-character has the convenience of being case-sensitive.

  • \$\begingroup\$ Batch is just the worst tool for everything, isn't it? (Well, at least you beat TI-Basic :) Nice seeing a codegolf in Batch, by the way! \$\endgroup\$ – yyny Sep 17 '16 at 0:30

Pyth, 42 bytes


A program that takes input on STDIN and prints the output.

Try it online

How it works

#sXw"aeiouAEIOU"+Jc"obounuiniapiiki"3mrd3J  Program.
#                                           Loop until error statement:
   w                                         Get w, the next line of the input
                   "obounuiniapiiki"         Yield string literal "obounuiniapiiki"
                  c                 3        Split that into groups of three characters
                 J                           Assign that to J and yield J
                                     mrd3J   Map title case over J
                +                            Merge the lower and title groups
    "aeiouAEIOU"                             Yield string literal "aeiouAEIOU"
  X                                          Translate w from that to the three-character
 s                                           Concatenate that
                                             Implicitly print

C, 167 bytes

I really didn't want to break my habit of always doing main functions when coding C, but this is substantially shorter than the version with a main and this way I got another letter to spell what I wanted!




        i = *n++;  /* Get char and advance */
        l = i>90,  /* Is lowercase? */
        i -= 32*l, /* Make uppercase */

        /* Is 1,2,3,4,5 depeding on the vowel and 0 for no vowel */
        a = !(i-65) + 2*!(i-69) + 3*!(i-73) + 4*!(i-79) + 5*!(i-85),

        printf(a?"%c%c%c":"%c",        /* Print 1 or 3 chars? */
               (a?"HOUIAI"[a]:i)+l*32, /* Print appropriate char+case */
                  "ibnnpk"[a],            /* Print appropriate char */
                  "!ouiii"[a]));          /* Print appropriate char */

There is something special about C and how horrible you can be with pointers and such.

  • \$\begingroup\$ 151 bytes \$\endgroup\$ – ceilingcat Feb 24 '19 at 13:41
  • \$\begingroup\$ @ceilingcat I'd say post your answer on its own. It's diverged enough to deserve its own answer. :) \$\endgroup\$ – algmyr Feb 24 '19 at 13:47

Retina, 60 bytes

Byte count assumes ISO 8859-1 encoding.


Try it online!


Javascript (ES6), 94 93 92 bytes


Saved 1 byte thanks to edc65
Saved 1 byte thanks to Neil


let f =

function translate() {
  document.getElementById("o").value = f(document.getElementById("i").value);
<input id="i" size=80 oninput="translate()" value="Hello, World!"><br><input id="o" size=80 disabled>

  • 1
    \$\begingroup\$ To check the return value of .indexOf and .search use ~ instead of <0 \$\endgroup\$ – edc65 Sep 16 '16 at 14:33
  • 1
    \$\begingroup\$ I looked to see what would happen if you only replaced vowels, and I originally got s=>s.replace(/[aeiou]/gi,c=>"ouiaiOUIAI"[n="aeiouAEIOU".indexOf(c)]+"bnnpk"[n%=5]+"ouiii"[n]) which is still 93 bytes. But since c is now known to be a vowel you can now use search instead of indexOf to save a byte! \$\endgroup\$ – Neil Sep 17 '16 at 10:13
  • \$\begingroup\$ @Neil - Nice! I tried both, actually, but didn't think about combining them. \$\endgroup\$ – Arnauld Sep 17 '16 at 10:33

Java 8, 172 bytes

String f(String s){String v="AEIOUaeiou",r="OboUnuIniApiIkiobounuiniapiiki",o="";for(char c:s.toCharArray()){int n=v.indexOf(c);o+=n>-1?r.substring(n*3,n*3+3):c;}return o;}


String f(String s){
    String v="AEIOUaeiou",r="OboUnuIniApiIkiobounuiniapiiki",o="";
    for(char c:s.toCharArray()){
        int n=v.indexOf(c);
    return o;

And Alien back to English (171 bytes):

String g(String s){String[] v="AEIOUaeiou".split(""),r="Obo Unu Ini Api Iki obo unu ini api iki".split(" ");for(int i=0;i<v.length;i++)s=s.replaceAll(r[i],v[i]);return s;}


String g(String s){
    String[] v="AEIOUaeiou".split(""),r="Obo Unu Ini Api Iki obo unu ini api iki".split(" ");
    for(int i=0;i<v.length;i++)s=s.replaceAll(r[i],v[i]);
    return s;

Tcl, 75 bytes

String to be translated is in the variable s.

string map {A Obo a obo E Unu e unu I Ini i ini O Api o api U Iki u iki} $s

Mathematica, 128 bytes


Not sure whether a shorter program can be obtained by using IgnoreCase->True together with a case check.


C 178 bytes

  • 1
    \$\begingroup\$ 153 bytes \$\endgroup\$ – ceilingcat May 3 '19 at 17:34
  • \$\begingroup\$ @ceilingcat &c can be ok if it save number as byte1 byte2 byte3... For example 255 in memory as ff 00 00 00 but if there is the other endian for 255 we have 00 00 00 ff and print the void string ... \$\endgroup\$ – user58988 May 11 '19 at 18:33

C, 163 162 159 bytes

  • \$\begingroup\$ putting char*t="aeiou"; into for loop saves 1 byte \$\endgroup\$ – Mukul Kumar May 3 '19 at 2:21
  • \$\begingroup\$ 144 bytes \$\endgroup\$ – ceilingcat May 3 '19 at 18:16

C#, 133 121 bytes

s=>{int i;return string.Concat(s.Select(c=>(i ="AIUEOaiueo".IndexOf(c))>-1?"OboIniIkiUnuApioboiniikiunuapi".Substring(i*3,3):c+""));}

Edit (thanks to milk)

thank you :) I actually know this overload but somehow completely forgot it when writing this..

  • \$\begingroup\$ You can use the Select(char, int) overload so you don't need to declare i and can put it all in one line. s=>string.Concat(s.Select((c,i)=>(i="AIUEOaiueo".IndexOf(c))>-1?"OboIniIkiUnuApioboiniikiunuapi".Substring(i*3,3):c+"")); \$\endgroup\$ – milk Sep 16 '16 at 23:52

C, 207 202 bytes (thanks to Cyoce)

#include <stdio.h>
#define r(c,t) case c:printf(t);continue;
int main(){int c;while(~(c=getchar())){switch(c){r('a',"obo")r('e',"unu")r('i',"ini")r('o',"api")r('u',"iki")default:putchar(c);}}return 0;}

1) I hate to omit type before any kind of declarations

2) I don't really like to put unusable code (without main() function)


c89 cg.c -o cg; echo "Testing" | ./cg
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Martin Ender Sep 18 '16 at 14:12
  • \$\begingroup\$ @MartinEnder, that's unexpected... but thank you :) \$\endgroup\$ – Xdevelnet Sep 18 '16 at 17:51
  • \$\begingroup\$ (c=getchar())!= EOF can become ~(c=getchar()) \$\endgroup\$ – Cyoce Sep 20 '16 at 1:00
  • \$\begingroup\$ 143 bytes \$\endgroup\$ – ceilingcat May 6 '19 at 23:25

Swift 2.2 196 bytes



var r = ["a":"obo","e":"unu","i":"ini","o":"api","u":"iki"];var q={(s:String) in var o = "";for var i in s.lowercaseString.characters{o += r[String(i)] != nil ? r[String(i)]!:String(i)};print(o);}


var r = ["a":"obo","e":"unu","i":"ini","o":"api","u":"iki"]
var q={(s:String) in
    var o = ""
    for var i in s.lowercaseString.characters {
        o += r[String(i)] != nil ? r[String(i)]!:String(i)
  • \$\begingroup\$ Are the spaces in var r = [ necessary? \$\endgroup\$ – Cyoce Sep 20 '16 at 1:05
  • \$\begingroup\$ Yeah in the playgrounds app if you don't put a space in between an assignment it give you an error and tells you to add spaces. Swift is probably one of the worst languages to golf with but I thought it would be fun to try. \$\endgroup\$ – Danwakeem Sep 20 '16 at 1:40
  • \$\begingroup\$ And it was interesting it didn't give me that error when I was assigning a variable to a closure. Hence the shrugging man \$\endgroup\$ – Danwakeem Sep 20 '16 at 1:42
  • \$\begingroup\$ yeah I noticed that too. That's why I was confused. \$\endgroup\$ – Cyoce Sep 20 '16 at 5:05

Perl 6,  84  82 bytes

{my%o=<a obo e unu i ini o api u iki>;S:i:g[<{%o.keys}>]=%o{$/.lc}.samecase($/~'a')}
{my%o=<a obo e unu i ini o api u iki>;S:i:g[<[aeiou]>]=%o{$/.lc}.samecase($/~'a')}


# bare block lambda with implicit parameter 「$_」
  # create the mapping
  my %v = <a obo e unu i ini o api u iki>;

  # replace vowels in 「$_」

  = # replace them with:

  %v{ $/.lc }
  # change it to be the same case as what was matched, and a lowercase letter
  .samecase( $/ ~ 'a' )


my &english-to-alien = {my%o=<a obo e unu i ini o api u iki>;S:i:g[<[aeiou]>]=%o{$/.lc}.samecase($/~'a')}

say english-to-alien 'Australia'; # Oboikistroboliniobo

C - 192 bytes

(newlines added for clarity)

int c,j,b;main(){

Just lookup tables and a boolean switch.

Lookup each letter in table (string) of vowels; if found, then modify it according to the rule in table s. Print each character followed by a string: if a vowel was found, print the character modified by the value in s followed by the rest of the syllable stored in table f; if a vowel was not found, print the original character and an empty string.


Ruby, 102 93 91 88 78 bytes



Execute the line like ruby -pe "gsub(/[#{b='aeiouAEIOU'}]/){'obounuiniapiikiOboUnuIniApiIki'[b.index($&)*3,3]}", next up type, for example, Australia it should output: Oboikistroboliniobo.

It's pretty straightforward, replace all vowels with a substring based on the index of the to-be replaced vowel in (b), times 3 and the next 3 characters in the translation string.

  • 1
    \$\begingroup\$ I suspect the leading and trailing quotation marks (and internal escapes if the input has quotation marks) in the output might disqualify this. Anyway, you can save two bytes by moving the assignment of b into the Regexp (/[#{b=...}/). \$\endgroup\$ – Jordan Sep 20 '16 at 4:03
  • 1
    \$\begingroup\$ I think the space p $* is unnecessary \$\endgroup\$ – Cyoce Sep 20 '16 at 5:09
  • 1
    \$\begingroup\$ Use the -p flag to save additional bytes. ruby -pe 'gsub(/[#{b="aeiouAEIOU"}]/){"obounuiniapiikiOboUnuIniApiIki"[b.index($&)*3,3]}' \$\endgroup\$ – Value Ink Sep 20 '16 at 7:30
  • \$\begingroup\$ I count 78 + 2 (-pe). How do you get 71? \$\endgroup\$ – Not that Charles Sep 21 '16 at 19:36
  • \$\begingroup\$ @NotthatCharles do the characters needed for execution really matter in this case? I just didn't count them. \$\endgroup\$ – Biketire Sep 27 '16 at 10:02

TI-BASIC, 201 197 195 bytes

Ans+" →Str1:"AEIOUaeiou→Str2:"OUIAIouiai→Str3:"bonunipiki→Str4:1→X:While X<length(Str1:inString(Str2,sub(Str1,X,1→A:5fPart(.2A→B:If A:sub(Str1,1,X-1)+sub(Str3,A,1)+sub(Str4,2B-1,2)+sub(Str1,X+1,length(Str1)-X→Str1:X+1+2(A>0→X:End:sub(Str1,1,length(Str1)-1

To think that I'd find another TI-BASIC answer here!

Anyway, the input is an English string in Ans.
The output is the translated string.



(Newlines added for readability. Multiple lines from the same line will be denoted with a : in the following code block.)

Ans+" →Str1                     ;append a space to the input string and store the result
                                ; in "Str1"
"AEIOUaeiou→Str2                ;store the upper- and lowercase vowels in "Str2"
"OUIAIouiai→Str3                ;store the beginning letter of each corresponding translated
                                ; vowel in "Str3"
"bonunipiki→Str4                ;store the remaining letters of each translated vowel
                                ; in "Str4"
1→X                             ;store 1 in "X"
While X<length(Str1             ;loop until all English letters have been checked
inString(Str2,sub(Str1,X,1→A    ;get the current letter and store its index in "Str2"
                                ; into "A"
5fPart(.2A→B                    ;get which translated vowel end should be used
                                ; B ranges from 1 to 5
If A                            ;if the current letter is a vowel
sub(Str1,1,X-1)                 ;extract the substring of the input before the
                                ; current letter
: +sub(Str3,A,1)                ;append the translated vowel start
: +sub(Str4,2B-1,2)             ;append the translated vowel end
: +sub(Str1,X+1,length(Str1)-X  ;append the remaining substring of the input
: →Str1                         ;store the result of these concatenations into "Str1"
X+1+2(A>0→X                     ;check if A>0 (if the current letter was a vowel)
                                ; if true, increment "X" by three
                                ; if false, increment "X" by one
sub(Str1,1,length(Str1)-1       ;remove the trailing space and store the result in "Ans"
                                ;implicit print of "Ans"


  • TI-BASIC is a tokenized language. Character count does not equal byte count.

  • Lowercase letters in TI-BASIC are two bytes each.


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.