23
\$\begingroup\$

The residents of Flapus use a base-8 number system. The numbers are:

0 - Kuzla
1 - Ponara
2 - Boqkel
3 - Colopee
4 - Vruenat
5 - Foham
6 - Stikty
7 - Kricola

For numbers over 7, the full name of the last digit comes first, followed by apostrophe and the first characters of the other digit(s), up to and including the first vowel:

11 - Ponara(1)'po(1)
13 - Colopee(3)'po(1)
64 - Vruenat'sti
55 - Foham'fo
47 - Kricola'vru

As the numbers go up, the formula stays the same - the full name last digit comes first, followed by an apostrophe and the first characters of the other digits, up to and including the first vowel. Note that apart from the final digit (first word), the order remains the same.

123 - Colopee(3)'po(1)bo(2)
205 - Foham(5)'bo(2)ku(0)
1123 - Colopee'popobo
7654 - Vruenat'kristifo

The exception to the rule is for numbers ending in 0. Here the word begins with Ku and is completed with the first letters of the other digits, up to and including the first vowel. No apostrophe is used.

10 - Kupo
70 - Kukri
350 - Kucofo
630 - Kustico
1000 - Kupokuku

Challenge

Write a program or function that accepts a valid base-8 number, and outputs the spoken equivalent. You may assume you will always receive a valid number. Trailing whitepace / single newline after your answer is ok. The first character needs to be upper-case, as per examples.

This is . Shortest code in bytes wins. Standard loopholes apply. Answers whose lengths are converted and additionally submitted in Flapussian get extra cookies.

Test cases

0 -> Kuzla
1 -> Ponara
2 -> Boqkel
3 -> Colopee
4 -> Vruenat
5 -> Foham
6 -> Stikty
7 -> Kricola
10 - > Kupo
11 -> Ponara'po
23 -> Colopee'bo
56 -> Stikty'fo
70 -> Kukri
100 -> Kupoku
222 -> Boqkel'bobo
2345 -> Foham'bocovru

\$\endgroup\$
1
  • 3
    \$\begingroup\$ Now that I think of it, the numbers all sound pretty cute \$\endgroup\$
    – busukxuan
    Jan 22, 2016 at 9:16

8 Answers 8

9
\$\begingroup\$

Retina, Colopee'pokri, 165 157 143 127 123 bytes

