# Decode Baby-talk!

When babies open their mouths, they're not just spewing gibberish. They're actually talking in a highly advanced, adult-proof cipher...

# The Baby-talk Cipher

When a baby talks, it could look something like gogooa gagooook aagaaoooy Each single-space separated section represents a character (so the example above represents 3 characters).

To decipher a section, we must count number of As and Os it contains. However, we only count those which are adjacent to another vowel. For example, the A in 'gag' would not count, but both the A and O in 'gaog' would.

Counting the example above would look like this:

Section    | Num Os | Num As

gogooa     | 2      | 1
gagooook   | 4      | 0
aagaaoooy  | 3      | 4


We then use these values to convert the input into plaintext on a Polybius square. This is a 5x5 representation of the English alphabet, omitting 'J' (please note that, in baby-talk, 0-counting rules apply to the table):

  0 1 2 3 4
0 A B C D E
1 F G H I K
2 L M N O P
3 Q R S T U
4 V W X Y Z


Using the number of Os as the column, and number of As as the row, we find which character each section represents:

Section    | Num Os | Num As | Character

gogooa     | 2      | 1      | (2,1) -> H
gagooook   | 4      | 0      | (4,0) -> E
aagaaoooy  | 3      | 4      | (3,4) -> Y


Which tells us that the baby was just saying "HEY".

Notes:
- If a section representing a character has more than 4 As or Os, ignore the extras, because 4 is the maximum value on the table. - For this task, Y is not a vowel - only A, E, I, O and U.

# The Challenge

Your task is to create a full program which takes one input, a word in baby-speak, and prints it in plaintext.

• Your program must be able to take input in uppercase, lowercase, and a mix of both.
• The input will only contain ASCII alphabet letters (A-Z and a-z), with single spaces to seperate the baby words.
• The output text can be in any case.
• You should the take the input from STDIN and print the plaintext on STDOUT. If your language does not have these, use the nearest equivalent.
• This is , so the shortest code in bytes wins - but any solution is welcome.

# Test Cases

'GLOOG KAKAAOOO ARGOOO OOOOOGUGUU' -> CODE
'oaka pooopaa gaau augu' -> GOLF
'Aoao U oOOAoa oaoAoo aoAoAOa' -> NAPPY
'GUG gAGaA gOougOou' -> ALE
'OOaGOG GoGOOoGoU gAA bLAA GOUGoOUgAIGAI' -> HELLO

• 'GUG gAGaA gOougOou' -> 'ALE' Babies drink ale? :D – Cows quack Nov 1 '16 at 7:31
• only the finest :D @KritixiLithos – FlipTack Nov 1 '16 at 8:08
• The case requirement seems unnecessary, right? All you're doing is adding a .toUpperCase() or similar function call, not an actually stimulating challenge – MayorMonty Nov 1 '16 at 12:45
• How does gogooa have 2 o's? And how does gagooook have 0 a's? – Magic Octopus Urn Nov 1 '16 at 13:57
• Actually, @EriktheGolfer , that's FAG :P – FlipTack Nov 6 '16 at 12:13

# 05AB1E, 46 bytes

lð¡vyžNvyð:}ð¡D€g1›ÏJ©'a¢4‚W5*®'o¢4‚Ws\+A'j-è?


Try it online!

Explanation in steps

1. split on spaces to form words
2. replace konsonants in words with spaces
3. split words on spaces to form groups of vowels
4. remove vowel groups with a length shorter than 2
5. get min of count(a) and 4, multiply by 5
6. get min of count(o) and 4
8. get letter at that index of alphabet (excluding "j")
• Good job, congrats on winning – FlipTack Nov 7 '16 at 16:14
• I like the approach of splitting by consonants, I didn't think of that – FlipTack Nov 7 '16 at 17:00

# Perl, 82 bytes

Includes +1 for -a

Give input on STDIN:

perl -M5.010 baby.pl <<< "OOaGOG GoGOOoGoU gAA bLAA GOUGoOUgAIGAI"


baby.pl:

