37
\$\begingroup\$

The goal here is to simply reverse a string, with one twist:
Keep the capitalization in the same places.

Example Input 1: Hello, Midnightas
Example Output 1: SathginDim ,olleh

Example Input 2: .Q
Exmaple Output 2: q.

Rules:

  • Output to STDOUT, input from STDIN
  • The winner will be picked 13th of July on GMT+3 12:00 (One week)
  • The input may only consist of ASCII symbols, making it easier for programs that do not use any encoding that contains non-ASCII characters.
  • Any punctuation ending up in a position where there was an upper-case letter must be ignored.
\$\endgroup\$
3
  • \$\begingroup\$ Is that with or without the outprinting? Is that with or without the string? \$\endgroup\$
    – user44904
    Jul 6, 2016 at 14:08
  • \$\begingroup\$ "Any punctuation ending up in a position where there was an upper-case letter must be ignored.", isn't the second example inconsistent with this rule? \$\endgroup\$ Aug 19, 2016 at 13:10
  • \$\begingroup\$ It is consistent with the rule because punctuations do not have an uppercase variation. \$\endgroup\$
    – user47018
    Aug 19, 2016 at 14:13

44 Answers 44

16
\$\begingroup\$

Python, 71 bytes

lambda s:''.join((z*2).title()[c.isupper()-1]for c,z in zip(s,s[::-1]))

Try it online

-3 bytes from Ruud, plus the inspiration for 2 more.

-4 more bytes from FryAmTheEggman

\$\endgroup\$
6
  • \$\begingroup\$ lambda s:''.join([z.lower(),z.upper()][c.isupper()]for c,z in zip(s,s[::-1])) is three bytes shorter \$\endgroup\$
    – Arfie
    Jul 6, 2016 at 13:03
  • 1
    \$\begingroup\$ @Ruud Thanks! Moving the function call to outside of the list selection saves 2 more! \$\endgroup\$
    – user45941
    Jul 6, 2016 at 13:06
  • 2
    \$\begingroup\$ (z*2).title()[c.isupper()-1] should work. \$\endgroup\$ Jul 6, 2016 at 15:10
  • 8
    \$\begingroup\$ You could win another byte with ~c.isupper() instead of c.isupper()-1 \$\endgroup\$
    – Lulhum
    Jul 6, 2016 at 18:01
  • \$\begingroup\$ This doesn't get input from stdin or output to stdout... \$\endgroup\$ Jul 7, 2016 at 16:11
13
\$\begingroup\$

Python 2, 73 bytes

Since the rules specify the input is ascii:

lambda s:''.join([z.lower,z.upper]['@'<c<'[']()for c,z in zip(s,s[::-1]))

All the credit goes to @Mego though, but I had not the reputation to just comment on his answer.

\$\endgroup\$
3
  • \$\begingroup\$ Can you use the ascii value of '@' and '[' to gain 2 bytes? \$\endgroup\$
    – aloisdg
    Jul 6, 2016 at 17:17
  • \$\begingroup\$ Unfortunately no, I'd have to use ord(c), integer and string comparison do not cope very well in Python \$\endgroup\$
    – Lulhum
    Jul 6, 2016 at 17:50
  • \$\begingroup\$ Pretty much what I got, but you were first +1 \$\endgroup\$
    – orlp
    Jul 6, 2016 at 19:20
13
\$\begingroup\$

Perl, 31 + 2 (-lp) = 33 bytes

This solution is from @Ton Hospel (13 bytes shorter thant mine).

s%.%(lc$&gt$&?u:l)."c chop"%eeg

But you'll need l and p switches on. To run it :

