40
\$\begingroup\$

In chat, we are often fast-typers and don't really look at the order of letters before posting a message. Since we are lazy, we need a program that automatically swaps the last two letters in our words, but since we don't want to respond too late, the code must be short.

Your task, if you wish to accept it, is to write a program that flips the last two letters of each word in a given string (so the word Thansk turns into Thanks). A word is a sequence of two or more letters in the English alphabet delimited by a single space.

  • The string / list of characters you receive as input is guaranteed to only contain alphabetic characters and spaces (ASCII [97 - 122], [65 - 90] and 32).

  • You can take input and provide output through any standard method, in any programming language, while taking note that these loopholes are forbidden by default.

  • The output may have one trailing space and / or one trailing newline.

  • The input will always contain words only (and the corresponding whitespace) and will consist of at least one word.

This is code-golf, so the shortest submission (scored in bytes), in each language wins!

Test cases

Note that the strings are surrounded with quotes for readability.

Input -> Output
"Thansk" -> "Thanks"
"Youer welcoem" -> "Youre welcome"
"This is an apple" -> "Thsi si na appel"
"Flippign Lettesr Aroudn" -> "Flipping Letters Around"
"tHe oDd chALlEneg wiht swappde lettesR" -> "teH odD chALlEnge with swapped letteRs"

Or, for test suite convenience, here are the inputs and their corresponding outputs separately:

Thansk
Youer welcoem
This is an apple
Flippign Lettesr Aroudn
tHe oDd chALlEneg wiht swappde lettesR
Thanks
Youre welcome
Thsi si na appel
Flipping Letters Around
teH odD chALlEnge with swapped letteRs

Thanks to DJMcMayhem for the title. This was originally a CMC.

asked Dec 27, 2017 at 19:45
\$\endgroup\$
6
  • \$\begingroup\$ May we output an array of words? \$\endgroup\$ Commented Dec 27, 2017 at 22:03
  • \$\begingroup\$ @Shaggy No, the output must be a string (or a list of characters by default) \$\endgroup\$ Commented Dec 27, 2017 at 22:04
  • \$\begingroup\$ May we request a trailing space on each input? \$\endgroup\$ Commented Dec 29, 2017 at 12:23
  • 1
    \$\begingroup\$ Whta shoudl eb doen wiht oen lettre worsd liek "a"? \$\endgroup\$ Commented Dec 29, 2017 at 14:08
  • 2
    \$\begingroup\$ @Fabian A word is a sequence of two or more letters \$\endgroup\$ Commented Dec 29, 2017 at 14:12

48 Answers 48

1
2
1
\$\begingroup\$

K (oK), (削除) 23 (削除ここまで) 22 bytes