#!/usr/bin/perl -a
say map{$A=$O=$_=uc;y/AEIOU/@/c;s/(\B.|.\B)/$$1+=$$1<4/eg;(A..I,K..Z)[5*$A+$O]}@F  This assumes a recent enough perl version where -a implies -n. If your perl is too old you will need to add an explicit -n option. It also assumes babies can't say general ASCII strings that start with digits like 1 this will not work • that's a correct assumption. I'll make sure to specify that in the question – FlipTack Nov 1 '16 at 20:33 # brainfuck, 656 bytes +[[>>>,[>++++[<-------->-]]<]<<[>]<-[+[<+>>+<-]----[>>+<<----]>>+[<[-<]<[>]>>-]-<[[-]>+<]>[[-[->]<<+>]<->>>]<<<[>>>+<<<-]<<-]>>>>>[[<+>>+<-]----[>-<----]>--[----<]<[>]>[----<]<[>]>[------<]<[>]>[------<]<[>]><+>[[-]<->]>>]<<<[>->]<[<]>[>[<<<<<+>>>>>>+<-]<<<<]<[-]>>>>[<[>[>+<-]<-]>[-]->[<+>-]>>]<<<[-<----[>-<----]>[>+>+<<-]+>[<->[-]<]<[<]>[[<<<]<+>>>>[>>>]<<<-]>+>--------------[<->[-]]<[-<<<<[<<<]>+>>[>>>]>]<<<<]<[<+<+>>-]>++++[<<[->]>[<]>-]+<<[[-]++++<[-]>>]>[<]<<[>+<-]>>+>->[>+>+<<-]<++++[>>[-<]<[>]<-]>>[[-]++++>[-]]<<<[>]<->>>>[<+>-]<[<<<+>>>-]<<<<[>+++++<-]>[>+>+<<-]<++++++++[>>[-<]<[>]<-]>>[[-]>+<]----[>+<----]>++.[-]+>>>,[<++++[>--------<-]]>]  This was a pretty good way to kill a couple of hours. Requires a brainfuck interpreter that uses 8-bit wrapping cells, allows you to go left from cell 0 and returns 0 if , is used when stdin is empty. In my experience, these are the most common settings. This program does not consider Y a vowel, but if OP wants it to it's an easy fix. It seems like writing this would be a daunting task but if you have some familiarity with the language there's nothing surprising or new in the code. Standard brainfuck tactics: Read the input but make sure you leave a couple of empty cells between each byte, use those empty cells to store data about the input, use the data you stored to decide how to transform it and spit something out at the end. In this case it was get the input, set it all to uppercase, figure out which cells are vowels, throw that information away after using it to determine which cells are next to vowels, set everything that isn't next to a vowel to some value that will never be relevant so they're not in the way later, and you're basically done. From there you just have to count your As and Os, multiply As by 5 and add the number of Os, special case anything above 8 to avoid J and output. I did choose to handle this one word at a time, rather than taking the whole input at once, so I had to set up the part of the code that reads stdin to break at 0 or 32, but that's not too big of a problem (just wrap the subtraction by 32 in a conditional so it doesn't happen if the value is already 0, then correct for any < or > instructions you missed later). I don't know how helpful it will be because I wrote it mostly to keep my thoughts straight rather than as a real explanation, but here's the code with my comments and its original indentation: +[[>>>,[>++++[<-------->-]]<]get an entire word of input each character lowered by 32 two empty cells between characters stops when reaching a space or null byte any lowercase letters have become uppercase; anything with a value below 65 used to be an uppercase character; fix it <<[>]<-[+ for each character until hitting 1: [<+>>+<-] make a backup subtract 64 from the character but stop if it hits 0 ----[>>+<<----]>>+ generate the number 64 [ 64 times: <[ if the character is not 0: - subtract 1 < go to a guaranteed 0 cell to break the loop ] we're either on the character or to the left of it; sync up <[>] >>-] -<[[-]>+<]> logical NOT of character [ if logical NOT returns true: [-[->]<<+>]<- add 32 to backup of character >>>] <<<[>>>+<<<-] move copy over to make room <<-] >>>>>[ for each character: [<+>>+<-] make copies ----[>-<----]>-- check if it's A [----<]<[>]> check if it's E [----<]<[>]> check if it's I [------<]<[>]> check if it's O [------<]<[>]> check if it's U IF YOU NEED TO ADD Y; THIS IS THE PLACE <+>[[-]<->] logical NOT to complete vowel check >>] <<<[ if the last char is a vowel; prevent a side effect >-> ] <[<]>[ for each character: >[ if it's a vowel: <<<<<+>>>>>>+<- leave a flag to the left and right to show that a ] vowel is adjacent <<<<] <[-]> clean up a side effect left behind if first char is vowel >>>[ for each char: <[ if it's adjacent to a vowel: >[>+<-]<- move it to the side ] >[-]- otherwise; destroy it >[<+>-] move backup over if it exists (subtracting 1) >>] all characters without a vowel beside them have been set to 255 all characters with a vowel beside them are set to itself minus 1 notable charaters are: 'A' minus 1 = 64 'O' minus 1 = 78 <<<[ for each character: -<----[>-<----] subtract 64 >[>+>+<<-] make a copy +>[<->[-]<]<[<]> logical NOT [[<<<]<+>>>>[>>>]<<<-] if NOT returns true; record an A >+>-------------- subtract 14 from backup [<->[-]]< logical NOT [-<<<<[<<<]>+>>[>>>]>] if NOT returns true; record an O <<<<] <[<+<+>>-] make a backup of A count >++++[<<[->]>[<]>-] subtract 4 but don't go below 0 +<<[ if the char was greater than 3: [-]++++<[-]>> put 4 there ] >[<] resynchronise <<[>+<-] if there were fewer than 4 As put the number back same thing but for the O count >>+>->[>+>+<<-] make a backup of O count <++++[>>[-<]<[>]<-] subtract 4 but don't go below 0 >>[ if the char was greater than 3: [-]++++>[-] put 4 there ] <<<[>] resynchronise <->>>>[<+>-] if there were fewer than 4 Os put the number back <[<<<+>>>-]<<<<[>+++++<-] A*5 plus B = index of character to output >[>+>+<<-] make a backup <++++++++[>>[-<]<[>]<-] subtract 8 but don't go below 0 >>[[-]>+<] if the result is nonzero it is late enough in the alphabet that it must be increased by 1 to exclude J as a possible output ----[>+<----]>++ add 65 to make it a letter .[-]+>>>, output and get new input [<++++[>--------<-]]> sub 32 if not 0 ]  • This is amazing... and yes, by vowels I meant a,e,i,o,u :) – FlipTack Nov 1 '16 at 19:56 # JavaScript (ES6), 145 bytes alert(prompt().replace(/\S+ ?/g,x=>(g=r=>(q=(x.match(/[aeiou]{2,}/gi)+"").split(r).length-1)>4?4:q,(g(/a/i)*5+g(/o/i)+10)*20/19|0).toString(36)))  Replaces each word (and the following space) with its corresponding letter. s.split .map().join is 3 bytes longer: alert(prompt().split .map(x=>(g=r=>(q=(x.match(/[aeiou]{2,}/gi)+"").split(r).length-1)>4?4:q,(g(/a/i)*5+g(/o/i)+10)*20/19|0).toString(36)).join)  • The challenge currently states that you should write "a full program which takes input [from STDIN] and prints it [to STDOUT]." This means that as currently written function answers aren't allowed. – CAD97 Nov 1 '16 at 16:11 • Nice submission, but as CAD said, it has to be a full program. I'm not very familiar with JavaScript but I think prompt and alert are the best equivalents to STDIN/OUT, right? – FlipTack Nov 1 '16 at 20:14 • @Flp.Tkc Yeah, unless you're using Node or some other environment. I'll update my code. – ETHproductions Nov 1 '16 at 20:15 • the question does say or the nearest equivalent. For js in the browser, a prompt and alert are close enough – Fred Stark Nov 7 '16 at 7:35 # Perl, 159 +1 = 160 bytes +1 byte for -n flag. Whitespace is not part of the code and is only provided for readability. for(split$",lc){
$b=0; @a=sort/([ao](?=[aeiou])|(?<=[aeiou])[ao])/g;$b++until$b>$#a||$a[$b]eq o;
$c=($d=$#a-$b+1)>4?4:$d;$b=$b>4?4:$b;
print+(a..i,k..z)[5*$b+$c];
}


