37
\$\begingroup\$

Given two strings of letters, transfer the capitalization pattern of each string onto the other one. Fewest bytes wins.

Input:   CodeGolf xxPPCGxx  
Output:  coDEGOlf XxppCgxx
  • Both strings will be equal-length and nonempty, with only letters a..z and A..Z.
  • You may output the two resulting strings in either order relative to the inputs.
  • You may represent a pair of strings as one string with a non-letter single-character separator for input and/or output.
  • You may represent a string as a list of characters or one-character strings, but not as a sequence of code point values unless these are simply strings in your language.
  • Your input and output may represent strings differently.

Test cases:

CodeGolf xxPPCGxx -> coDEGOlf XxppCgxx
lower UPPER -> LOWER upper
MiXeD lower -> mixed LoWeR
A A -> A A
ABcd EfGh -> AbCd EFgh
\$\endgroup\$
0

28 Answers 28

15
\$\begingroup\$

Java (JDK 10), 66 bytes

a->b->{for(int i=a.length,t;i-->0;b[i]^=t)a[i]^=t=(a[i]^b[i])&32;}

Try it online!

Explanations

a->b->{                           // Curried lambda
 for(int i=a.length,t;i-->0;      //  Descending loop on i,
                                  //  Declare t
     b[i]^=t                      //   Apply the case difference to b[i]
   )
  a[i]^=t=(a[i]^b[i])&32;         //   Assign the case difference of the two letters to t, and apply it to a[i].
}
\$\endgroup\$
10
  • 11
    \$\begingroup\$ Completely unrelated to this answer of yours, but it's easier than creating a chat. ;p Did you notice the Java-10 TIO has a bug when using array[i++%n]+=...;? array[t=i++%n]=array[t]+...; works fine; and array[i%n]+=...;i++; works fine as well, but using i++ or ++i with a modulo and += to append to a row in an array doesn't work.. Here a Java 10 TIO as example to see the problem. Is this a bug (or feature :S) in the Java 10 JDK or in the Java 10 TIO compiler? \$\endgroup\$ Jun 4, 2018 at 13:26
  • 1
    \$\begingroup\$ @KevinCruijssen I see the issue, but it seems weird. I see that the version used on TIO is 10.0.0_46 (of 20-03-2018). The latest version is 10.0.1. We should probably ask TIO to update their version of Java. \$\endgroup\$ Jun 4, 2018 at 13:42
  • 3
    \$\begingroup\$ @KevinCruijssen Dennis updated the version to 10.0.1 and the issue is still happening (I don't have Java 10 installed yet so I rely on TIO, just like you). I've asked on Stack Overflow as I just don't know what happens here... It's baffling! \$\endgroup\$ Jun 4, 2018 at 15:18
  • 5
    \$\begingroup\$ @KevinCruijssen It's ok, it's not like this answer attracts a lot of upvotes :P Anyways... The thing is that you actually found a bug. Since the spec says it should be acting as you would think it does, keep writing your answer that way, optimized for Java 10 if you require so. That way, you have a valid Java 10 answer, but untestable because of that bug. Just write it and test it in Java 8, then make the proper Java 10 changes like changing String to var. \$\endgroup\$ Jun 4, 2018 at 19:40
  • 6
    \$\begingroup\$ I think it's really neat that you found a bug in JDK 10. Good job :] \$\endgroup\$
    – Poke
    Jun 5, 2018 at 19:42
13
\$\begingroup\$

C (gcc), 86 58 55 53 bytes

c(a,s,e)char*a,*s;{for(;*s++^=e=(*s^*a)&32;)*a++^=e;}

Try it online!

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

Jelly, 9 bytes

O&32^/^OỌ

Try it online!

How it works

O&32^/^OỌ  Main link. Argument: [s, t] (pair of strings)

O          Ordinal; replace each character with its code point.
 &32       Perform bitwise AND with 32, yielding 32 for lowercase letters, 0 for
           uppercase ones.
    ^/     Reduce by XOR, yielding 32 for letter pairs with different 
           capitalizations, 0 for letter pair with matching capitalizations.
      ^O   XOR the result with each of the code points.
        Ọ  Unordinal; replace each code point with its character.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ ...we knew it was gonna happen :D \$\endgroup\$ Jun 2, 2018 at 20:01
7
\$\begingroup\$

APL (Dyalog Classic), 13 12 bytes

⊖⊖819⌶¨⍨∊∘⎕a

Try it online!

input and output is a 2×N character matrix

⎕a is the uppercase English alphabet 'ABC...Z'

∊∘⎕a returns a boolean matrix indicating which letters in the input are uppercase

819⌶ converts its right argument to uppercase or lowercase depending on its boolean left argument ("819" is leetspeak for "BIG")

819⌶¨⍨ does that for each (¨) character, swapping () the arguments

means reverse vertically; one acts as the left argument to 819⌶ and the other is the final action

\$\endgroup\$
2
  • 1
    \$\begingroup\$ "819" is leetspeak for "BIG" ... Seriously? That's the actual explanation for why it's 819? 0_o \$\endgroup\$
    – DLosc
    Jun 4, 2018 at 4:34
  • \$\begingroup\$ @DLosc yes :) see chat \$\endgroup\$
    – ngn
    Jun 4, 2018 at 4:44
