13
\$\begingroup\$

Create a program with the lowest amount of characters to reverse each word in a string while keeping the order of the words, as well as punctuation and capital letters, in their initial place.

By "Order of the words," I mean that each word is split by a empty space (" "), so contractions and such will be treated as one word. The apostrophe in contractions should stay in the same place. ("Don't" => "Tno'd").

(Punctuation means any characters that are not a-z, A-Z or whitespace*).

  • Numbers were removed from this list due to the fact that you cannot have capital numbers. Numbers are now treated as punctuation.

For example, for the input:

Hello, I am a fish.

it should output:

Olleh, I ma a hsif.

Notice that O, which is the first letter in the first word, is now capital, since H was capital before in the same location.

The comma and the period are also in the same place.

More examples:

This; Is Some Text!

would output

Siht; Si Emos Txet!

Any language can be used. The program with the lowest amount of characters wins.

\$\endgroup\$
  • 3
    \$\begingroup\$ How should contractions be treated? That is does Don't touch that! map to t'noD hcuot taht! or to noD't hcuot taht!? \$\endgroup\$ – dmckee Apr 7 '13 at 4:39
  • 2
    \$\begingroup\$ @dmckee "(Punctuation means any characters that are not a-z, A-Z, 1-9 or whitespace)" \$\endgroup\$ – John Dvorak Apr 7 '13 at 4:46
  • 1
    \$\begingroup\$ @dmckee so it should map to Nod't hcuot tath! \$\endgroup\$ – John Dvorak Apr 7 '13 at 4:49
  • 1
    \$\begingroup\$ Reversing each word is easy. Reversing each word and keeping capitalisation is not. \$\endgroup\$ – John Dvorak Apr 7 '13 at 4:53
  • 1
    \$\begingroup\$ Yup, that's the challenge ;) just simply reversing them would be too simple and would likely come down to the language used. This is meant to make you think. \$\endgroup\$ – nasonfish Apr 7 '13 at 4:56
7
\$\begingroup\$

GolfScript, 58 54 48 characters

" "/{.{65- 223&26<}:A,\{.A{96&\)31&@+}*}%+}%" "*

This is a GolfScript solution which became rather long. Lots of the code is actually finding out if a character is in a-zA-Z. Maybe someone can find an even shorter way of testing it.

You can try the code online. Examples:

> Hello, I am fish.
Olleh, I ma hsif.

> This; Is Some Text!
Siht; Si Emos Txet!

> Don't try this at home.
Tno'd yrt siht ta emoh.
\$\endgroup\$
  • \$\begingroup\$ That online golfscript editor looks useful. Bookmarking, thanks \$\endgroup\$ – John Dvorak Apr 7 '13 at 11:00
  • \$\begingroup\$ You can pull the final " " inside the % to save one. I've found other ways of testing a-zA-Z for 11 chars, but none yet for 10. \$\endgroup\$ – Peter Taylor Apr 10 '13 at 7:08
4
\$\begingroup\$

APL 69

Takes screen input via: t←⍞

⎕av[1↓∊(↑¨v),¨((¯1×⌽¨z)+z←¯32×~1↓¨v>97)+¨⌽¨1↓¨v←(+\v<66)⊂v←0,⎕av⍳t←⍞]
\$\endgroup\$
  • \$\begingroup\$ Shouldn't APL be counted in UTF-8 bytes? :-) \$\endgroup\$ – John Dvorak Apr 7 '13 at 10:40
  • \$\begingroup\$ @JanDvorak The APL+Win V5 character set is single byte. I have to convert to UTF-8 to post here in order for the characters to render correctly. ⎕av⍳t above returns an index into the character set from 0-255 for the characters in the vector t. \$\endgroup\$ – Graham Apr 7 '13 at 10:50
4
\$\begingroup\$

Coffeescript, 134 133 characters

alert prompt().replace /\S+/g,(x)->c=x.match r=/[a-z]/gi;return x.replace r,(y)->return c.pop()[`(y<"a"?"toUpp":"toLow")`+"erCase"]()