The code splits the input by spaces and converts each baby word to lowercase before proceeding. The regex finds all a or o vowels that are followed by another vowel, or are preceeded by a vowel, and sorts them, a's at the start, o's at the end, then finds the index of the first 'o'. If the remaining number of matches (aka, the number of 'a's) is greater than 4, then we care about 4 a's, and if there are more than 4 o's, we care about 4 o's. Then it pulls the appropriate letter out of the matrix and prints it, then moves onto the next baby word.

## Brainfuck, 283 bytes

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


Formatted:

,
[
[
<
[
>-
[
not a
>>>-<<<
----
[
not e
----
[
not i
>+<
------
[
not o
>-<
------
[
consonant
<[-]>
>>>[-]->>[-]<<<<<-
]
]
]
]
]
>[>>>>+<<<<-]> >+<
[
prev was vowel
>[>+<-]>>[>+<-]<<<-
]
<,<<[>>>+<<<-]
>
]
>+
[
<+>[-<<]
>[[-]+++++[<++++++>-]<+<]
>>>
]
<
]
>>[-]>+>>+
[
[-]
>[<+>-[<+>-[<+>-[<+>[-]]]]]<
<<
]
>->
[
>+<-
[
[>+<-]
>>+>
]
>
[
+>----[->]
]
]
+[-<+]
>>+++++++++++++[>+++++<-]
>.,
]


