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\$
18
  • 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\$ Apr 7, 2013 at 4:39
  • 2
    \$\begingroup\$ @dmckee "(Punctuation means any characters that are not a-z, A-Z, 1-9 or whitespace)" \$\endgroup\$ Apr 7, 2013 at 4:46
  • 1
    \$\begingroup\$ @dmckee so it should map to Nod't hcuot tath! \$\endgroup\$ Apr 7, 2013 at 4:49
  • 2
    \$\begingroup\$ Reversing each word is easy. Reversing each word and keeping capitalisation is not. \$\endgroup\$ Apr 7, 2013 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, 2013 at 4:56

7 Answers 7

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\$
2
  • \$\begingroup\$ That online golfscript editor looks useful. Bookmarking, thanks \$\endgroup\$ Apr 7, 2013 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\$ Apr 10, 2013 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\$
2
  • \$\begingroup\$ Shouldn't APL be counted in UTF-8 bytes? :-) \$\endgroup\$ Apr 7, 2013 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, 2013 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\$
2
  • \$\begingroup\$ Nice try, but it should also keep punctuation in place: pastebin.com/X8QLf6fW \$\endgroup\$
    – manatwork
    Apr 8, 2013 at 10:08
  • \$\begingroup\$ EDIT: oh i see now \$\endgroup\$
    – mniip
    Apr 8, 2013 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\$
3
  • \$\begingroup\$ Shouldn't it be A-Za-z? \$\endgroup\$
    – Cyoce
    Feb 27, 2016 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\$ Apr 26, 2016 at 18:06
  • 1
    \$\begingroup\$ Also shouldn't this be, erm, golfed? \$\endgroup\$
    – Cyoce
    Apr 28, 2016 at 22:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.