15
\$\begingroup\$

Rövarspråket

Rövarspråket is a word game played by Swedish children, from the books about Kalle Blomkvist by Astrid Lindgren.

The basic rules are as follows (from Wikipedia):

  • Every consonant (spelling matters, not pronunciation) is doubled, and an o is inserted in-between.
  • Vowels are left intact.

A few examples:

  • "hello" -> "hohelollolo"
  • "Min svävare är full med ål" -> "MoMinon sosvovävovarore äror fofulollol momedod ålol"

Swedish consonants are the same as the English ones, so the program should work with both Swedish and English entries.

The letter "y" is taken as a consonant in this case - as most of the time it is.


Your Task:

Write a program to convert a string of Swedish letters, inputted through a function or through stdin, into its Rövarspråket equivalent. Shortest answer in bytes wins!

\$\endgroup\$
  • \$\begingroup\$ @MartinBüttner Clarified my question further - it should work with Swedish (as it is a Swedish word-game). \$\endgroup\$ – James Williams Mar 24 '15 at 18:14
  • \$\begingroup\$ What is the meaning of alphabetical entries ? \$\endgroup\$ – Optimizer Mar 24 '15 at 18:15
  • \$\begingroup\$ @Optimizer A string of only alphabetical characters. Sorry, I worded it badly, I'll edit \$\endgroup\$ – James Williams Mar 24 '15 at 18:15
  • 3
    \$\begingroup\$ How should we treat non letters? At least spaces show up in the second example. \$\endgroup\$ – nimi Mar 24 '15 at 19:28
  • 2
    \$\begingroup\$ On a side note: 'Y' is considered a vowel in Swedish \$\endgroup\$ – leo Mar 26 '15 at 12:18

25 Answers 25

14
\$\begingroup\$

Retina, 14 + 5 = 19 bytes

Retina is a language that is essentially just .NET regex with as little overhead as possible. The code for this program consists of two files:

i`[b-z-[eiou]]
$0o$0

This reads the input on STDIN and prints the output to STDOUT.

If you call the files pattern.rgx and replacement.rpl, you can run the program simply like

echo "hello" | ./Retina pattern.rgx replacement.rpl

Explanation

This is pretty straightforward, but let me add some explanation anyway (mostly about how Retina works). If Retina is invoked with 2 files it is automatically assumed to operate in "Replace mode", where the first file is the regex and the second file is the pattern.

Retina can be configured (which includes RegexOptions and other options) by prepending the regex with ` and a configuration string. In this case I'm only giving it i which is the normal regex modifier for case insensitivity.

As for the regex itself, it uses .NET's character class subtraction to match any consonant in the ASCII range. The replacement then just writes the match back twice with an o in between.

\$\endgroup\$
  • \$\begingroup\$ Are you missing an a in your vowel character class? \$\endgroup\$ – Brian Gordon Mar 25 '15 at 19:22
  • 3
    \$\begingroup\$ @BrianGordon No, I'm starting the character class from b, so I don't need to subtract a. \$\endgroup\$ – Martin Ender Mar 25 '15 at 19:27
  • 2
    \$\begingroup\$ Interesting, I've never seen nested, subtractive character ranges before. Is that just a .NET thing? \$\endgroup\$ – Steve Bennett Apr 20 '15 at 9:18
  • \$\begingroup\$ I feel like you need to count at least one character for the delimiting between the two files. that would be a semicolon or newline in another language. it's the space between the filenames if you want to get picky about where the character comes from in this language. \$\endgroup\$ – Sparr May 20 '15 at 3:41
  • \$\begingroup\$ @Sparr yes, that's the policy now, but that policy is newer than this challenge/answer. For reference (In fact, if you look at the time stamps, you can see that I pushed for the policy because of this answer, but applying rules like that throughout the site retroactively doesn't make much sense.) \$\endgroup\$ – Martin Ender May 20 '15 at 12:23
12
\$\begingroup\$

Using Unix KSH 27 28 32 27 bytes (or 21 if we only count inside sed command)

Thanks to the suggestions of others :) Appreciated.

.. I got down to this:

sed 's/[^AEIOUÅÄÖ ]/&o&/ig'

(allowed for spaces and Swedish characters)