Coffeescript is (for the purposes of code golf) a slightly denser version of javascript. It doesn't have the ternary operator, but it has an escape to javascript.

Here's the javascript version:

Javascript, 152 151 characters

alert(prompt().replace(/\S+/g,function(x){c=x.match(r=/[a-z]/gi);return x.replace(r,function(y){return c.pop()[(y<"a"?"toUpp":"toLow")+"erCase"]()})}))

Indented:

alert(prompt().replace(/\S+/g,function(x){
  c=x.match(r=/[a-z]/gi);
  return x.replace(r, function(y){
    return c.pop()[(y<"a"?"toUpp":"toLow")+"erCase"]()
  })
}))
\$\endgroup\$
2
\$\begingroup\$

Ruby: 89 characters (including 1 for the -p switch)

Not copied Jan Dvorak's CoffeeScript solution, but after many attempts my code ended looking like an exact copy. A subconscious voice probably kept whispering “follow the white rabbit Jan Dvorak”. So upvotes for the algorithm should go to his answer.

$_.gsub!(/\S+/){|m|l=m.scan r=/[a-z]/i;m.gsub(r){|c|l.pop.send c<?a?:upcase: :downcase}}

Sample run:

bash-4.2$ ruby -p reverse-word.rb <<< "Hello, I am a fish.
This; Is Some Text!
Don't touch that!
S'm00ch1e"
Olleh, I ma a hsif.
Siht; Si Emos Txet!
Tno'd hcuot taht!
E'h00cm1s
\$\endgroup\$
0
\$\begingroup\$

Lua, 143

print(((io.read"*l"):gsub("%w+",function(s)local r=""for i=1,#s do r=("")[s:byte(-i)>96 and"lower"or"upper"](s:sub(i,i))..r end return r end)))
\$\endgroup\$
  • \$\begingroup\$ Nice try, but it should also keep punctuation in place: pastebin.com/X8QLf6fW \$\endgroup\$ – manatwork Apr 8 '13 at 10:08
  • \$\begingroup\$ EDIT: oh i see now \$\endgroup\$ – mniip Apr 8 '13 at 19:24
-1
\$\begingroup\$

EcmaScript 6 (112 characters)

The input is provided in s.

alert(s.replace(/\S+/g,x=>(_=x.match(X=/[a-z]/gi),x.replace(X,a=>_.pop()[(a<"a"?"toUpp":"toLow")+"erCase"]()))))

Based on @Jan Dorvak's answer.

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

C# (375)

 public static string rev(string s)
    {
        var r = new Regex("[^A-za-z]");

        var result = "";
        var token = "";
        foreach (var c in s)
        {
            if (!r.IsMatch(c + ""))
            {
                token += c;
            }
            else
            {
                result += new string(token.Reverse().ToArray());
                result += c;
                token = "";
            }
        }

        var arr = result.ToArray();
        int i = 0;
        foreach (var c in s)
        {
            arr[i] = char.IsUpper(c) ? char.ToUpper(arr[i]) : char.ToLower(arr[i]);
            i++;
        }

        result = new string(arr);
        return result;
    }

Minified

public static string rev(string s){var r=new Regex("[^A-za-z]");var result="";var token="";foreach(var c in s){if(!r.IsMatch(c+"")){token+=c;}else{result+=new string(token.Reverse().ToArray());result+=c;token="";}}var arr=result.ToArray();int i=0;foreach(var c in s){arr[i]=char.IsUpper(c)?char.ToUpper(arr[i]):char.ToLower(arr[i]);i++;}result=new string(arr);return result;}
\$\endgroup\$
  • \$\begingroup\$ Shouldn't it be A-Za-z? \$\endgroup\$ – Cyoce Feb 27 '16 at 20:30
  • \$\begingroup\$ @Cyoce A little detail: [A-z] is not [A-Za-z]. The first one is a common (?) mistake, 'cause it contains non-alphabetic characters. \$\endgroup\$ – Erik the Outgolfer Apr 26 '16 at 18:06
  • 1
    \$\begingroup\$ Also shouldn't this be, erm, golfed? \$\endgroup\$ – Cyoce Apr 28 '16 at 22:01

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.