" "/{x@prm[!#x]1}'" "\

Try it online!

Example:

" "/{x@prm[!#x]1}'" "\"Hello World"
"Helol Wordl"

Explanation:

Port of FrownyFrog's solution to save 1 byte.

I'll come back to this.

" "/{prm[x]1}'" "\ / the solution
 " "\ / split input on " "
 { }' / apply lambda to each
 prm[x] / permute input x
 1 / and take the 2nd result
" "/ / join with " "

Previous solution:

  • " "/-2{(x_y),|x#y}'" "\ 23 bytes
answered Dec 29, 2017 at 11:01
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 7 bytes

#vy`sðJ

Try it online!

-1 thanks to Magic Octopus Urn.

Prints one trailing space.

answered Dec 27, 2017 at 20:13
\$\endgroup\$
11
  • \$\begingroup\$ This is 11 bytes \$\endgroup\$ Commented Dec 28, 2017 at 12:50
  • 2
    \$\begingroup\$ @DanFromGermany No, 05AB1E has a code page in which this can be represented as 8 bytes. \$\endgroup\$ Commented Dec 28, 2017 at 12:51
  • \$\begingroup\$ Can you run the program represented in 8 bytes? \$\endgroup\$ Commented Dec 28, 2017 at 13:06
  • \$\begingroup\$ @DanFromGermany Yes, the 05AB1E interpreter can run this program from a file in the 05AB1E encoding. \$\endgroup\$ Commented Dec 28, 2017 at 13:09
  • 1
    \$\begingroup\$ @MagicOctopusUrn It's not a list though, it's after `. \$\endgroup\$ Commented Feb 2, 2018 at 14:58
1
\$\begingroup\$

Ly, 30 bytes

i00I[rpr' =[ppf' 0]p0I]pfrp[o]

Try it online!

This one reads all the input into the stack, then copies characters one at a time to the other end of the stack (with a null separator between the original and the "fixed" codepoints). Anytime a space it found, it reverse the position of the previous two codepoints.

When the loop hits the null separator it end, then the just prints the stack.

i00I[rpr' =[ppf' 0]p0I]pfrp[o]
i0 # Read all the input, then push a null
 0I # Copy the bottom of the stack to the top
 [ ]p # Loop until the null reaches the bottom of the stack
 rpr # Reverse, pop, reverse (delete bottom of the stack)
 0I # Copy the bottom of the stack to the top
 ' = # Is the codepoint " "?
 [p 0]p # If-then, runs if codepoint is " "
 pf' # Delete " ", flip two entries, add " " back
 f # End of input, flip the last two codepoints
 rp # Reverse stack, delete null
 [o] # Print the stack as characters
answered Jul 15, 2021 at 9:51
\$\endgroup\$
1
\$\begingroup\$

Vyxal S, 5 bytes

⌈ƛ÷$Ṡ

Try it Online!

-2 thanks to Aaron Miller.

answered Jul 15, 2021 at 5:47
\$\endgroup\$
1
  • \$\begingroup\$ 5 bytes \$\endgroup\$ Commented Jul 18, 2021 at 15:04
1
\$\begingroup\$

Lexurgy, 24 bytes

This kind of challenge is one of the canonical reasons for captures in Lexurgy to exist (for things like metathesis and reduplication).

Capture 2 of any character, and swap their order when they are at the end of a "word".

a:
[]1ドル []2ドル=>2ドル 1ドル/_ $
answered Apr 6, 2022 at 0:47
\$\endgroup\$
1
\$\begingroup\$

BQN, 17 characters

∾(+`«∘≠⟜' ')⌽ ̈∘⊔⊢

Try it here!

Explanation

The function consists of a two 2 and a 3-train. If we were to write it out with the argument x where necessary and function composition removed, we'd have:

{∾ ⌽ ̈ (+` « ' '≠x) ⊔ x}

Below, I've tried to sketch what happens and I use the golfed code again:

 ⊢ # For the left argument of group (⊔) we use the identity
 # function, i.e. it receives the string argument.
 ( ≠⟜' ') # For the right argument we start by mapping the string
 # using the predicate ≠⟜' ', so "The bomb" becomes 1‿1‿1‿0‿1‿1‿1‿1.
 « # Shift left by 1 which shifts in 0, so we get 1‿1‿0‿1‿1‿1‿1‿0.
 +` # Scan using + left to right, so we get 1‿2‿2‿3‿4‿5‿6‿6.
 # By shifting the boolean array to the left, we have
 # ensured that the position before a space in the original
 # argument gets the same number as its predecessor in the
 # scan result!
 ⊔ # Group the original argument into "buckets" designated by the
 # integer list we just computed for the left argument which
 # gives us: ⟨ "", "T", "he", " ", "b", "o", "mb" ⟩
 ⌽ ̈ # Reverse every string: ⟨ "", "T", "eh", " ", "b", "o", "bm" ⟩
∾ # Concatenate: "Teh bobm"
∾(+`«∘≠⟜' ')⌽ ̈∘⊔⊢ # The entire thing.
answered Aug 21 at 22:56
\$\endgroup\$
0
\$\begingroup\$

Jelly, 10 bytes

ḲṪ,\\€Ḋ€UK

Try it online!

answered Dec 27, 2017 at 20:11
\$\endgroup\$
0
0
\$\begingroup\$

SNOBOL4 (CSNOBOL4), (削除) 136 (削除ここまで) 119 bytes

	I =INPUT
B	I SPAN(&LCASE &UCASE) . Y ARBNO(' ') =:F(O)
	Y RPOS(2) REM . Z =REVERSE(Z)
	O =O Y ' '	:(B)
O	OUTPUT =O
END

Try it online!

Prints with a trailing space. (削除) You know you've done something wrong when a language is a backronym for StriNg Oriented and symBOlic Language and your code is longer than Brain-Flak :( (削除ここまで) now it's slightly better.

Line B takes I and replaces (alphabetic characters saved as Y)(some number of spaces) with the empty string.

The following line extracts the last 2 characters of Y as Z and replaces them as Z reversed, then the next line concatenates O, Y, and a single space character.

Finally, it prints when I no longer matches the required pattern in line B.

answered Dec 27, 2017 at 20:12
\$\endgroup\$
0
\$\begingroup\$

Standard ML (MLton), (削除) 92 (削除ここまで) 77 bytes

implode o foldr(fn(a,b:: #" "::r)=>b::a:: #" "::r|(a,r)=>a::r)[#" "]o explode

Try it online! Based on xnor's Haskell solution.


Previous 92 byte version

fun f(a::b:: #" "::r)=b::a:: #" "::f r|f(x::r)=x::f r|f r=r
fun$s=implode(f(explode(s^" ")))

Try it online! Example usage: $ "Flippign Lettesr Aroudn" yields "Flipping Letters Around ".

Ungolfed

fun f (a :: b :: #" " :: r) = b :: a :: #" " :: f r
 | f (x :: r) = x :: f r
 | f r = r
fun g s = implode (f (explode (s ^ " ")))

Try it online!

answered Dec 27, 2017 at 22:15
\$\endgroup\$
0
\$\begingroup\$

Wolfram Language (Mathematica), 72 bytes

x""<>(Characters[StringSplit@x][[;;,#]]&/@{;;-3,-1,-2})~Riffle~" "

Try it online!

Another approach using manipulation of character list and take parts instead of string regex.

The two Unicode characters are \[Function] and \[Transpose] in private use area of Mathematica, take 3 bytes each.

74 bytes

Try it online!

answered Dec 28, 2017 at 12:20
\$\endgroup\$
0
\$\begingroup\$

Excel VBA, 78 Bytes

Anonymous VBE immediate window that takes input from range A1 and outputs to the VBE immediate window.

For Each s in Split([A1]):l=Len(s):?Left(s,l-2)Right(s,1)Mid(s,l-1,1)" ";:Next
answered Dec 28, 2017 at 19:09
\$\endgroup\$
0
\$\begingroup\$

Ruby, 53 bytes

$*.each{|x|print x[0,x.length-2]+x[-2,2].reverse," "}

The program takes input through command line arguments (formatted as a regular sentence, without quotes).

$* is a shorthand for ARGV, therefore i can iterate over each of the words, already in an array.

Only thing that bugs me is that awful x.length-2 snippet. I would prefer to use x.last(-2), but i believe that is only in RoR.

Called like:

ruby file.rb Helol Wordl

So that each word becomes a parameter. (Not wrapped in quotes)

answered Dec 29, 2017 at 19:28
\$\endgroup\$
3
  • \$\begingroup\$ Doesn’t return the correct results for me. The letters aren’t swapped on all the words. \$\endgroup\$ Commented Dec 29, 2017 at 19:31
  • \$\begingroup\$ @Mr.Xcoder It is because TIO passes the argument in quotes :) Add a argument for each word, and it works \$\endgroup\$ Commented Dec 29, 2017 at 19:42
  • \$\begingroup\$ This works, in practice, atleast on windows you can pass arguments without quotes, hence you can type it as if you typed a regular sentence \$\endgroup\$ Commented Dec 29, 2017 at 19:44
0
\$\begingroup\$

Clojure, (削除) 122 (削除ここまで) 117 bytes

-5 bytes by shortcutting the indices of the characters to swap

(fn[p](map #(let[l(count %)v(vec %)y(dec l)z(- l 2)](apply str(assoc v y(v z)z(v y))))(clojure.string/split p #" ")))

It's a shame that most of Clojure's String function are tucked away inside of Clojure.string, and that there are no good ways of manipulating the characters of Strings directly. clojure.string/split is atrociously long, and the conversion to-and-from vectors added quite a lot. I might be able to shave off a couple bytes by shortcutting the trailing indices, but this is the only decent algorithm I could think of.

(defn flip-last [phrase]
 (let [words (clojure.string/split phrase #" ")]
 ; For each word...
 (map #(let [len (count %)
 ; Need to turn the string into a vector so we can manipulate it using indices
 vec-word (vec %)]
 ; ... then turn the vector of characters back into a String.
 (apply str
 ; Associate the element at the second last index with the element at the last index,
 ; and vice-versa...
 (assoc vec-word (dec len) (vec-word (- len 2))
 (- len 2) (vec-word (dec len)))))
 words)))
answered Dec 31, 2017 at 16:52
\$\endgroup\$
0
\$\begingroup\$

QuadR, 8 bytes

..\b
⌽⍵M

Try it online!

..\b any two characters followed by a word boundary

gets replaced with

⌽⍵M the reverse of the Match


Equivalent to the following 18-byte Dyalog APL function:

'..\b'⎕R{⌽⍵.Match}
answered Feb 1, 2018 at 11:24
\$\endgroup\$
0
\$\begingroup\$

Japt -S, (削除) 7 (削除ここまで) 6 bytes

A port of Jonathan's Jelly solution.

 ̧Ëá ÅÎ

Try it

 ̧Ëá ÅÎ :Implicit input of string
 ̧ :Split on spaces
 Ë :Map
 á : Permutations
 Å : Slice off the first element
 Î : Get the first element
 :Implicit output joined with spaces
answered Dec 27, 2017 at 22:23
\$\endgroup\$
0
\$\begingroup\$

PHP4 (48 chars)

Given $argv[1] as a command line argument :

echo preg_replace('#(.)(.)\b#','2ドル1ドル',$argv[1]);

PHP7.4 (48 chars)

The function $f is inverting the last two chars of every word :

$f=fn($s)=>preg_replace('#(.)(.)\b#','2ドル1ドル',$s);

Try it Online - Usage :

echo $f('Flippign Lettesr Aroudn');

Both versions are using 🐘's PCRE Text Processing Functions.

Info: Support for PHP4 has been discontinued since 2008 but same code still works in PHP8.1.

Mathematica (58 chars)

f=StringReplace[#,RegularExpression["(.)(.)\\b"]:>"2ドル1ドル"]&

Try it online

answered Apr 5, 2022 at 18:37
\$\endgroup\$
0
\$\begingroup\$

Factor, 50 bytes

[ " "split [ 2 cut* reverse append ] map " "join ]

Try it online!

Factor's regular expressions don't support backreferences for philosophical reasons, so here's (possibly) the next best thing. It splits the input on spaces, applies a quotation to each word, and joins them with a space into a single string. Here's how the mapping quotation works:

 ! "Flipping"
2 cut* ! "Flippi" "ng"
reverse ! "Flippi" "gn"
append ! "Flippign"
answered Apr 5, 2022 at 21:32
\$\endgroup\$
0
\$\begingroup\$

AWK, 34 bytes

0ドル=gensub(/(.)(.)\>/,"\2円\1円","g")

Attempt This Online!

Or, before I figured out the regex trick, at 64 bytes:

{for(;$++i;)printf substr($i,1,l=split($i,a,X)-2)a[l+++2]a[l]FS}

answered Aug 22 at 13:08
\$\endgroup\$
1
2

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.