perl -lpe 's%.%(lc$&gt$&?u:l)."c chop"%eeg'
\$\endgroup\$
7
  • 5
    \$\begingroup\$ Hello, and welcome to PPCG! This is great! \$\endgroup\$ Jul 6, 2016 at 14:41
  • \$\begingroup\$ Very nice indeed! I've never used-a autosplit, I feel I could have used this many times in the past! I need to remember that! I think you can save another byte using map...,... instead of map{...}... as you have $F at the start though! :) \$\endgroup\$ Jul 7, 2016 at 7:33
  • \$\begingroup\$ Shorter code (31+2 bytes): perl -lpe 's%.%(lc$&gt$&?u:l)."c chop"%eeg \$\endgroup\$
    – Ton Hospel
    Aug 17, 2016 at 21:39
  • \$\begingroup\$ Notice that -a is implied by -F \$\endgroup\$
    – Ton Hospel
    Aug 17, 2016 at 21:43
  • \$\begingroup\$ @TonHospel wow, thank you very much and well done, that's some quite nice code! About -a (and -n) being implied by -F, I read it a while ago on perlrun, tried it, but it didn't work; but I tried it again now and it works fine so I'm guessing I did something wrong back then. Thanks. \$\endgroup\$
    – Dada
    Aug 18, 2016 at 15:48
9
\$\begingroup\$

Pyth, 13 11 10 9 bytes

Thanks to @FryAmTheEggman for reminding me about V and @LeakyNun for another byte.

srV_Qm!/G

Try it online! now on mobile, updating link in a bit

\$\endgroup\$
3
  • \$\begingroup\$ srV_Qm!rId0 is 11, but I think it might be possible to shorten that map... \$\endgroup\$ Jul 6, 2016 at 13:45
  • \$\begingroup\$ @FryAmTheEggman Remove the d and you saved a byte. \$\endgroup\$
    – Leaky Nun
    Jul 6, 2016 at 22:42
  • \$\begingroup\$ srV_Qm!/G should save a byte \$\endgroup\$
    – Leaky Nun
    Jul 6, 2016 at 22:45
8
\$\begingroup\$

Python, 66 bytes

f=lambda s,i=0:s[i:]and(s[~i]*2).title()[~('@'<s[i]<'[')]+f(s,i+1)