echo "hello" | sed 's/[BCDFGHJ-NP-TV-Z]/&o&/ig'
hohelollolo
echo "HELLO" | sed 's/[BCDFGHJ-NP-TV-Z]/&o&/ig'
HoHELoLLoLO
echo "QuIcKlY Now" | sed 's/[BCDFGHJ-NP-TV-Z]/&o&/ig'
QoQuIcocKoKlolYoY NoNowow
\$\endgroup\$
  • 4
    \$\begingroup\$ Also, I think it is allowable to claim your answer is a sed program, and just count the bytes between the single quotes \$\endgroup\$ – Digital Trauma Mar 24 '15 at 19:21
  • 1
    \$\begingroup\$ s/[^AEIOU]/&o&/ig seems to work.. for single words at least... you'll need to exclude spaces as well \$\endgroup\$ – Digital Trauma Mar 24 '15 at 19:23
  • 1
    \$\begingroup\$ bash, though the shell shouldn't matter, so long as your sed program is in single quotes \$\endgroup\$ – Digital Trauma Mar 24 '15 at 19:30
  • 1
    \$\begingroup\$ Also watch out for the swedish vowels ö, å, etc - these need excluding too. Might be better to use a whitelist of just the consonants s/[BCDFGHJ-NP-TV-Z]/&o&/ig \$\endgroup\$ – Digital Trauma Mar 24 '15 at 19:32
  • 2
    \$\begingroup\$ I would make it 'sed' and use "s/[^AEIOUÅÄÖ ]/&o&/ig", which covers Swedish vowels and spaces for 25 bytes. \$\endgroup\$ – swstephe Mar 24 '15 at 22:34
7
\$\begingroup\$

CJam, 32 30 bytes

q{_eu'[,66>"EIOU"-#)g{'o1$}*}/

This is a full program reading from STDIN and printing to STDOUT. It works for arbitrary Unicode input and treats the following 42 characters as consonants:

BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz

Test it here.

Explanation

q                              "Slurp STDIN.";
 {                          }/ "For each character...";
  _eu                          "Duplicate and convert to upper case.";
     '[,66>                    "Get a string from B to Z using range and slice.";
           "EIOU"-             "Remove the remaining four vowels.";
                  #            "Find the position of the character in this string or
                                -1 if the character can't be found.";
                   )g          "Increment, take signum, which gives 1 for consonants, 
                                and 0 otherwise.";
                     {    }*   "Repeat this block that many times, i.e. do nothing for
                                non-consonants.";
                      'o       "Push an 'o'.";
                        1$     "Copy the current character.";
\$\endgroup\$
5
\$\begingroup\$

JavaScript, 59 57 55 44 bytes

s=>s.replace(/(?![eiou])[b-z]/gi,"$&o$&")

Thanks to Masterzagh for reminding me that a function would be acceptable as well, and for his regex tip regarding backreferences without capturing!

Longer version with input/output:

alert(prompt().replace(/(?![eiou])[b-z]/gi,"$&o$&"));

Displays a prompt box to enter the string, then shows a dialog containing the Rövarspråket output. The code uses a regex to double the consonants and insert os.

\$\endgroup\$
  • \$\begingroup\$ "Write a program to convert a string of Swedish letters, inputted through a function or through stdin", You can make it s=>alert(s.replace(/(?![eiou])([b-z])/gi,"$1o$1")); \$\endgroup\$ – user64039 Jan 12 '17 at 15:09
  • \$\begingroup\$ And since it wasn't asked to output, you don't need the alert either. \$\endgroup\$ – user64039 Jan 12 '17 at 15:16
  • \$\begingroup\$ One more thing, you can backreference without capturing. Basically do s=>s.replace(/(?![eiou])[b-z]/gi,"$&o$&"), since $& means current match you can remove the parenthesis that capture your letter and while you're at it save another byte by removing the semicolon at the end. \$\endgroup\$ – user64039 Jan 12 '17 at 15:40
  • \$\begingroup\$ @Masterzagh That's cool, thanks again! \$\endgroup\$ – ProgramFOX Jan 12 '17 at 16:13
4
\$\begingroup\$

Mathematica, 84 73 72 bytes