6
\$\begingroup\$

Pyth, 10 bytes

rVV_mmrIk1

Try it here!

Explanation & neat Pyth tricks used

  • rVV_mmrIk1 — Full program. Input is taken from STDIN as a list of two strings, and the output is written to STDOUT as a list of two lists of characters.

  • mm — For each character in each of the strings:

    • Ik — Check if it is invariant under...
    • r...1 — ... Converting to uppercase. Yields True for uppercase characters and False for lowercase ones.
  • _ — Reverse that list.

  • VV — And double-vectorize the following function over the two lists:

    • r — Convert to uppercase if the value is True (aka 1), else convert to lowercase.

This submission abuses the fact that r0 and r1 are the lowercase and uppercase functions in Pyth, and we use truth values (the values obtained by checking if each character is uppercase, reversed) yielding True for uppercase and False for lowercase. The fact that booleans are subclasses of integers in Python is very handy for the approach this answer is using. Porting Dennis and Jonathan's Jelly approaches both resulted in more than 18 bytes, so I am quite happy with the Pyth-specific tricks used here.

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

MATL, 11 bytes

kG91<P32*-c

Try it online! Or verify all test cases.

Explanation

k      % Implicit input: 2-row char matrix. Convert to lower-case
G      % Push input again 
91<    % Less than 91?, element-wise. Gives 1 for upper-case
P      % Flip vertically
32*    % Multiply by 32, element-wise
-      % Subtract, element-wise
c      % Convert to char. Implicit display
\$\endgroup\$
4
\$\begingroup\$

Haskell, 78 bytes

import Data.Char
c x|isUpper x=toUpper|1<2=toLower
(!)=zipWith c
x#y=(y!x,x!y)

Try it online!

\$\endgroup\$
1
  • 4
    \$\begingroup\$ isUpper x can be x<'a'. \$\endgroup\$
    – Lynn
    Jun 3, 2018 at 15:44
4
\$\begingroup\$

x86-64 machine code, 14 bytes

Callable from C (x86-64 SysV calling convention) with this prototype:

void casexchg(char *rdi, char *rsi);  // modify both strings in place

An explicit-length version with length in rcx is the same size. void casexchg(char *rdi, char *rsi, int dummy, size_t len);


This uses the same bit-exchange algo as the C and Java answers: If both letters are the same case, neither needs to change. If they're opposite case, they both need to change.

Use XOR to diff the case bit of the two strings. mask = (a XOR b) AND 0x20 is 0 for same or 0x20 for differing. a ^= mask; b ^= mask caseflip both letters iff they were opposite case. (Because the ASCII letter codes for upper and lower differ only in bit 5.)

NASM listing (from nasm -felf64 -l/dev/stdout). Use cut -b 26- <casexchg.lst >casexchg.lst to turn this back into something you can assemble.

   addr    machine
 6         code          global casexchg
 7         bytes         casexchg:
 8                       .loop:
 9 00000000 AC               lodsb                ; al=[rsi] ; rsi++
