35
\$\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\$
7
  • 2
    \$\begingroup\$ Are we allowed to modify the input and make it the output? \$\endgroup\$
    – S.S. Anne
    Dec 28, 2019 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, 2019 at 4:47
  • 6
    \$\begingroup\$ Bonus challenge: make a program that still works when ran through the swapping process. \$\endgroup\$
    – Sanchises
    Dec 29, 2019 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, 2019 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, 2019 at 4:20

41 Answers 41

31
\$\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\$
0
29
\$\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
  • 1
    \$\begingroup\$ Wow. That's really impressive. \$\endgroup\$ Dec 27, 2019 at 21:06
10
\$\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\$
10
\$\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\$
2
  • 1
    \$\begingroup\$ Damn this is awesome \$\endgroup\$
    – xdevs23
    Dec 27, 2019 at 12:35
  • 2
    \$\begingroup\$ Ḣ,Ṫjṭ2/ saves a byte. (I like the nine: J’!Œœ§Ṃœ?) \$\endgroup\$ Dec 28, 2019 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\$
4
  • \$\begingroup\$ @Mr.Xcoder Thanks, fixed. \$\endgroup\$
    – xnor
    Dec 27, 2019 at 11:15
  • \$\begingroup\$ Do you need the f= part? In this answer it doesn't include the f= part. \$\endgroup\$
    – justhalf
    Dec 30, 2019 at 4:25
  • 1
    \$\begingroup\$ @justhalf I do because I have a recursive call to f. \$\endgroup\$
    – xnor
    Dec 30, 2019 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, 2019 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\$
5
\$\begingroup\$

Perl 6 -p, 26 bytes

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

Try it online!

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

Ruby, 42 bytes

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

Try it online!

\$\endgroup\$
3
  • \$\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, 2019 at 23:18
  • \$\begingroup\$ This would be unfair, it's a completely different idea. \$\endgroup\$
    – G B
    Dec 27, 2019 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, 2019 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\$
0
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\$

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\$
1
3
\$\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\$
3
\$\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\$
1
  • \$\begingroup\$ -l mode is not needed at all; the program works just fine with just -p. \$\endgroup\$
    – Value Ink
    Dec 28, 2019 at 2:23
3
\$\begingroup\$

Haskell, 40 bytes

f(a:b:c:d)=b:a:f(c:d)
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\$
0
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\$

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\$
2
  • 1
    \$\begingroup\$ You can use (?!^) instead of (?<=.). See this answer on SO. \$\endgroup\$
    – Arnauld
    Dec 27, 2019 at 19:55
  • \$\begingroup\$ Actually I think @histocrat's regex might be even shorter still. \$\endgroup\$
    – Neil
    Jun 2, 2020 at 10:56
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\$
0
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\$
2
\$\begingroup\$

Fortran (GFortran), 125 bytes

character(99)a,b(99)
read('(a)'),a
j=len_trim(a)
b=[a(1:1),(a(i+1:i+1),a(i:i),i=2,j-1,2),a(j:j)]
print*,(b(i)(1:1),i=1,j)
end

Try it online!

Shame string manipulation in Fortran is so wordy as every substring needs two references. The main magic is mapping a to a character array via:

[a(1:1),            ! Prepend first char
(a(i+1:i+1),a(i:i), ! Swap a(i+1) for a(i)
  i=2,j-1,2)        ! For i in 2..n-1
,a(j:j)]            ! Append last char
\$\endgroup\$
2
\$\begingroup\$

J, 48 bytes

Man, I love J

(1{.]),([:,[:(|."1)_2[\1}.]}.~_1-2|#),]{.~_1-2|#

Try it online!

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

Zsh, 74 71 bytes

Found a more idiomatic Zsh solution. Try it online!

w=$1;printf $w[1]${w[2,$#w-1]//(#m)(?)(?)/$MATCH[2]$MATCH[1]}${w:$#w-1}

74 bytes: w=$1;printf $w[1];for i ({2..$[$#w-2]..2})printf $w[i+1]$w[i];<<<${w:$i+1}

\$\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\$

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\$
2
  • \$\begingroup\$ As @Arnauld suggested to @ShieruAsakoto, you should be able to use (?!^) instead of (?<=.). \$\endgroup\$
    – Neil
    Jun 2, 2020 at 10:49
  • \$\begingroup\$ Actually I think @histocrat's regex might be even shorter still. \$\endgroup\$
    – Neil
    Jun 2, 2020 at 10:52
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\$

Your Answer

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

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