This works with or without a trailing newline in the input.

Try it online.

Each character is processed mod 32 (with control flow such that the code implementing the mod operation only occurs once in the program). This enables case insensitivity, as well as collapsing the space character and EOF into a single case. A trailing newline is treated the same as J, which doesn't affect the output.

Sketch of memory layout:

0 x C c y a A b B

where c is the input character, C is the char mod 32, x is whether it is a vowel, y is whether the previous char was a vowel, A and B are the counts of valid (next to vowels) a and o chars respectively, and a and b are their respective buffers that get copied or cleared depending on whether there is an adjacent vowel.

When a space or EOF is reached, some juggling is done to reduce counts greater than 4 and to skip the letter J, and then the decoded character is printed.

• this is very close to the java implementation in byte count ... hats off to you – hstde Nov 7 '16 at 8:36
• it's a crime that this has less points than my trivial solution that's over twice as long – undergroundmonorail Dec 2 '16 at 0:43
• @undergroundmonorail That makes me an accomplice! – Mitch Schwartz Dec 12 '16 at 18:04

# PHP, 163 bytes

<?php for(;$c=preg_replace('/(?<![AEIOU]).(?![AEIOU])/','',strtoupper($argv[++$i]));$j=min($d[79],4)+5*min($d[65],4),print range(A,Z)[$j+($j>8)])$d=count_chars($c);


<?php
for (
;
$c = preg_replace( '/(?<![AEIOU]).(?![AEIOU])/', '', strtoupper($argv[++$i]) );$j = min($d[79], 4) + 5 * min($d[65], 4),
print range(A, Z)[$j + ($j > 8)]
)
$d = count_chars($c);


Tests:

