27
\$\begingroup\$

Intro/Background

I was looking at "You Had One Job" pictures lately, and noticed an old favourite of mine:

SHCOOL

And I said to myself: "I need a program that can generate text like that". So I devised a set of rules for character swapping and wrote a CGCC challenge!

The Challenge

Given a single string as input, output a string with its inner characters swapped. This can be done by:

  • Leaving the first letter as is
  • Swapping each pair of characters thereafter
  • Leaving the last letter as is. If the string is of an odd length (i.e. the length of the string mod 2 is 1), leave the last two letters as they are.

Example Inputs/Outputs

School -> Shcool
Somebody -> Smobedoy
Character -> Cahartcer
CGCC -> CCGC
Stack Exchange! -> SatkcE cxahgne!
Never gonna give you up -> Nvereg noang vi eoy uup

Walkthrough on swapping

School (Length: 6)
S
 hc
   oo
     l
Shcool


Somebody (Length: 8)
S
 mo
   be
     do
       y
Smobedoy


Character (Length: 9)
C
 ah
   ar
     tc
       er
Cahartcer

Stack Exchange! (Length: 15)
S
 at
   kc
     E 
       cx
         ah
           gn
             e!
SatkcE cxahgne!

Rules

  • Input/output can be taken/given in any convenient format
  • The input will not contain newlines
  • Minimum input length is 4
  • Input will only contain printable ASCII characters

Scoring

This is , so the answer with the lowest bytes wins.

Sorry about the last test case everyone. It's fixed now

\$\endgroup\$
  • 2
    \$\begingroup\$ Are we allowed to modify the input and make it the output? \$\endgroup\$ – S.S. Anne Dec 28 '19 at 4:35
  • \$\begingroup\$ @JL2210 As stated in the challenge, input and output can be taken and given in any convient format. So if modifying the input and making it the output makes this challenge easier, then go ahead and do so! \$\endgroup\$ – Lyxal Dec 28 '19 at 4:47
  • 5
    \$\begingroup\$ Bonus challenge: make a program that still works when ran through the swapping process. \$\endgroup\$ – Sanchises Dec 29 '19 at 7:25
  • \$\begingroup\$ I'm not familiar with the convention in Python, strings are immutable, while lists are not. Can I take a list and output a list instead of string? \$\endgroup\$ – justhalf Dec 30 '19 at 4:19
  • 1
    \$\begingroup\$ @justhalf As stated in the challenge, input and output can be taken and given in any convenient format. So if taking and outputting a list is easier for you, feel free to do so. \$\endgroup\$ – Lyxal Dec 30 '19 at 4:20

37 Answers 37

27
\$\begingroup\$

Haskell, 31 bytes

f(a:b:c:d:e)=a:c:f(b:d:e)
f x=x

Try it online!

Avoids having to special-case omitting the first character by having extracting it be part of the recursive definition.

\$\endgroup\$
  • \$\begingroup\$ I was trying to get this for a while but I could only get the version prior to the revision. Nice job! \$\endgroup\$ – Post Rock Garf Hunter Dec 26 '19 at 22:51
25
\$\begingroup\$

brainfuck, 28 bytes

,.,[>,>,[<.[-]<.>>>]<<[.>]>]

Try it online!

First, we print the first character. Then we read the second character and enter the main loop. (,.,[)

When entering the main loop, we expect the first character of a pair to be in the current cell, and we read the next two into the next two cells (>,>,). The tape then looks like this:

[pair1] [pair2] [nextpair1] [0]
                     ^

Then, if nextpair1 exists, we know there's going to be at least one character after the current pair, so we can output the two characters in this current pair in reverse ([<.[-]<.>>>]) – the triple > at the end moves us to the location after nextpair1 to break out of the loop. Otherwise, we're at the end of the string, so we go back to pair1 (<<) and print as many characters as we received in order ([.>]).

The main loop will end here if this was the end of the string (>]). If not, recall that we ended at the [0] in the diagram above after the check to see if nextpair1 existed. So the <<[.>] would have brought the pointer to pair2 (which was cleared) instead of pair1, and then >] restarts the main loop, but with the cursor pointing at nextpair1, which is exactly what we want.

\$\endgroup\$
  • 1
    \$\begingroup\$ Wow. That's really impressive. \$\endgroup\$ – Eric Duminil Dec 27 '19 at 21:06
8
\$\begingroup\$

Retina, 12 bytes