10 00000001 3207             xor   al, [rdi]
11 00000003 2420             and   al, 0x20       ; 0 if their cases were the same: no flipping needed
12                       
13 00000005 3007             xor   [rdi], al      ; caseflip both iff their cases were opposite
14 00000007 3046FF           xor   [rsi-1], al
15                       
16 0000000A AE               scasb                ; cmp al,[rdi] / inc rdi
17                           ; AL=0 or 0x20.
18                           ; At the terminating 0 in both strings, AL will be 0 so JNE will fall through.
19                           ; 0x20 is ASCII space, which isn't allowed, so AL=0x20 won't cause early exit
20 0000000B 75F3             jne  .loop
21                       ;    loop  .loop            ; caller passes explict length in RCX
22                       
23 0000000D C3               ret

  size = 0xe bytes = 14
24 0000000E 0E           db $ - casexchg_bitdiff

The slow loop instruction is also 2 bytes, same as a short jcc. scasb is still the best way to increment rdi with a one-byte instruction. I guess we could xor al, [rdi] / stosb. That would be the same size but probably faster for the loop case (memory src + store is cheaper than memory dst + reload). And would still set ZF appropriately for the implicit-length case!

Try it online! with a _start that calls it on argv[1], argv[2] and uses sys_write on the result

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

k, 14 bytes