Recurses through the indices i, taking the character s[~i] from the back and the case of s[i] from the front. Being capital is checked as lying in the contiguous range @ABC...XYZ[. Credit to FryAmTheEggman from the (_*2).title() trick.

\$\endgroup\$
6
\$\begingroup\$

TCC - 4 bytes

<>ci

Try it online!

Explanation:

     - output is implicit in TCC
<>   - reverse string
  c  - preserve capitalization
   i - get input
\$\endgroup\$
1
  • \$\begingroup\$ The link to the online interpreter is dead. I don't even know where this language is anymore \$\endgroup\$
    – Jo King
    Sep 3, 2022 at 5:19
5
\$\begingroup\$

Retina, 75 67 65 bytes

Byte count assumes ISO 8859-1 encoding.

$
±·$`
O$^`\G[^·]

s{T`L`l`±.
T01`l`L`±.*·[A-Z]
±·

±(.)
$1±
·.
·

Try it online! (The first line enables a test suite with multiple linefeed-separated test cases.)

\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 95 83 bytes

s=>[...t=s.toLowerCase()].reverse().map((c,i)=>s[i]==t[i]?c:c.toUpperCase()).join``

Edit: Saved a massive 12 bytes thanks to @edc65.

\$\endgroup\$
2
  • \$\begingroup\$ s=>r=[...l=s.toLowerCase()].reverse().map((c,i)=>s[i]!=l[i]?c.toUpperCase():c).join`` -10 \$\endgroup\$
    – edc65
    Jul 6, 2016 at 15:02
  • \$\begingroup\$ @edc65 Thanks! (Note: the r= is unnecessary.) \$\endgroup\$
    – Neil
    Jul 6, 2016 at 15:15
5
\$\begingroup\$

Pyke, 11 10 9 bytes

_FQo@UhAl

Try it here!

_         -   reversed(input)
 F        -  for i in ^
   o      -      o+=1
  Q @     -     input[^]
     Uh   -    ^.is_upper()+1
       Al -   [len, str.lower, str.upper, ...][^](i)
          - "".join(^)
\$\endgroup\$
4
  • \$\begingroup\$ It first gave me an error, then at the same time the correct answer. i.imgur.com/uTcH27F.png \$\endgroup\$
    – user47018
    Jul 10, 2016 at 8:48
  • \$\begingroup\$ That always happens, you can click disable warnings to turn that off. \$\endgroup\$
    – Blue
    Jul 10, 2016 at 8:49
  • \$\begingroup\$ Aha, okay. Sorry, I'm not good with Pyke \$\endgroup\$
    – user47018
    Jul 10, 2016 at 8:50
  • \$\begingroup\$ Might be because I'm the only guy using it \$\endgroup\$
    – Blue
    Jul 10, 2016 at 8:50
4
\$\begingroup\$

J, 30 bytes

(={"_1 toupper@]|.@,.])tolower

Doesn't support non-ASCII

\$\endgroup\$
3
  • \$\begingroup\$ "toupper" "tolower" can't you use code points to shorten it? \$\endgroup\$
    – Leaky Nun
    Jul 6, 2016 at 22:50
  • \$\begingroup\$ @LeakyNun Maybe but I can't really say for sure \$\endgroup\$
    – miles
    Jul 6, 2016 at 23:40
  • \$\begingroup\$ @LeakyNun It's surprising, but I think it's very unlikely this should could be shortened in J. \$\endgroup\$
    – Jonah
    Oct 14, 2022 at 4:32
4
\$\begingroup\$

05AB1E, 19 16 15 13 bytes

Thanks to Emigna for saving a 3 bytes!

Probably gonna get beat by Jelly... Code:

Âuvy¹Nè.lil}?

Uses the CP-1252 encoding. Try it online!.

\$\endgroup\$
6
  • \$\begingroup\$ S.l_v¹lRNèyiu}? is 1 byte shorter \$\endgroup\$
    – Emigna
    Jul 6, 2016 at 13:07
  • \$\begingroup\$ @Emigna Wow thanks! That is very clever. \$\endgroup\$
    – Adnan
    Jul 6, 2016 at 13:13
  • \$\begingroup\$ Âuvy¹Nè.lilë}? is 14. Just happy I can help you for once :) \$\endgroup\$
    – Emigna
    Jul 6, 2016 at 13:16
  • \$\begingroup\$ @Emigna That is amazing! Very nice use of bifurcate :). \$\endgroup\$
    – Adnan
    Jul 6, 2016 at 13:20
  • \$\begingroup\$ Ruvy¹Nè.lil}? actually. I didn't use the bifurcation and forgot to remove the else. So 13. \$\endgroup\$
    – Emigna
    Jul 6, 2016 at 13:21
4
\$\begingroup\$

Brachylog, 28 bytes

@lr:?z:1ac.
h@u.,@A@um~t?|h.

Explanation

  • Main Predicate:

    @lr                 Reverse the lowercase version of the Input
       :?z              Zip that reversed string with the Input
          :1a           Apply predicate 1 to each couple [char i of reverse, char i of Input]
             c.         Output is the concatenation of the result
    
  • Predicate 1:

    h@u.,               Output is the uppercase version of the first char of Input
         @A@um~t?       The second char of Input is an uppercase letter
                 |      Or
                  h.    Output is the first char of Input
    
\$\endgroup\$
4
\$\begingroup\$

MATL, 13 bytes