V`^.|..(?=.)

Try it online! Link includes test cases. Explanation: V reverses each match. The first character is matched separately, then characters are matched in pairs as long as there is still one character left that is unreversed.

\$\endgroup\$
8
\$\begingroup\$

Jelly, 8 7 bytes

Ḣ,Ṫjṭ2/

Try it online!

A full program taking a string as its argument and printing the swapped string. Thanks to @JonathanAllan for saving a byte!

Explanation

Ḣ       | Head
 ,Ṫ     | Paired with tail
   j    | Join with:
    ṭ2/ | The remainder, pair wise reduced by tacking the left item in the pair to the end of the right
\$\endgroup\$
  • 1
    \$\begingroup\$ Damn this is awesome \$\endgroup\$ – xdevs23 Dec 27 '19 at 12:35
  • 1
    \$\begingroup\$ Ḣ,Ṫjṭ2/ saves a byte. (I like the nine: J’!Œœ§Ṃœ?) \$\endgroup\$ – Jonathan Allan Dec 28 '19 at 3:33
7
\$\begingroup\$

Python 2, 49 bytes

f=lambda s:s[3:]and s[:3:2]+f(s[1:5:2]+s[4:])or s

Try it online!

Based off my Haskell answer. I tried a more direct port using splatted input, but it was clunky:

57 bytes

f=lambda a,b,c,*d:d[1:]and a+c+f(b,*d)or a+b+c+''.join(d)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ @Mr.Xcoder Thanks, fixed. \$\endgroup\$ – xnor Dec 27 '19 at 11:15
  • \$\begingroup\$ Do you need the f= part? In this answer it doesn't include the f= part. \$\endgroup\$ – justhalf Dec 30 '19 at 4:25
  • 1
    \$\begingroup\$ @justhalf I do because I have a recursive call to f. \$\endgroup\$ – xnor Dec 30 '19 at 4:32
  • \$\begingroup\$ Ah, I see. Anyway, nice trick with the recursion! I can only match your second version with my answer due to the return and the function definition. \$\endgroup\$ – justhalf Dec 30 '19 at 4:33
6
\$\begingroup\$

APL (Dyalog Extended), 27 20 bytesSBCS

Anonymous tacit prefix function. Requires ⎕IO←0.

⊢⊇⍨∘⍋≢⌊1+⍳∘≢+2×2|⍳∘≢

Try it online!

Explanation and walk-through for "Somebody" and "Character":

⍳∘≢ the indices of the length; [0,1,2,3,4,5,6,7], [0,1,2,3,4,5,6,7,8]

2| two-mod of that; [0,1,0,1,0,1,0,1], [0,1,0,1,0,1,0,1,0]

 twice that; [0,2,0,2,0,2,0,2], [0,2,0,2,0,2,0,2,0]

⍳∘≢+ add the indices of the length to that; [0,3,2,5,4,7,6,9], [0,3,2,5,4,7,6,9,8]

1+ increment that; [1,4,3,6,5,8,7,10], [1,4,3,6,5,8,7,10,9]

≢⌊ the minimum of the length and that; [1,4,3,6,5,8,7,8], [1,4,3,6,5,8,7,9,9]

 the grade (the indices that would sort it) of that; [0,2,1,4,3,6,5,7], [0,2,1,4,3,6,5,7,8]

⊢⊇⍨∘ use that to reorder the string; "Smobedoy", "Cahartcer"

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

Ruby, 42 bytes

f=->s{s[/(.)(.)(.)(.+)/]?$1+$3+f[$2+$4]:s}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ If you want, cribbing the Retina solution directly saves 5 bytes or you could enable -p mode to drop it all the way down to 30 bytes. \$\endgroup\$ – Value Ink Dec 26 '19 at 23:18
  • \$\begingroup\$ This would be unfair, it's a completely different idea. \$\endgroup\$ – G B Dec 27 '19 at 10:07
  • \$\begingroup\$ Understandable. It seems histocrat has taken that approach for their Ruby solution, and even shorter than my suggestion. \$\endgroup\$ – Value Ink Dec 28 '19 at 2:24
4
\$\begingroup\$

Brain-Flak, 48 40 bytes

({}<{({}<({}<>)>)<>}<>{{({}<>)<>}{}}<>>)

Try it online!

This doesn't work for strings that contain null bytes (unless the null byte is the first byte of the string).

Explanation

({}<...>) Store the first element for later
  {({}<({}<>)>)<>}... Move the stack over in twos (preserving the order of each pair moved)
    <>{...{}}<>
      {({}<>)<>} Move everything back in ones

The one complex part is the <>{...{}}<>. Since moving over in twos can pick up an extra zero from the bottom of the stack we need to removing when bringing things back. Conveniently our main loop will stop when it hits a zero, so when it hits a zero we destroy that zero and, if the next thing is not zero we try again.

This means we will only stop if there are two zeros in a row, which since the input cannot contain zeros, will only occur at the bottom of the stack. In the process we will get rid of any zeros that are present, which fixes our extra zero issue.

Works for all inputs, 114 112 bytes

({}<([](())){({}[()]<(()[{}])>)}({}{}<([]){{}({}<({}<>)>)<>([])}>{}<>){(<{}({}<{}>)>)}{}([]){{}({}<>)<>([])}<>>)

Try it online!

Nearly all of the code is devoted to making this work for even length inputs.

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

C++ (clang), 117 ... 82 80 bytes

#import<map>
#define f(s)for(int i=1;i<s.size()-2;)s[i++]^=s[i++]^=s[i+1]^=s[i];

Try it online!

Saved 11 bytes thanks to @AZTECCO!!!
Saved 2 bytes thanks to @ceilingcat!!!

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

Perl 6 -p, 26 bytes

s:g[^.||)>..$||..]=$/.flip

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Seems to fail for odd number of chars. For instance heidi and heidila. \$\endgroup\$ – Kjetil S. Jan 9 at 15:54
  • \$\begingroup\$ @KjetilS. Thanks, fixed. \$\endgroup\$ – nwellnhof Jan 10 at 16:52
3
\$\begingroup\$

Python 3, 62 bytes

lambda x:x[0]+re.sub("(.)(.)",r"\2\1",x[1:-1])+x[-1]
import re

Try it online!

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

Haskell, 35 bytes

f(a:b:c)=b:a:f c
f x=x
g(a:b)=a:f b

Try it online!

xnor has a shorter version of this answer that combines f and g into a single function.

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

05AB1E, 14 bytes

¦¨2ô€RJ¹θ¹н.ÁJ

Try it online!

¦¨2ô€RJ¹θ¹н.ÁJ
¦¨             # Delete the first and last letter
  2ô           # Break into groups of 2
    €R         # Reverse each of them
      J        # Join it back together
       ¹θ¹н    # Push the last and first letter of the input
           .Á  # Rotate stack, so the first letter is first
             J # Join the items in the stack
\$\endgroup\$
2
\$\begingroup\$

J, 24 19 bytes

C.~[:}:_2<@|.\#\@}.

Try it online!

Creates the boxed indexes representing the cyclic form of the permutation we need (bookeeping), and then applies it C. to the input.

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

Gema, 15 characters

\A?=?
??\P?=$2?

The only interesting point here is the use of

\P       Position -- leave input stream here after the template matches

Sample run:

bash-5.0$ echo -n 'School' | gema '\A?=?;??\P?=$2?'
Shcool

Try it online! | Try all test cases online!

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

Japt, 11 bytes

h1Ué ¤ò mÔq

Try it

h1Ué ¤ò mÔq     :Implicit input of string U
h1              :Overwrite from the 1st (0-indexed) character on with
  Ué            :  Rotate U to the right
     ¤          :  Slice off the first 2 characters
      ò         :  Split into pairs
        m       :  Map
         Ô      :    Reverse
          q     :  Join
\$\endgroup\$
2
\$\begingroup\$

Ruby -pl, 27 bytes

gsub /^.|..(?=.)/,&:reverse

Try it online!

Alternate solution with the same bytecount, but a regex nobody else has used yet:

gsub /(^|.)(.(?=.))/,'\2\1'

Try it online!

\$\endgroup\$
  • \$\begingroup\$ -l mode is not needed at all; the program works just fine with just -p. \$\endgroup\$ – Value Ink Dec 28 '19 at 2:23
2
\$\begingroup\$

Python 3, 57 bytes

def f(s):s[1:-2:2],s[2:-1:2]=s[2:-1:2],s[1:-2:2];return s

Try it online!

Accepts a list and returns a list.

The idea is to simply take the alternating slices and swap them.

Do let me know if the boilerplate stuff can be shortened in Python submissions.

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

C (clang), 51 48 bytes

f(char*s,z){*++s^=*s^=s[1]^=*++s;z>5&&f(s,z-2);}

Try it online!

A recursive solution that modifies the original string

Saved 3 thanks to @ceilingcat suggestion to use ^=

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

x86-16 machine code, 13 bytes

Unassembled listing:

 46         INC  SI         ; skip first char 
 8B FE      MOV  DI, SI     ; point DI to string 
 D1 E9      SHR  CX, 1      ; divide counter by 2 with round down 
 49         DEC  CX         ; skip last char 
        CLOOP: 
 AD         LODSW           ; load next two chars 
 86 E0      XCHG AH, AL     ; reverse chars 
 AB         STOSW           ; store next two chars 
 E2 FA      LOOP CLOOP      ; keep looping
 C3         RET             ; return to caller

Input/output string in [SI], length in CX.

PC-DOS test program output:

enter image description here

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

Burlesque, 17 bytes

rt2cog_j)<-++.+RT

Try it online!

rt  # Rotate the string left
2co # Split into chunks of 2
g_j # Take pair of first and last out
)<- # Reverse each chunk
++.+# Join everything back together
RT  # Rotate the string right

For even length input only you can shave a single character:

RT2col_)<-++.+RT
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 20 bytes

§θ⁰F⪪✂θ¹±¹¦¦¦²⮌ι§θ±¹

Try it online! Link is to verbose version of code. Works with strings of at least 2 characters. Explanation:

§θ⁰

Print the first character of the string.

F⪪✂θ¹±¹¦¦¦²

Split the inner slice of the string into 2-character substrings.

⮌ι

Print each substring reversed.

§θ±¹

Print the last character of the string.

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

SNOBOL4 (CSNOBOL4), 104 bytes

 P =LEN(1)
 INPUT P . F REM . S
S S P . X P . Y REM . S
 F =F Y X
 GT(SIZE(S),2) :S(S)
O OUTPUT =F S
END

Try it online!

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

Pip, 17 bytes

[@aRV_MTMa<>2a@v]

Try it online!

So ugly... seems like there's gotta be a shorter way, but I haven't found it yet.

Explanation

[               ]  Construct a list containing:
 @a                 1. The first character of the argument string
                    2.
       TMa             The argument string with first and last characters trimmed
          <>2          split into groups of two characters
      M                to each element of which we map the function
   RV_                 reverse
             a@v    3. The last character of the argument string
                   Concatenate the list and print (implicit)

Alternate 17-byte solution

Using the same regex as Neil's Retina answer (independently discovered) gives another 17-byte solution:

aR`^.|..(?=.)`RV_

Try it online!

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

Red, 95 76 bytes

func[s][prin take s t: take/last s
foreach[a b]s[prin any[b""]prin a]prin t]

Try it online!

Directly prin(t)s the characters instead of returning a string.

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

Java (JDK), 43 bytes

s->s.replaceAll("(?<=.)(.)(.)(?=.)","$2$1")

Try it online!

Without much API, 60 bytes

s->{for(int i=1;i<s.length-2;)s[i]^=s[++i]^(s[i]=s[i++-1]);}

Try it online!

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

Keg, 16 bytes (SBCS)

The same program as below, with extra simplifying-ops added.

,(!½!2%¬-|$,,)(,

Try it online!

Keg -ir, 18 bytes

You know, Jono's challenges are definitely easily doable in Keg.

,(!2/1!2%--|$,,)(,

Try it online!

Explanation

                   # Take an input from STDIN
,                  # Step 1. Output the first item.
 (!2/              # Repeat half of the length-of-stack times
     1!2%--        # subtract by 1 if that's odd
           |$,,    # Swap & output the two items
               )(, # Output the remaining items
\$\endgroup\$
1
\$\begingroup\$

Wren, 73 bytes

Did some simple optimizations

Fn.new{|x|x[0]+(1..x.count-3).map{|y|x[y%2==0?y-1:y+1]}.join()+x[-2..-1]}

Try it online!

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

JavaScript (Node.js), 40 bytes

f=s=>s[3]?s[0]+s[2]+f(s[1]+s.slice(3)):s

Try it online!

JavaScript (Node.js), 41 40 bytes

-1 bytes thanks to Arnauld

s=>s.replace(/(?!^)(.)(.)(?=.)/g,"$2$1")

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ You can use (?!^) instead of (?<=.). See this answer on SO. \$\endgroup\$ – Arnauld Dec 27 '19 at 19:55
1
\$\begingroup\$

Emacs, 7 keystrokes

C-f <f3> C-f C-t M-0 <f4> C-/

or 9 keystrokes without fn-keys

C-f C-x ( C-f C-t M-0 C-x ) C-/

C-f move forward one character

<f3> start keyboard macro

C-f

C-t transpose the character under the cursor with the one before it

M-0 call the next command with numeric argument 0

<f4> run this macro and end definition, with argument 0, this macro is run indefinitely until a break occurs, i.e. when C-f goes past the last character

C-/ undo the last change, i.e. the last transpose, so that the end condition is fulfilled; this saves some keystrokes over vim because u undo after a recursive macro call undos all the runs of the macro instead of the last change

\$\endgroup\$

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.