{`c$l+|x-l:_x}

Try it online! Input/output is a list of two strings.

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

J, 36 31 27 bytes

-9 bytes thanks to FrownyFrog!

(XOR"$32*[:~:/97>])&.(3&u:)

Try it online!

The previous solution was:

J, 36 31 bytes

-5 bytes thanks to FrownyFrog!

|:@(XOR 32*0~:/@|:97>])&.(3&u:)

Try it online!

How it works:

                          (3&u:)  converts the strings to code points
   (                    )&.       then do the following and convert back to chars
                    97>]          check if they are uppercase letters 
             0~:/@|:              transpose and check if the two values are different
          32*                     multiply by 32 (32 if different, 0 otherwise)
      XOR                         xor the code point values with 32 or 0
 |:@                              and transpose
\$\endgroup\$
6
  • \$\begingroup\$ The [: can be 0 and the (22 b.) can be XOR. &.(3&u:) saves 1 byte. \$\endgroup\$
    – FrownyFrog
    Jun 2, 2018 at 22:47
  • \$\begingroup\$ @FrownyFrog Very nice golfs, thank you! You are really good! \$\endgroup\$ Jun 3, 2018 at 7:12
  • \$\begingroup\$ 27 \$\endgroup\$
    – FrownyFrog
    Jun 3, 2018 at 21:09
  • \$\begingroup\$ @FrownyFrog Wow! Can you explain the use of " and $? Thanks! \$\endgroup\$ Jun 4, 2018 at 18:52
  • \$\begingroup\$ The input is done with ,:, there are 2 rows on the left side. We need "(1) but "$ works too, because it stands for "1 _. $ b.0 gives the rank of $ (monadic, dyadic left, dyadic right). \$\endgroup\$
    – FrownyFrog
    Jun 4, 2018 at 22:02
3
\$\begingroup\$

R, 118 94 75 72 bytes

m=sapply(scan(,""),utf8ToInt);w=m>96;apply(m-32*(w-w[,2:1]),2,intToUtf8)

Try it online!

There must be a much golfier way. -43 bytes thanks to Giuseppe who pointed me to the MATL solution by Luis Mendo. TIO link contains a function solution for the same byte count.

m=sapply(a<-scan(,""),utf8ToInt)    # Turns input into a matrix of bytecode (2 columns)
w=m>96                              # Predicate : which chars are lower?
apply(m-32*(w-w[,2:1]),2,intToUtf8) # -32*w turns the string to UPPER
                                    # +32*w[,2:1] swaps capitalization
                                    # intToUtf8 turns bytecode to strings

Bonus: The output is a named vector whose names are the original input strings!

\$\endgroup\$
2
  • \$\begingroup\$ You should be able to drop a<- since you don't use a anywhere else. \$\endgroup\$
    – Giuseppe
    Jun 5, 2018 at 18:03
  • \$\begingroup\$ @Giuseppe Were you reading my mind? ;) \$\endgroup\$
    – JayCe
    Jun 5, 2018 at 18:04
3
\$\begingroup\$

Vyxal , 4 bytes

•??•

Try it Online!

Explanation:

•    # A with the capitalization of B
 ??  # Get both input strings (order ends up reversed)
   • # A with the capitalization of B
     # "ṡ" flag - Print entire stack, separated by spaces
\$\endgroup\$
2
  • \$\begingroup\$ Finally a use for A with the capitalization of B, huh? \$\endgroup\$
    – Alan Bagel
    Nov 30, 2021 at 20:20
  • \$\begingroup\$ @AlanBagel Yep, I've been waiting to use that one for a while. :) \$\endgroup\$ Nov 30, 2021 at 20:21
2
\$\begingroup\$

Python 3, 83 bytes

lambda a,b:(g(a,b),g(b,a))
g=lambda*a:[chr(ord(x)&95|(y>'Z')<<5)for x,y in zip(*a)]

Try it online!

-3 bytes thanks to Mr. Xcoder
-3 bytes thanks to Chas Brown

\$\endgroup\$
2
  • \$\begingroup\$ 83 bytes with a bit of bit-twiddling. \$\endgroup\$
    – Chas Brown
    Jun 2, 2018 at 19:36
  • \$\begingroup\$ @ChasBrown Oh cool, nice. Thanks! \$\endgroup\$
    – hyper-neutrino
    Jun 3, 2018 at 0:50
2
\$\begingroup\$

Haskell, 78 bytes

c!d=([c..'z']++[';'..])!!sum[32|(c>'Z')/=(d>'Z')]
(#)=zipWith(!)
s%t=(s#t,t#s)

Try it online!

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

QBasic, 133 bytes

INPUT a$,b$
FOR i=1TO LEN(a$)
c=ASC(MID$(a$,i,1))
d=ASC(MID$(b$,i,1))
s=32AND(c XOR d)
?CHR$(c XOR s);
r$=r$+CHR$(d XOR s)
NEXT
?
?r$

Takes the two strings comma-separated and outputs the results newline-separated. Uses the bit-fiddling algorithm from Dennis's Jelly answer. Other than that, the main golf trick here is that the first result string is printed directly, one character at a time, which is a little shorter than saving both result strings in variables and printing them outside the loop.

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

JavaScript, 77 74 73 bytes

W=>W.map((w,x)=>w.map((c,i)=>W[+!x][i][`to${c>{}?'Low':'Upp'}erCase`]()))

f=
W=>W.map((w,x)=>w.map((c,i)=>W[+!x][i][`to${c>{}?'Low':'Upp'}erCase`]()))

console.log(
    f([[...'CodeGolf'],[...'xxPPCGxx']])
)

Takes an array of char arrays, outputs an array of char arrays.

-1 byte (@Arnauld): c>'Z'c>{}

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can save a byte with c>{}. \$\endgroup\$
    – Arnauld
    Jun 3, 2018 at 22:10
1
\$\begingroup\$

Jelly, 13 bytes

=Œu=/ị"Ɱż"Œs$

Try it online!

Also 13: =ŒuṚ×32ạŒlO$Ọ (or =ŒuṚæ«5ạŒlO$Ọ)

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

Retina, 75 bytes

^
¶
+`¶(([A-Z])|(.))(.*)¶(([A-Z])|(.))
$#6*$u$1$#7*$l$1¶$4$#2*$u$5$#3*$l$5¶

Try it online! Explanation: The newlines are used as markers to determine how much of the string has been processed. The regex tries to match against uppercase letters or failing that any characters. If an uppercase letter was matched then the other character is uppercased otherwise it is lowercased and vice versa, while the newlines are advanced to the next character.

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

Python 3, 76 75 bytes

lambda a,b:''.join(chr(ord(x)&95|ord(y)&32)for x,y in zip(a+' '+b,b+'a'+a))

Try it online!

Outputs the result as one string with a single-character separator.

Thx to Jonathon Allan for 1 byte.

\$\endgroup\$
1
  • \$\begingroup\$ (y>'Z')*32 -> ord(y)&32 \$\endgroup\$ Jun 2, 2018 at 20:29
1
\$\begingroup\$

Crystal, 108 bytes

def f(a,b)r=s=""
a.zip(b){|x,y|r+="`"<x<"{"?y.downcase: y.upcase
s+="`"<y<"{"?x.downcase: x.upcase}
{s,r}end

Try it online!

How it works?

def f(a, b)                       # Strings as list of characters
r = s = ""                        # Strings buffers initialization
a.zip(b) do |x, y|                # Join two arrays to paired tuples and iterate
r+="`"<x<"{"?y.downcase: y.upcase # Check if character is downcase using triple
s+="`"<y<"{"?x.downcase: x.upcase # comparison and ascii table. Then apply it to
end                               # the other character using String methods
{s, r}                            # Return two new strings using a tuple
end                               # PS: Tuples are inmutable structures in Crystal
\$\endgroup\$
1
\$\begingroup\$

Assembly (nasm, x64, Linux), 25 bytes (123 bytes source)

Hex bytes:

0x88, 0xE6, 0x30, 0xC6, 0x80, 0xE6, 0x20, 0x88
0xF2, 0x66, 0x31, 0xD0, 0x88, 0x26, 0xAA, 0xAC
0x8A, 0x26, 0x8A, 0x07, 0x08, 0xE4, 0x75, 0xE8, 0xC3

The function entry point is at a, with the strings passed in using RDI and RSI.

b:MOV DH,AH
XOR DH,AL
AND DH,32
MOV DL,DH
XOR AX,DX
MOV [RSI],AH
STOSB
LODSB
a:MOV AH,[RSI]
MOV AL,[RDI]
OR AH,AH
JNZ b
RET

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ I just realized you're golfing the asm source, not the machine-code size. That's usually more fun, because it's occasionally useful in real life. (All else being equal, smaller is typically better for the front-end and uop cache density.) Tips for golfing in x86/x64 machine code. \$\endgroup\$ Jun 8, 2018 at 3:48
  • \$\begingroup\$ @PeterCordes Thanks for the tip. I've added the hex bytes. My assembly is a little rusty (I last had to write a little device driver for DOS 3.3!) but I think I got most of the optimizations in. \$\endgroup\$
    – ErikF
    Jun 8, 2018 at 4:04
  • \$\begingroup\$ Yeah, this looks pretty good. Interesting partial-register hacks. and al,32 is only 2 bytes, using the special AL,imm8 encoding that most ALU instructions have. You could require the string length in RCX and use loop. I was going to say you should test ah,ah because that's more efficient than or while being the same length, but it's longer in asm source so the crusty old idiom actually has merit for asm-source code golfing :P \$\endgroup\$ Jun 8, 2018 at 4:11
  • \$\begingroup\$ Using memory-destination xor and a tighter loop structure, my version came in at 14 bytes of x86-64 machine code. Same for count implicit-length or explicit-length strings. Its NASM source could probably be golfed down shorter than 123 bytes, too. I'm not sure which would run faster on a modern CPU like Skylake or Ryzen (Ryzen wouldn't have any extra cost for merging DH when reading DX, but SKL would need an extra cycle to insert a merging uop.) \$\endgroup\$ Jun 8, 2018 at 11:00