PktGtk<)Xk5M(

Try it online!

Pk      % Implicit inpput. Flip, lowercase
t       % Duplicate
Gtk<    % Logical index of uppercase letters in the input string
)       % Get letters at those positions in the flipped string
Xk      % Make them uppercase
5M(     % Assign them to the indicated positions. Implicit display
\$\endgroup\$
3
\$\begingroup\$

TSQL, 175 bytes

Golfed:

DECLARE @ varchar(99)='Hello, Midnightas'

,@o varchar(99)='',@i INT=0WHILE @i<LEN(@)SELECT
@i+=1,@o+=IIF(ascii(x)=ascii(lower(x)),lower(y),upper(y))FROM(SELECT
SUBSTRING(@,@i+1,1)x,SUBSTRING(@,len(@)-@i,1)y)z
PRINT @o

Ungolfed

DECLARE @ varchar(99)='Hello, Midnightas'

,@o varchar(99)=''
,@i INT=0

WHILE @i<LEN(@)
  SELECT @i+=1,@o+=IIF(ascii(x)=ascii(lower(x)),lower(y),upper(y))
  FROM
    (SELECT SUBSTRING(@,@i+1,1)x,SUBSTRING(@,len(@)-@i,1)y)z

PRINT @o

Fiddle

\$\endgroup\$
4
  • \$\begingroup\$ hardcoding the input ? \$\endgroup\$
    – cat
    Jul 6, 2016 at 18:15
  • \$\begingroup\$ @cat that is the only way. In sql, there is no STDIN or input command. If you look at stackoverflow that is how all the questions are solved - you can also look at my other answers on codegolf \$\endgroup\$ Jul 6, 2016 at 19:41
  • \$\begingroup\$ Oh, yeah, I definitely remember having this conversation wih a SQL user before (you, maybe). That's weird, but should be fine. \$\endgroup\$
    – cat
    Jul 6, 2016 at 19:44
  • 1
    \$\begingroup\$ @cat we have not had this conversation before, but you did help me with a byte count earlier \$\endgroup\$ Jul 6, 2016 at 19:56
3
\$\begingroup\$

Actually, 25 bytes

;`úíuY"ùû"E£`M@ùRZ`i@ƒ`MΣ

Try it online!

Explanation:

;`úíuY"ùû"E£`M@ùRZ`i@ƒ`MΣ
;                          create a copy of the input
 `úíuY"ùû"E£`M             for each character in input:
  úíuY                       0-based index in lowercase English letters, or -1 if not found, increment, boolean negate (1 if uppercase else 0)
      "ùû"E£                 `û` if the character is lowercase else `ù` (str.lower vs str.upper)
              @ùRZ         make the other copy of the input lowercase, reverse it, and zip it with the map result
                  `i@ƒ`M   for each (string, function) pair:
                   i@ƒ       flatten, swap, apply (apply the function to the string)
                        Σ  concatenate the strings
\$\endgroup\$
3
\$\begingroup\$

Haskell, 83 80 75 71 bytes

The most straightforward way I could think of.

import Data.Char
f a|isUpper a=toUpper|1>0=toLower
zipWith f<*>reverse
\$\endgroup\$
6
  • \$\begingroup\$ If you swap the parameters of (#), k can be rewritten in point-free style: k=reverse>>=zipWith(#), that saves a couple bytes :) \$\endgroup\$
    – Flonk
    Jul 6, 2016 at 18:53
  • \$\begingroup\$ The second line can be point-free in b as f a|isUpper a=toUpper|1>0=toLower, though this conflicts with Flonk's improvement. \$\endgroup\$
    – xnor
    Jul 6, 2016 at 19:23
  • \$\begingroup\$ You can use xnor's version of f and rewrite Flonk's k to zipWith f<*>reverse. \$\endgroup\$
    – nimi
    Jul 6, 2016 at 19:39
  • \$\begingroup\$ Don’t you need to eliminate the parameter s? \$\endgroup\$
    – Lynn
    Jul 6, 2016 at 20:17
  • \$\begingroup\$ Yes, and you're also allowed to cut the k=. \$\endgroup\$
    – xnor
    Jul 6, 2016 at 20:17
3
\$\begingroup\$

PowerShell, 154, 152, 99, 86 bytes

Thank you @TimmyD for saving me a whopping 47 bytes (I also saved an additional 6)

Thank you @TessellatingHeckler for saving an additional 13 bytes.

Latest:

param($a)-join($a[$a.length..0]|%{("$_".ToLower(),"$_".ToUpper())[$a[$i++]-in65..90]})

Original:

param($a);$x=0;(($a[-1..-$a.length])|%{$_=$_.tostring().tolower();if([regex]::matches($a,"[A-Z]").index-contains$x){$_.toupper()}else{$_};$x++})-join''

Normal formatting:

Latest (looks best as two lines in my opinion):

param($a)
-join($a[$a.length..0] | %{("$_".ToLower(), "$_".ToUpper())[$a[$i++] -in 65..90]})

Explanation:

param($a)-join($a[$a.length..0]|%{("$_".ToLower(),"$_".ToUpper())[$a[$i++]-in65..90]})
param($a)
# Sets the first passed parameter to variable $a
         -join(                                                                      )
# Converts a char array to a string
               $a[$a.length..0]
# Reverses $a as a char array
                               |%{                                                  }
# Shorthand pipe to foreach loop
                                  ("$_".ToLower(),"$_".ToUpper())
# Creates an array of the looped char in lower and upper cases
                                                                 [$a[$i++]-in65..90]
# Resolves to 1 if the current index of $a is upper, which would output "$_".ToUpper() which is index 1 of the previous array

Original:

param($a)
$x = 0
(($a[-1..-$a.length]) | %{
    $_ = $_.tostring().tolower()
    if([regex]::matches($a,"[A-Z]").index -contains $x){
            $_.toupper()
        }else{
            $_
        }
        $x++
    }
) -join ''

First time poster here, was motivated because I rarely see PowerShell, but at 154 152 bytes on this one... I can see why! Any suggestions appreciated.

I have learned that I must completely change my way of thinking to golf in code and its fun!

\$\endgroup\$
5
  • \$\begingroup\$ Hello, and welcome to PPCG! This is great! \$\endgroup\$ Jul 6, 2016 at 22:45
  • \$\begingroup\$ Welcome to PPCG! Nice to see another PowerShell user around here. You can cut out quite a bit by replacing the .tostring() with quotes, and by using ASCII integer manipulation rather than regex. Try the following, for 105 bytes -- param($a)-join($a[$a.length..0]|%{if(($x=$a[$i++])-le90-and$x-ge65){"$_".ToUpper()}else{"$_".ToLower()}}). \$\endgroup\$ Jul 11, 2016 at 15:07
  • \$\begingroup\$ Brilliant! We can make that even shorter by using a range instead of -le and -ge: param($a)-join($a[$a.length..0]|%{if(65..90-contains$a[$i++]){"$_".ToUpper()}else{"$_".ToLower()}}) \$\endgroup\$ Jul 11, 2016 at 15:49
  • \$\begingroup\$ X-inY is shorter than Y-containsX, and you can change your if for the fake ternary operator to get 86 bytes - param($a)-join($a[$a.length..0]|%{("$_".ToLower(),"$_".ToUpper())[$a[$i++]-in65..90]}) \$\endgroup\$ Jul 12, 2016 at 0:50
  • \$\begingroup\$ Man, I feel like I've missed out on a lot of tricks having never code golfed before. Its almost like learning to code all over again! \$\endgroup\$ Jul 12, 2016 at 15:46
2
\$\begingroup\$

Dyalog APL, 12 bytes

⌽f¨⍨⊢≠f←819⌶

819⌶ is the case folding function

f← because its name is long, we assign it to f

⊢≠f Boolean where text differs from lower-cased text

f¨⍨ use that (1 means uppercase, 0 means lowercase) to fold each letter...

... of the reversed text

Handles non-ASCII according to the Unicode Consortium's rules.

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

CJam, 22 bytes

q_W%.{el\'[,65>&{eu}&}

Test it here.

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

Racket, 146 bytes

(λ(s)(build-string(string-length s)(λ(n)((if(char-upper-case?(string-ref s n))char-upcase char-downcase)(list-ref(reverse(string->list s))n)))))

Racket is bad at this whole "golfing" thing.

Shrug As always, any help with shortening this would be much appreciated.

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

Jolf, 21 bytes

Try it here!

Μid?&γ._pXiS=pxHHpxγγ

Explanation

Μid?&γ._pXiS=pxHHpxγγ
Μid                   (Μ)ap (i)nput with (d)is fucntion:
   ?        =pxHH     (H is current element) if H = lowercase(H)
    &γ._pXiS          and set γ to the uppercase entity in the reversed string
                 pxγ  lowercase γ
                    γ else, return γ
\$\endgroup\$
1
  • \$\begingroup\$ (d)is function... Sacrifice spelling for the sake of golf! \$\endgroup\$
    – Steven H.
    Jul 6, 2016 at 22:14
2
\$\begingroup\$

Perl 6, 29 bytes

$_=get;put .flip.samecase($_)
\$\endgroup\$
2
\$\begingroup\$

C#, 86 85 bytes

s=>string.Concat(s.Reverse().Select((c,i)=>s[i]>96?char.ToLower(c):char.ToUpper(c)));

A C# lambda where the input and the output is a string. You can try it on .NetFiddle.


I am struggling to understand why I cant achieve to convert char.ToLower(c) to c+32. I hope to fix it!

12 bytes saved thanks to @PeterTaylor (c|32 to add 32 to the ascii value of c and c&~32 to substract 32). The result would be 72 bytes (but can fail on non alpha char).

s=>string.Join("",s.Reverse().Select((c,i)=>(char)(s[i]>96?c|32:c&~32)));
\$\endgroup\$
2
  • 1
    \$\begingroup\$ It would be c|32 instead of c+32, but it won't work with non-alpha characters. \$\endgroup\$ Jul 6, 2016 at 16:53
  • \$\begingroup\$ @PeterTaylor It works great! Thank you! \$\endgroup\$
    – aloisdg
    Jul 6, 2016 at 17:12
2
\$\begingroup\$

Vyxal r, 9 2 bytes

Ṙ•

Try it online!

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

Julia 1.0, 73, 65 64 bytes

!s=prod(titlecase(s[end-i+1]^2)[2-('@'<s[i]<'[')] for i=keys(s))

Try it online!

-9 MarcMush

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

Jelly, 13 10 bytes

ŒlðUŒuT}¦n

Try it online!

Did I say this was extremely golfable by someone who understands ¦? Turns out it's just understanding anything at all about chaining in general.

Œl            Lowercase the input,
   U          reverse it,
    Œu        then uppercase it
      T}¦     at indices where
  ð      n    the lowercase input doesn't equal the original input.
\$\endgroup\$
2
\$\begingroup\$

C (gcc), 139 bytes

#define B v[c+~i]
#define C(x,y)isupper(x)?toupper(y):tolower(y)
i,t,c;f(char*v){for(c=strlen(v);i<c/2;i++)t=C(B,v[i]),v[i]=C(v[i],B),B=t;}

Try it online!

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

Julia 1.0, 114 92 78 bytes

~x=(b=reverse(lowercase(x));prod(i->b[i]-32('@'<x[i]<'['<b[i]-5<'v'),keys(b)))

Try it online!

  • -22 bytes thanks to amelies: use prod
  • -10 bytes thanks to MarcMush: avoid uppercase and isuppercase
  • -4 bytes thanks to MarcMush: use keys(b) instead of 1:length(b)
\$\endgroup\$
2
1
\$\begingroup\$

PHP, 128 bytes

$s=$argv[1];$l=strrev($s);for($i=0;$i<strlen($s);++$i){echo(strtolower($s[$i])!==$s[$i]?strtoupper($l[$i]):strtolower($l[$i]));}

I may attempt to optimize this further but I'll just leave it as is for now.

\$\endgroup\$
1
  • \$\begingroup\$ As notices are allowed, there are a few parts you can optimize at. Instead of a for loop, you can do a while loop and set the char to test directly: while($a=ord($s[$i++])). With that, as we use ord() you can test based on the char number: $a<90&&$a>65. However, for the strtoupper and lower you need to correct the index number as in the loop it was already increased, this means: strtolower($l[$i-1]). This should save quite some bytes \$\endgroup\$
    – RFSnake
    Sep 10, 2020 at 11:27
1
\$\begingroup\$

Octave, 51 50 bytes

@(s)merge(isupper(s),b=flip(toupper(s)),tolower(b))

@(s)merge(s>64&s<91,b=flip(toupper(s)),tolower(b))
\$\endgroup\$

Your Answer

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