$php babytalk.php GLOOG KAKAAOOO ARGOOO OOOOOGUGUU CODE$ php babytalk.php oaka pooopaa gaau augu
GOLF
$php babytalk.php Aoao U oOOAoa oaoAoo aoAoAOa NAPPY$ php babytalk.php GUG gAGaA gOougOou
ALE
$php babytalk.php OOaGOG GoGOOoGoU gAA bLAA GOUGoOUgAIGAI HELLO  # Java 8, 272266251 249 bytes interface M{static void main(String[]i){String z="(?=[AEIOU])|(?<=[AEIOU])";for(String s:i[0].split(" ")){int a=s.split("(?i)A"+z+"A",-1).length-1,o=s.split("(?i)O"+z+"O",-1).length-1,t=(a>4?4:a)*5+(o>4?4:o);System.out.printf("%c",t>9?t+66:t+65);}}}  -6 bytes thanks to @Joba. -1 byte converting from Java 7 to 8, and 14 16 additional bytes saved by changing the print-part. Explanation: Try it here. interface M{ // Class: static void main(String[]i){ // Main method: String z="(?=[AEIOU])|(?<=[AEIOU])"; // Regex-part for look-ahead or look-behind of vowels for(String s:i[0].split(" ")){ // Loop over the program-arguments int a=s.split("(?i)A"+z+"A",-1).length-1, // The amount of A's with adjacent vowels o=s.split("(?i)O"+z+"O",-1).length-1, // The amount of O's with adjacent vowels t=(a>4?4:a) // If a is larger than 4, just take 4, else take a *5 // Multiply it by 5 +(o>4?4:o); // And add 4 if o is larger than 4, else take o System.out.printf("%c", // Print a character: t>9? // If t is larger than 9 (index of J) t+66 // Take character unicode (skipping J) : // Else: t+65); // Take character unicode (prior to J) } // End of loop } // End of main-method } // End of program  • The challenge currently states that you should write "a full program which takes input [from STDIN] and prints it [to STDOUT]." This means that as currently written function answers aren't allowed. – CAD97 Nov 1 '16 at 16:11 • @CAD97 Thanks, read past that somehow. I've edited my answer accordingly. – Kevin Cruijssen Nov 1 '16 at 18:02 • Instead of using the upper case string, add the case invariant regex flag (?i) at the beginning of the s.split – Joba Nov 7 '16 at 12:19 # Python 3, 163162157 146 bytes import re for W in input().upper().split():S=''.join(re.findall("[AEIOU]{2,}",W)).count;I=min(S('A'),4)*5+min(S('O'),4);print(end=chr(65+I+(I>9)))  Uses regex to find all string of vowels larger than 2, counts As and Os with maximum of 4, and then prints. ## APL, 60 {⎕A[a+9<a←5⊥+/¨'ao'∊⍨¨⊂⍵/⍨0(,∨,⍨)2∧/⍵∊'aeiou']}¨' '(≠⊂⊢)819⌶  Note that ⎕IO←0 and ⎕ML←3 Example: fn←{⎕A[a+9<a←5⊥+/¨'ao'∊⍨¨⊂⍵/⍨0(,∨,⍨)2∧/⍵∊'aeiou']}¨' '(≠⊂⊢)819⌶ fn 'Aoao U oOOAoa oaoAoo aoAoAOa' NAPPY  Works in Dyalog 15.0, since it's the version in which 819⌶ was introduced to lowercase a string. • Are you sure you dropped the J and not the K? – FrownyFrog Oct 11 '17 at 23:32 # Pyth, 64 bytes Can probably be golfed further. Try it here ! L?<b5b4DebK+ds:rbZ"[aeiou]{2,}"1J+*/K\a5y/K\oR@G?<J9JhJu+GeHcQd"  ## R, 261 bytes I think I spent way too much time just to get this working and I believe this is an unnecessarily complicated solution, although it works. Takes input from stdin, it's important that the string is enclosed in quotes. x=el(strsplit(toupper(scan(,""))," ")) cat(apply(sapply(c("A","O"),function(y)sapply(sapply(regmatches(x,gregexpr("[AEIOU]{2,}",x,)),paste,collapse=""),function(s)min(sum(el(strsplit(s,""))%in%y),4)))+1,1,function(z)t(matrix(LETTERS[-10],5))[z[1],z[2]]),sep="")  The use of four nested apply-family could theoretically be reduced to only two by making use of mapply instead. But because inputs to mapply will not be of the same length, the shorter one is recycled which complicates things and I couldn't figure out a working solution. If anyone is interested I'll add an ungolfed explanation later. Try all the test cases on R-fiddle Please note that this version takes input as a function argument instead from stdin because scan doesn't work on R-fiddle. Furthermore, added a newline to make it easier to read. # Python 3, 262 bytes import re;f,b,v,n,r,l,t,g,a,o=re.findall,input().lower(),'aeiou',list(range(26)),'[aeiou]','abcdefghiklmnopqrstuvwxyz','',len,'a','o';del n[9], for w in b.split(): O,A=g(f(o+r,w))+g(f(r+o,w)),g(f(a+r,w))+g(f(r+a,w)) if O>4:O=4 if A>4:A=4 t+=l[A*5+O] print(t)  Less Golfed (The comments are the variables in the shortened code): import re findAll = re.findall #f babyTalk = input('Baby Talk: ').lower() #b vowels = 'aeiou' #v numbers = list(range(26)) #n del numbers[9] letters = 'abcdefghiklmnopqrstuvwxyz' #l finalText = '' #t length = len #g regex = '[aeiou]' #r o = 'o' #o a = 'a' #a for word in babyTalk.split(): #w in b Os = len(findAll('o[aeiou]', word)) + len(findAll('[aeiou]o', word)) #O As = len(findAll('a[aeiou]', word)) + len(findAll('[aeiou]a', word)) #A if Os > 4: Os = 4 if As > 4: As = 4 print(As, Os) finalText += letters[As*5+Os] print(finalText)  Try it online! • This doesn't work for a word blaoaoaog: the interlaced vowels are counted more than once, giving z when it should be t (though it does work on just aaaooo, though I cannot figure out why....) – CAD97 Nov 2 '16 at 1:13 • @CAD97 Are you saying that aooa should be p, not n? – nedla2004 Nov 2 '16 at 1:50 • not on purpose; aooa == (2,2) == n, aoaoao == (3,3) == t – CAD97 Nov 2 '16 at 2:11 • just tested it and CAD is correct, gaoaoaog prints Z instead of T. I think it's because your regex is picking up [ao,oa,ao,oa,ao], which counts 5,5, then constricts it to 4,4, printing Z. – FlipTack Nov 2 '16 at 20:48 • @Flp.Tkc Do you know how to fix it? I am very new to regex. – nedla2004 Nov 2 '16 at 22:21 ## Kotlin, 221 209 bytes Now much more ugly and slow, all in the name of 11 bytes readLine()!!.toLowerCase().split(" ").map{fun c(c:Char)=Regex("([aeiou]{2,})").findAll(it).fold(0){a,b->a+b.value.count{it==c}}.let{if(it>4)4 else it} (('A'..'I')+('K'..'Z'))[c('a')*5+c('o')]}.forEach(::print)  Save it to a file (ex. BabyTalk.kts) to run as a script. Or, the above code can be prepended with fun main(z:Array<String>)= and compiled normally for a cost of 26 more bytes. Try it online! Indented: readLine()!! .toLowerCase() .split(" ") .map { fun c(c: Char) = Regex("([aeiou]{2,})") .findAll(it) .fold(0) { a, b -> a + b.value.count { it == c } } .let { if (it > 4) 4 else it } (('A'..'I') + ('K'..'Z'))[c('a') * 5 + c('o')] } .forEach(::print)  # PHP, 124 129 121 120 125 bytes for(;$s=$argv[++$i];print chr((8<$O+=5*$A)+$O+65))for($k=$A=$O=0;$c=_&$s[$k++];$p=$c)$$c+=$$c<4&!trim($p.$s[$k]&__,AEIOU)[1];


Takes input from command line arguments. Run with -nr or try it online.

breakdown

for(;$s=$argv[++$i]; # loop$s through arguments
print chr((8<$O+=5*$A)+$O+65) # 3. map A and O counts to letter, print ) for($k=$A=$O=0;                 # 1. reset A and O counters
$c=$s[$k++]&_; # 2. loop$c through characters:
$p=$c)                          # 2. remember current character as previous
$$c+= # 1. increment counter for c, if ...$$c<4&                          # it is < 4 and ...
!trim($p.$s[\$k]&__,AEIOU)[1];   # ... previous or next char is vowel


# J, 109 bytes

echo{&(u:97+i.26)(+8<[)5#.4<.'AO'+/@e."1 0/~(;@#~1<#@>)@(</.~0+/\@,}.~:&(e.&'AEOUI')}:);._1' ',toupper 1!:1]3


Try it online!