(.+)(.)
$2'$1
0
Kuzla
1
Ponara
2
Boqkel
3
Colopee
4
Vruenat
5
Foham
6
Stikty
7
Kricola
(?<='.*[iou])[a-z]+

T`L`l`'.+
zla'

The trailing linefeed is significant.

Try it online!

Explanation

(.+)(.)
$2'$1

We start by bringing the trailing digit to the front and inserting an apostrophe after it. Note that this leaves single-digit numbers unchanged, since the regex doesn't match - so those never get an apostrophe in the first place.

0
Kuzla
1
Ponara
2
Boqkel
3
Colopee
4
Vruenat
5
Foham
6
Stikty
7
Kricola

This replaces each digit with its full name, regardless of where it appears.

(?<='.*[iou])[a-z]+

This shortens all the digit names that appear after an apostrophe. Note that only the vowels iou appear first in a digit name, so we check a position that is right after one of those, and after an apostrophe and then match (and remove) all lower case letters that follow that position. Since we've inserted the digit names in title case, this will stop before the next digit.

T`L`l`'.+

This uses transliteration to turn all upper case characters, L, into their lower case counterpart, l, provided they are found in a match that starts with ' (in order to leave the leading capital untouched).

zla'

The only thing that's left is correctly handling multiples of (octal) 10. In that case, we'll have a result starting with Kuzla', which we want to start with Ku instead. So we simply remove all occurrences of zla'.

\$\endgroup\$
1
  • \$\begingroup\$ I refactored and used your regex approach - saves 10 bytes! I don't think I can squeeze much more out of my Java solution. Still miles away from yours though! \$\endgroup\$ Jan 26, 2016 at 12:03
5
\$\begingroup\$

Pyth, 117 bytes (Kricola'popo)

Jc"Ku Po Bo Co Vru Fo Sti Kri";K+kc"nara qkel lopee enat ham kty cola";=TsezIszp@JTp@KTp?&T>sz7\'kVPzpr@JsN0;.?"Kuzla

Hand-transpiled to pythonic pseudocode:

                                           z = input()      # unevaluated, raw
                                           k = ""
Jc"Ku Po Bo Co Vru Fo Sti Kri";            J = "Ku Po...Kri".split()
K+kc"nara qkel lopee enat ham kty cola";   K = k + "nara...cola".split() # k casted to [""]
=Tsez                                      T = int(end(z))  # end(z) means z[-1]
Isz                                        if int(z):
  p@JT                                         print(J[T])
  p@KT                                         print(K[T])
  p?&T>sz7\'k                                  print("'" if T and s > z else k)
  VPz                                          for N in z[:-1]:  # P(z) is z[:-1]
    pr@JsN0                                        print(J[int(N)].lower())
.?                                         else:
  "Kuzla                                       print("Kuzla")
\$\endgroup\$
2
  • \$\begingroup\$ Nice work! You can save a few bytes by changing your if ... else into a ternary by changing your for loop into a map operation, and then making some minor changes. Here is what I got. I'd also draw your attention to ." which can be used on compressed strings. \$\endgroup\$ Jan 21, 2016 at 21:11
  • \$\begingroup\$ @FryAmTheEggman I was aware of .", but I totally didn't expect it could compress the first string! \$\endgroup\$
    – busukxuan
    Jan 22, 2016 at 4:10
4
\$\begingroup\$

JavaScript (ES6), 171

n=>(x='Kuzla Ponara Boqkel Colopee Vruenat Foham Stikty Kricola ku po bo co vru fo sti kri'.split` `,r=x[d=+(n=[...n]).pop()],n.map(d=>r+=x[+d+8],n[0]?r=d?r+"'":'Ku':0),r)

Test

F=n=>(
  x='Kuzla Ponara Boqkel Colopee Vruenat Foham Stikty Kricola ku po bo co vru fo sti kri'.split` `,
  r=x[d=+(n=[...n]).pop()],
  n.map(d=>r+=x[+d+8],n[0]?r=d?r+"'":'Ku':0),
  r
)  


console.log=x=>O.textContent+=x+'\n'

o=''
for(i=0;i<999;i++)
  o+=i.toString(8) +':'+ F(i.toString(8))+(i%8!=7?' ':'\n')
console.log(o)
#O { font-size:12px }
<pre id=O></pre>

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

Java (1.8) - Vruenat'fobo (486 340 bytes)

Just when I thought I couldn't possibly golf this any more, I found another 33 bytes! Very pleased! Biggest savings were from switching to char arrays (shorter to upper/lowercase), and reusing the input string array for the words.

Discovering loads of golfing tricks, down to under 400! In theory I could still reduce this more, as I said a function would be ok in the rules, whereas this is a full program.

Updated Using Martin Büttner's approach, I refactored to use regex instead. Managed to save another 10 bytes! Thanks Martin.

interface F{static void main(String[]n){String t="",o,a=n[0];n="Kuzla,Ponara,Boqkel,Colopee,Vruenat,Foham,Stikty,Kricola".split(",");int i=0,l=a.length()-1;char f=a.charAt(l);o=n[f-48]+(l>0?"'":"");while(i<l)t+=n[a.charAt(i++)-48];o+=t.replaceAll("(?<=.*[iou])[a-z]+","").toLowerCase();if(f==48)o=o.replace("zla'","");System.out.print(o);}}

Ungolfed

interface Flapus {
static void main(String[] names) {
    String temp="",out, a = names[0];
    names = "Kuzla,Ponara,Boqkel,Colopee,Vruenat,Foham,Stikty,Kricola".split(",");
    int i=0, last = a.length()-1;
    char lastchar = a.charAt(last);

    out=names[lastchar-48]+(last>0?"'":"");
    while(i<last) {
        temp+=names[a.charAt(i++)-48];
    }
    out+=temp.replaceAll("(?<=.*[iou])[a-z]+", "").toLowerCase();
    if (lastchar==48) {
        out=out.replace("zla'","");
    }
    System.out.print(out);
}
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ You can use interface F and remove the public declaration on the main method. You can also remove the space in String[] x and in .substring(0, v+1). \$\endgroup\$ Jan 19, 2016 at 9:26
  • 1
    \$\begingroup\$ You could save some more bytes by generating the array from a split string : "Kuzla,Ponara,Boqkel,Colopee,Vruenat,Foham,Stikty,Kricola".split(",") is 70 bytes, while the inline array is 74. \$\endgroup\$
    – Aaron
    Jan 20, 2016 at 9:23
  • \$\begingroup\$ Try as I might, I can't seem to golf this any harder. Anyone out there with any further tips? \$\endgroup\$ Jan 21, 2016 at 14:42
3
\$\begingroup\$

Python (3.5) 225 222 217 202 bytes

A working solution with list comprehension in python

s=input()
d="Kuzla,Ponara,Boqkel,Colopee,Vruenat,Foham,Stikty,Kricola".split(',')
r=d[int(s[-1])]+"'"if s[-1]!='0'else'Ku'
d=[i[:2+(i[2]in'ui')].lower()for i in d]
for i in s[:-1]:r+=d[int(i)]
print(r)

Explanation

d="Kuzla,Ponara,Boqkel,Colopee,Vruenat,Foham,Stikty,Kricola".split(',')

Win 3 bytes with the split version (previous version: d="Kuzla","Ponara",...)

r=d[int(s[-1])]+"'"if s[-1]!='0'else'Ku'

Initialisation of the result in function of the last digit

d=[i[:2+(i[2]in'ui')].lower()for i in d]

Change the d list to keep first 2 or 3 characters and put in lower case

for i in s[:-1]:r+=d[int(i)]

Cat the string

\$\endgroup\$
3
  • 1
    \$\begingroup\$ 2345 returns Foham'bocovr. It should return Foham'bocovru. This is because you are only reading 2 characters, instead of up to and including the first vowel. Pesky Vruenat \$\endgroup\$ Jan 19, 2016 at 15:14
  • \$\begingroup\$ Same problem for 'Stikty' and 'Kricola' \$\endgroup\$ Jan 19, 2016 at 15:17
  • 1
    \$\begingroup\$ @Denham Coote oops I forgot to answer your comments. thanks for your remarks, I corrected the issues \$\endgroup\$
    – Erwan
    Jan 26, 2016 at 6:54
2
\$\begingroup\$

Javascript ES6, 231 228 225 222 204 bytes

a=[...prompt(c="Kuzla,Ponara,Boqkel,Colopee,Vruenat,Foham,Stikty,Kricola".split`,`)];b=c[a.pop()];a.length?b=b==c[0]?"Ku":b+"'":0;for(;a.length;)b+=c[a.shift()].match(/.+?[iou]/)[0].toLowerCase();alert(b)

Saved a bunch of bytes thanks to Neil.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ General golfing tips: [...s] instead of s.split``; b=b==c[0]?"Ku":b+"'" instead of if(b==c[0]){b="Ku"}else b+="'"; similarly for the if(a.length) (just use 0 for the else part); a.map(d=>b+=c[d].match...) instead of fiddling around with for and shift. I think that's 29 bytes saved already. \$\endgroup\$
    – Neil
    Jan 19, 2016 at 0:47
  • \$\begingroup\$ Peeking at someone else's answer suggests you can save another 2 bytes because you only need to use [iou] as your "vowel" class. \$\endgroup\$
    – Neil
    Jan 19, 2016 at 0:49
  • \$\begingroup\$ @Neil Thanks. I'll do that. \$\endgroup\$ Jan 19, 2016 at 1:57
2
\$\begingroup\$

F#, 364 288 250 bytes (Kubofo)

let M="Ku-Ponara-Boqkel-Colopee-Vruenat-Foham-Stikty-Kricola".Split '-'
let m="Ku-Po-Bo-Co-Vru-Fo-Sti-Kri".Split '-'
let rec r a=function|0->a|i->r(m.[i%10].ToLower()::a)(i/10)
fun i->String.concat""<|M.[i%10]::((if(i%10)=0 then""else"'")::r[](i/10))

Returns a function that takes an integer and returns its Flapus equivalent. =D

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

Python 3 - 181 177 bytes (Ponara'bosti)

a='Ku Po Bo Co Vru Fo Sti Kri zla nara qkel lopee enat ham kty cola'.split()
*y,x=map(int,input())
u=x>0
v=y>[]
print(a[x]+a[x+8]*u**v+"'"*(u&v)+''.join(a[i].lower()for i in y))

Beware of the most amazing use of pow you will ever see in your entire life. u**v is equivalent on boolean context as u|(not v) which was previously golfed to the nice ~v+2|u expression!

\$\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.