StringReplace[#,a:RegularExpression@"(?i)[BCDFGHJ-NP-TV-Z]":>a<>"o"<>a]&

Explanation:

  • RegularExpression@"(?i)[BCDFGHJ-NP-TV-Z]" is a regex matching all consonants case-insensitively.
  • a:*..*:>a<>"o"<>a creates a delayed rule to bind those consonants to a, and replace it with and o surrounded by itself.
  • Finally, StringReplace[#,*..*]& creates a pure function applying that rule to every matching letter in its argument.
\$\endgroup\$
  • \$\begingroup\$ @MartinBüttner Thanks! Still new to Mathematica golfing... \$\endgroup\$ – LegionMammal978 Mar 24 '15 at 23:17
  • \$\begingroup\$ @MartinBüttner Was going to do that anyways but got distracted by some notifications :P \$\endgroup\$ – LegionMammal978 Mar 24 '15 at 23:25
4
\$\begingroup\$

Julia, 46 44 bytes

t->replace(t,r"(?![eiou])[b-z]"i,s->s*"o"*s)

This creates an anonymous function that takes a single string input and prints the Rövarspråket equivalent. To call it, give it a name, e.g. f=t->....

Not much has really been golfed here, other than spaces after the commas in replace().

Here we're using 3 arguments in the replace() function: the input string, the regular expression for identifying substrings, and a replacement. Julia denotes regular expression patterns by r"...". Adding i to the end makes it case insensitive. This particular regex matches consonants. If a function is used for the replacement, the output is that function applied to each matched substring. The function we're using here takes a string s and returns sos, since * performs string concatenation in Julia. Thus the end result is the input string with each consonant doubled with an "o" between.

Examples:

julia> f("Min svävare är full med ål")
"MoMinon sosvovävovarore äror fofulollol momedod ålol"

julia> f("hello")
"hohelollolo"

julia> f("Rövarspråket")
"RoRövovarorsospoproråkoketot"

Note that this will be 9 bytes longer if we have to print the result rather than return it. Awaiting confirmation from the OP.


Edit: Saved 2 bytes thanks to Martin Büttner!

\$\endgroup\$
3
\$\begingroup\$

Haskell, 81 bytes

x n|elem n"bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ"=[n,'o',n]|1<2=[n]
f=(>>=x)

Usage: f "Hello there!" -> "HoHelollolo tothoherore!".

I cannot cleverly construct the list of consonants without expensive imports. Even turning the letter to check to lowercase needs more bytes than simply listing both upper and lowercase consonants.

\$\endgroup\$
3
\$\begingroup\$

Java 8, 45

Use as a lambda function. Uses regular expression.

a->a.replaceAll("(?i)[b-z&&[^eiou]]","$0o$0")

Try here

\$\endgroup\$
2
\$\begingroup\$

Perl, 33 Bytes

This answer is mostly regex-only, with a small amount of extra code to perform I/O.

$_=<>;s/[^aeiou\W]/$&o$&/gi;print

It's been a while since I've used Perl regexes, so this can probably be improved.

$_=<>;                              This takes input from STDIN `<>` and stores
                                    it into the default variable $_
      s/          /     /gi;        This is a case-(i)nsentive, (g)lobal, 
                                    (s)ubstitution regex.  Since no other
                                    variable is specified, it is applied to
                                    the default variable $_.
        [^aeiou\W]                  This matches any single character that 
                                    is a consonant, by using a double-
                                    negative ^\W to match only alphanumeric 
                                    characters excluding vowels.  Accented 
                                    vowels are not considered alphanumeric 
                                    by Perl.
                   $&o$&            This forms the replacement.  $& contains the 
                                    match (the consonant), so this replaces each 
                                    consonant with two copies of itself with 
                                    an 'o' in between.
                            print   This prints the result.  With no arguments, 
                                    it prints $_ by default.
\$\endgroup\$
  • \$\begingroup\$ Won't [^aeiou] still match å and other non-ASCII vowels? \$\endgroup\$ – Alex A. Mar 25 '15 at 0:40
  • \$\begingroup\$ @AlexA. I already noticed the problem. It was a zero-character fix (\s to \W). \$\endgroup\$ – PhiNotPi Mar 25 '15 at 0:51
  • \$\begingroup\$ +1, most thorough explanation for Perl code I have seen on this site. \$\endgroup\$ – Zgarb Mar 25 '15 at 8:49
2
\$\begingroup\$

C (ideone.com version) - 133

Ok, this is huge. But C doesn't have regular expressions. Please tell me if you see something that can make it shorter...

#define x (*c<66||*c>90)&&(*c<98||*c>122)||strchr("EIOUeiou",*c)?"":
c[2];main(){while(0<(*c=getchar()))printf("%s%s%s",c,x"o",x c);}
\$\endgroup\$
  • \$\begingroup\$ How does the local variable c get declared? \$\endgroup\$ – wjl Mar 25 '15 at 21:20
  • \$\begingroup\$ @wjl global variables in C are zero initialized. Local variables are on the stack and are not initialized. See stackoverflow.com/questions/3553559/… Variables with out a type default to int and since printf works on chars the code might have endian issues - I will check tomorrow. \$\endgroup\$ – Jerry Jeremiah Mar 26 '15 at 11:31
  • \$\begingroup\$ Yes, I understand default initialization. I was just trying to nicely point out that this code does not compile since c isn't declared at all, e.g. out.c:2:18: error: ‘c’ undeclared (first use in this function). \$\endgroup\$ – wjl Mar 26 '15 at 15:40
  • \$\begingroup\$ @wjl I guess it depends on the compiler. It compiles and runs at ideone.com ideone.com/s7M5mZ when you choose C - any idea what the difference is? \$\endgroup\$ – Jerry Jeremiah Mar 26 '15 at 18:38
  • \$\begingroup\$ Looks like a bug with ideone's compiler. If you fix the newline between c[2];main (necessary because #define doesn't end at a semicolon) it gives similar errors to GCC. Anyway, no big deal, it's still a fun code-golf, but you might actually need a few more characters to make this valid C. =) \$\endgroup\$ – wjl Mar 26 '15 at 20:06
2
\$\begingroup\$

Windows Batch, 235 bytes

@echo off
setlocal enabledelayedexpansion
set d=qwrtypsdfghjklzxcvbnm
set #=%1
:x
if defined # (
for /l %%i in (0,1,20)do (
set m=!d:~%%i,1!
if /i !m!==%#:~0,1% set g=!g!!m!o)
set g=!g!%#:~0,1%
set #=%#:~1%
goto x)
echo %g%

Usage:

script.bat hello

Output:

hohelollolo

You might be wondering why I didnt set d to "aoui", checking for not-equals requires breaking out of a loop. Not everything that should work, does work, in batch. The script handles 1 word of characters [as they appear on your keyboard]. All spaces and newlines that are still present are required for the script to run.

Windows XP or higher, required. Not tested in Windows 8 and above.

\$\endgroup\$
2
\$\begingroup\$

PowerShell - 35 bytes

Just to show that PowerShell can compete in these sometimes too, and with the regex shamelessly stolen from Martin Büttner's Retina answer:

%{$_-replace'[b-z-[eiou]]','$0o$0'}

accepts string input from stdin

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

Pyth - 28 bytes

This is works in the obvious way by generating the consonants list on the fly using set-wise difference.

FNzpk+N?+\oN}rNZ-{G{"aeiou"k

Explanation coming soon.

Try it here.

\$\endgroup\$
  • \$\begingroup\$ You can save 4 bits by removing 4 chars and replacing one char with another one. \$\endgroup\$ – Jakube Mar 24 '15 at 19:12
1
\$\begingroup\$

Clip 10, 30

gx"((?i)[b-z&&[^eiou]])""$1o$1

Basic regex substitution.

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

Pyth, 25 24 23

sm+d*+\od}rd0-G"aeoui"z

Run it here.

\$\endgroup\$
  • \$\begingroup\$ One char of your solution is redundant. \$\endgroup\$ – Jakube Mar 24 '15 at 21:42
1
\$\begingroup\$

Python, 61

I couldn't get a character class union or subtraction to work, and so I don't think Python has that feature. I had to use a negative lookahead instead.

import re;f=lambda s:re.sub('(?i)(?![eiou])([b-z])',r'\1o\1',s)

Run it here: http://repl.it/fQ5

Link to the inverse: https://codegolf.stackexchange.com/a/48182/34718

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

K, 38 chars

f:{,/(1+2*~(_x)in"aeiouåäö ")#'x,'"o"}

-1 f"Min svävare är full med ål";
MoMinon sosvovävovarore äror fofulollol momedod ålol
\$\endgroup\$
1
\$\begingroup\$

K, 31 bytes

,/{(x,"o",x;x)9>" aeiouåäö"?x}'

A straightforward solution seems fairly competitive given that K lacks regexes. Select between the "XoX" form and "X" form based on whether each character was found in a lookup table of ignored vowels and join the resulting lists.

You can try it in your browser using oK:

http://johnearnest.github.io/ok/index.html?run=%20%2C%2F%7B(x%2C%22o%22%2Cx%3Bx)9%3E%22%20aeiouåäö%22%3Fx%7D'%22Min%20svävare%20är%20full%20med%20ål%22

(Unfortunately I can't provide a clickable link because stack overflow doesn't appear to allow accented characters in URLs)

\$\endgroup\$
0
\$\begingroup\$

Golfscript, 35 bytes

{."aeiouåäö\n "?-1={."o"\}{}if}%

Expects the input to be on the stack. With input (50 bytes):

"#{STDIN.gets}"{."aeiouåäö\n "?-1={."o"\}{}if}%

Works with the swedish vovels å, ä and ö.

\$\endgroup\$
  • 2
    \$\begingroup\$ input is always on stack on GS \$\endgroup\$ – Optimizer Mar 25 '15 at 9:40
0
\$\begingroup\$

Sed (on command line), 28 bytes

sed 's/\([^aeiou]\)/\1o\1/g'

Either pipe the text in or type it direct. Just the sed code on its own is 22 bytes.

\$\endgroup\$
  • 3
    \$\begingroup\$ This also duplicates spaces and chars like ä. \$\endgroup\$ – ProgramFOX Mar 25 '15 at 13:02
0
\$\begingroup\$

R, 45 chars

gsub("([^aeiouäöå ])","\\1o\\1",readline(),i=T)

Simple regex. Reads from stdin. i=T stands for ignore.case=TRUE (thanks to partial matching of argument names), which makes gsub case insensitive.

Usage:

> gsub("([^aeiouäöå ])","\\1o\\1",readline(),i=T)
Min svävare är full med ål
[1] "MoMinon sosvovävovarore äror fofulollol momedod ålol"
> gsub("([^aeiouäöå ])","\\1o\\1",readline(),i=T)
hello
[1] "hohelollolo"
> gsub("([^aeiouäöå ])","\\1o\\1",readline(),i=T)
hElLo
[1] "hohElolLoLo"
\$\endgroup\$
0
\$\begingroup\$

<>< (Fish), 64 bytes

>" oieauåäöOIEAUÅÄÖ"0i:1+?!;01.
 :&=?\     l?!v&
^[0o&<&o"o"o:&<

It's not the shortest answer but I enjoy the challenge of programming in <><

Try it out here

\$\endgroup\$
0
\$\begingroup\$

golflua, 36 bytes

B=I.r():g("[^aeiou%W ]","%1o%1")w(B)

Simple pattern-matching: take stdin, then find the non-vowels (%W takes care of non-alphanumeric chars) & insert an o between the two replacements. Sadly, doing all this within the write (i.e., w(I.r():g(....))) also output the count of insertions, though it saved 3 chars. A Lua equivalent would be

line = io.read()
rovar = line:gsub("[^aeiou%W ]","%1o%1")
print(rovar)
\$\endgroup\$
0
\$\begingroup\$

REXX, 107 bytes

parse arg s
v='aeiouåäö '
o=
do until s=''
  parse var s l 2 s
  if verify(l,v)>0 then l=l'o'l
  o=o||l
  end
say o

"MoMinon sosvovävovarore äror fofulollol momedod ålol"

\$\endgroup\$
0
\$\begingroup\$

JavaScript 43

Thanks to @Masterzagh for saving on function syntax.

x=>x.replace(/[bcdfghj-np-tv-z]/gi,"$&o$&")

JavaScript 62

function E(x){return x.replace(/[bcdfghj-np-tv-z]/gi,"$&o$&")}
\$\endgroup\$
  • \$\begingroup\$ Your function can be in the form of an anonymous arrow function like x=>x.replace(/[bcdfghj-np-tv-z]/gi,"$&o$&"). Arrow functions work like this name=(arg1, arg2)=>{code}. () are not needed if there's only one argument and {} are not needed if there's only one line of code. Return is also not needed if the one line returns something. \$\endgroup\$ – user64039 Jan 12 '17 at 15:13
  • \$\begingroup\$ And I forgot to say. You don't need to give it a name to solve the problem which only asked you to create a function. \$\endgroup\$ – user64039 Jan 12 '17 at 15:20

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.