1
\$\begingroup\$

TI-Basic, 225 bytes

Prompt Str1,Str2
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ→Str3
"seq(inString(Str3,sub(Ans,I,1),I,1,length(Ans→u
Str1
u→F
Str2
augment(u,ʟF→S
augment(ʟF,Ans→F
".
For(I,1,dim(ʟS
Ans+sub(Str3,remainder(ʟF(I)-1,26)+1+26(ʟS(I)>26),1
End
Disp sub(Ans,2,length(Str1
sub(Ans,2+length(Str2),length(Str2

-1 byte if the i is replaced with the imaginary number i.
+3 bytes by replacing remainder(ʟF(I)-1,26) with 26fPart((ʟF(I)-1)/26) if the calculator does not support remainder(.

Outputs are displayed, separated by a newline.

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

Charcoal, 17 bytes

Eθ⭆ι⎇№α§§θ¬κμ↥λ↧λ

Try it online! Link is to verbose version of code. Takes input as an array of two strings. Explanation:

 θ                  Input array
E                   Map over strings
   ι                Current string
  ⭆                 Map over characters
         θ          Input array
           κ        Outer loop index
          ¬         Logical Not
        §           Index into array
            μ       Inner loop index
       §            Index into array
      α             Uppercase characters
     №              Count number of matches
              λ λ   Current character
             ↥      Uppercase
               ↧    Lowercase
    ⎇               Ternary
                    Implicitly print
\$\endgroup\$
0
\$\begingroup\$

F#, 120 bytes

Bugger.

open System
let g=Seq.fold2(fun a x y->a+string(x|>if y>'Z'then Char.ToLower else Char.ToUpper))""
let b f s=g f s,g s f

Try it online!

The function g takes the two strings as parameters. Seq.fold2 applies a function with an accumulator (a) to each element (x and y) in the strings. Initially a is an empty string, and it adds the converted character to it in each iteration.

b is the main function. It first converts f with respect to s, and then converts s with respect to f. It then returns a tuple with both values.

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

Prolog (SWI), 121 bytes

[H|T]-[I|U]-[J|V]-[K|W]:-((H>96,I>96;H<92,I<92),J=H,K=I;H>96,J is H-32,K is I+32;J is H+32,K is I-32),T-U-V-W.
_-_-[]-[].

Try it online!

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

Ruby, 74 69 bytes

->a,b{a.zip(b).map{|x|x.one?{|y|y>?_}?x.map(&:swapcase):x}.transpose}

Try it online!

Input and output are arrays of chars, so the footer does back and forth transformations from strings.

I'm not yet sure whether this is a good approach to the problem, but this challenge definitely looks like a nice use scenario for swapcase method.

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

PHP 4.1.2, 40 bytes

Replace the pair of quotation marks with byte A0 (in ISO-8859-1 or Windows-1252, this is NBSP) to get the byte count shown, then run from a web browser (or from the command line), providing the strings as the query string arguments (or environment variables) a and b.

<?=$a^$c=($a^$b)&str_pad("",2e5),_,$b^$c;

In this version of PHP, register_globals is on by default, so the strings will automatically be assigned to the variables $a and $b. Increase the value 2e5 (200000) if necessary.

PHP 7.1+, 58 bytes

Run on the command line, using php -r 'code here' string1 string2:

[,$a,$b]=$argv;echo("$b $a"^$a.=" $b")&str_pad("",3e5)^$a;

The value 3e5 (300000) is chosen to exceed (MAX_ARG_STRLEN * 2 + 1) on most Linux systems (specifically, x86 and other architectures for which PAGE_SIZE is 4096, and MAX_ARG_STRLEN is thus 131072), to avoid problems with any possible input string. Increase if necessary.

Try it online!

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

Stax, 10 bytes

▌Ö↑o╓→ì]yç

Run and debug it

Here's an ungolfed representation of the same program to show how it works.

        Example
        ["Ab", "cd"]                    
:)      [["Ab", "cd"], ["cd", "Ab"]]    Get all rotations of input
m       ["cd", "Ab"]                    For each, run the rest of program; print result
  M     ["cA", "db"]                    Transpose matrix
  {     "cA"                            Begin block for mapping to result
    B   "A" 99                          "Pop" first element from string array; leave the rest
    96> "A" 1                           Is the character code > 96?
    :c  "a"                             Set case of string; 0 -> upper,  1 -> lower
  m     "ab"                            Perform the map using the block

Run this one

\$\endgroup\$

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.