18
\$\begingroup\$

What is Typoglycemia?

Typoglycemia is a term that refers to the phenomenon where readers are able to understand text even when the letters in the middle of words are jumbled, as long as the first and last letters of each word remain in their correct positions. For example,

Aoccdrnig to a rscheearch at Cmabrigde Uinervtisy, it dseno’t mtaetr in waht oerdr the ltteres in a wrod are, the olny iproamtnt tihng is taht the frsit and lsat ltteer be in the rghit pclae.

The rset can be a taotl mses and you can sitll raed it whotuit a pboerlm.

Tihs is bcuseae the huamn mnid deos not raed ervey lteter by istlef, but the wrod as a wlohe. Azanmig huh? Yaeh, and I awlyas tghuhot slpeling was ipmorantt!

However, in this challenge we will implement a minor variation.

Typo Injection Rules

For each sentence, errors will be injected into words longer than four letters. All such words will contain exactly one error. All words with four letters or less will contain no errors.

For example, here are the simple rules applied to this sentence:

The boy could not solve the problem so he asked for help.
Rule Number Description Example
0 Swap the first two letters of the word. The boy oculd not oslve the rpoblem so he saked for help.
1 Swap the second and third letters of the word. The boy cuold not slove the porblem so he aksed for help.
2 For even-length words, swap the middle two letters.
For odd-length words, swap the left-of-middle and middle letters.
The boy cuold not slove the prbolem so he aksed for help.
3 Swap the third- and second-to-last letters of the word. The boy colud not sovle the probelm so he asekd for help.
4 Swap the last two letters of the word. The boy coudl not solev the problme so he askde for help.

Challenge

Input a sentence and start with rule 0 for the first word, regardless of its length. If a word has four or fewer letters, skip modifying it but still advance to the next rule when moving to the next word in the sentence. Cycle through the rules 0-4 for each eligible word and repeat the cycle as necessary until the end of the sentence.

Input

A sentence.

Output

A sentence with each word modified according to the applicable rule.

Test Cases

Input

The quick brown fox jumps over the lazy dog.

Output

The qiuck borwn fox jumsp over the lazy dog.


Input

According to a researcher at Cambridge University, it doesn't matter in what order the letters in a word are, the only important thing is that the first and last letter be at the right place. The rest can be a total mess and you can still read it without problem. This is because the human mind does not read every letter by itself but the word as a whole.

Output

cAcording to a researcehr at aCmbridge Uinversity, it does'nt mattre in what odrer the lettesr in a word are, the only ipmortant tihng is that the frist and last lettre be at the rihgt plac.e The rest can be a ottal mess and you can tsill read it withuot proble.m This is beacuse the humna mind does not read eveyr eltter by iteslf but the word as a whoel.

\$\endgroup\$
4
  • \$\begingroup\$ Is there a mistake at "without problem." -> "withuot proble.m"? Same with "right place." -> "rihgt plac.e" \$\endgroup\$
    – enzo
    Feb 8 at 22:41
  • 2
    \$\begingroup\$ Nah, any punctuation characters such as a period (.) are not treated any differently. Although, it does look weird, so no objections if your code handles them better. \$\endgroup\$
    – vengy
    Feb 8 at 22:53
  • \$\begingroup\$ Does that mean punctuation just counts as if it was a letter? \$\endgroup\$
    – Xcali
    Feb 8 at 23:00
  • \$\begingroup\$ Correct. It's still readable. Although, my spelling is worse after having worked on this challenge. ;) \$\endgroup\$
    – vengy
    Feb 8 at 23:04

14 Answers 14

4
\$\begingroup\$

Rattle, 181171 bytes

\ |P3II^s0P3[=#+3g`n[^32g1+s1][32g1>4*1[1g2[0g1<^`g>$<sg1>^`]g2[1g1<^`>g>$<s<g1>^`]g2[2g1<^`g1/2>^`g<$>sg1>^`g1/2<^`]g2[3<<g<$>s>>]g2[4<g<$>s>]]=s1g2+%5s2]>]`g0-[=#+3g`b]`

Try it Online!

This is not necessarily the shortest this code can get but it's a start.

Explanation

|                           take input ("\ " adds a space)
 P3                         move pointer to slot 3 (slots 0,1,2 will be used differently)
   I                        place all characters from input in consecutive memory slots
    I^                      get length of input
      s0                    save length of input in slot 0
        P3                  set the pointer to 3
          [...]`            loop over each character of the input

Inside this main loop, [^32...] just increments a counter if the current character is not a space. If the character is a space ([32...]), it applies the applicable rule ([0...] for rule 0, etc.) then increments the rule counter before resetting the word-length counter.

g0[=#+3g`b]`

This just reads over each modified character and outputs the final string.

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

Python 3, 159 156 154 144 138 bytes

def f(t,*R):
 for*C,in t.split():s=len(C);g=s>4;i=g*[2,4,s,-4,-2][len(R)%5]//2-1;C[i],C[i+g]=C[i+g],C[i];R+=''.join(C),
 return' '.join(R)

Try it online!

  • -3 bytes by using a lambda for g
  • -2 bytes by inlining c
  • -10 bytes by removing g
  • -6 bytes by removing the if-statement

A function f that accepts the sentence as a string and returns the modified sentence as string.

How does it work?

Create a empty tuple. At the end, this tuple will be joined to a string and Returned.

Declare a for-loop. Since every iteration adds an element to R, the size of R equals to the current iteration number, 0-indexed. The loop says:

  • for each word in the text provided as input, transform it into a list of Characters
  • get its size and check if it's greater than 4
    • if it is, get the current rule number (remainder of the division between the current iteration number and 5), retrieve the factor corresponding to that rule ([2,4,s,-4,-2]), integer-divide it by 2 (//2), subtract one (-1), and set i to the result
      • for rule 0, it will give \$\lfloor \frac{2}{2} \rfloor\ - 1 = 1-1=0\$ (a.k.a. the first letter)
      • for rule 1, it will give \$\lfloor \frac{4}{2} \rfloor - 1 = 2-1=1\$ (a.k.a. the second letter)
      • for rule 2, it will give \$\lfloor \frac{s}{2} \rfloor - 1\$ (a.k.a. the left-middle letter)
      • for rule 3, it will give \$\lfloor \frac{-4}{2} \rfloor - 1=-2-1=-3\$ (a.k.a. the third-to-last latter)
      • for rule 4, it will give \$\lfloor \frac{-2}{2} \rfloor - 1=-1-1=-2\$ (a.k.a. the second-to-last latter)
    • otherwise, set i to \$\lfloor \frac{0}{2} \rfloor - 1=0-1=-1\$
  • Swap the letter at index i with the letter at index i+g. The expression i+g evaluates to i+1 if the size of the word is greater than 4 (i.e. the next letter after i), otherwise evaluates to i (i.e. the same letter as i, equivalent to "do nothing")
  • Convert the list of Characters to a string again, and add it to R

Join the accumulator to a string and return it.

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

Perl 5 + -040plF, 60 bytes

@F>4&&s;^.{@{[(@F-2,0,1,0|@F/2-1,@F-3)[$.%5]]}}\K(.)(.);$2$1

Try it online!

Explanation

First the flags: -040 (in combination with the implied -n from -p) splits input strings on space and runs the code for each, -p implies -n (which reads input automatically and stores in $_) and -prints out $_ at the end of the script, -l strips off the space for processing and adds it back on when printing, and -F splits the string so that each char of the input is stored in @F.

If @F contains more than 4 elements (i.e. the string is longer than 4 chars) run a s;ubstituion on $_ swapping the next two chars after the first n (e.g s/.{n}(.)(.)/$2$1/), where n is defined using an inline array, indexed using $. (which is the current "line" of input, which since we're using space to split our "lines" is the, 1-indexed, word we're working on) modulo 5. The values of n are 0 (first two chars), 1 (second and third), 0|@F/2-1 (the middle two, or left-most of middle and middle), @F-3 (the first two of the last three), @F-2 (the last two), but the list is shifted by one as we need to account for the 1-indexed count. The s///ubstitution is delimited by ; so that we can use the implied ; from the while ($_ = <STDIN>) {...;} produced by -n.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Nice! I was trying to get something working with -040 but it just wasn't happening for me. \$\endgroup\$
    – Xcali
    Feb 9 at 14:53
2
\$\begingroup\$

C (gcc), 240 bytes

#include <string.h>
a,b,l,r;f(char*s){r=0;char*w=strtok(s," ");while(w){l=strlen(w);if(l>4){a=r==0?0:r==1?1:r==2?l/2:r==3?l-3:l-2;b=r<2?a+1:r==2?l/2-1:r==3?l-2:l-1;w[a]^=w[b];w[b]^=w[a];w[a]^=w[b];}printf("%s ",w);w=strtok(0," ");r=-~r%5;}}

Try it online!

How it works?

Nothing too magical here but the main gist is

  • Split the sentence into words. (space delimited)
  • Perform an XOR swap of the two characters without using a temporary variable.

Output

The qiuck borwn fox jumsp over the lazy dog.

cAcording to a researcehr at aCmbridge Uinversity, it does'nt mattre in what odrer the lettesr in a word are, the only ipmortant tihng is that the frist and last lettre be at the rihgt plac.e The rest can be a ottal mess and you can tsill read it withuot proble.m This is beacuse the humna mind does not read eveyr eltter by iteslf but the word as a whoel.

\$\endgroup\$
1
  • 4
    \$\begingroup\$ 195 \$\endgroup\$
    – ceilingcat
    Feb 9 at 0:18
2
\$\begingroup\$

Perl 5 -p, 118 bytes

s|\S+|$p=("..",'.\K..',"."x(($z=length$&)/2-1).'\K..','..(?=.$)','..$')[$i++%5];$z>4?$&=~s;$p;reverse$&=~/./g;er:$&|ge

Try it online!

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

Uiua SBCS, 59 57 bytes

/$"_ _"≡⊔(□(◌|⍜⊏⇌)>4⧻,⊟+1.(0|1|-1⌊÷2⧻.|¯3|¯2))◿5⇡⧻.⊜□≠@ .

Try it!

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

05AB1E, 39 bytes

#εDg©4›i1Ý2L®;D<‚®3-D>‚D>)ćDrNè©è®Rǝ]ðý

Try it online.

Explanation:

#                   # Split the (implicit) input-sentence on spaces
 ε                  # Map over each word:
  D                 #  Duplicate the current word
   g                #  Pop the copy, and push its length
    ©               #  Store this length in variable `®` (without popping)
     4›i            #  If the length is larger than 4:
        1Ý          #   Push [0,1]
        2L          #   Push [1,2]
        ®;          #   Push halve the length
          D<        #   Duplicate it, and decrease it by 1
            ‚       #   Pair the two together: [length/2,length/2-1]
        ®3-         #   Push the length-3
           D>       #   Duplicate, and increase it by 1
             ‚      #   Pair the two together: [length-3,length-2]
        D           #   Duplicate the pair
         >          #   Increase both values in the copy by 1: [length-2,length-1]
        )           #   Wrap all values on the stack into a list
         ć          #   Extract the head; push first item and remainder-list separately
          D         #   Duplicate the extracted word
           r        #   Reverse the order from pairList,word,word to word,word,pairList
            Nè      #   Modular index the current map-index into the list of pairs
              ©     #   Store this as new variable `®` (without popping)
               è    #   Index into the word to get the pair of characters
                ®   #   Push index-pair `®` again
                 R  #   Reverse it
                  ǝ #   Insert the characters back into the word at those indices
                    #  (implicit else: use the duplicated unmodified word instead)
 ]                  # Close both the if-statement and map
  ðý                # Join it back together with space delimiter
                    # (after which the modified sentence is output implicitly as result)

©è®Rǝ is taken from my answer for the Swap Two Values in a List challenge.

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

Ruby, 94 93 characters

->s{i=0;s.gsub(/\S+/){|w|r=[-1,1,2,w.size/2,-2][(i+=1)%5];w[4]&&(w[r],w[r-1]=w[r-1],w[r]);w}}

Sample run:

irb(main):003:0> ->s{i=0;s.gsub(/\S+/){|w|r=[-1,1,2,w.size/2,-2][(i+=1)%5];w[4]&&(w[r],w[r-1]=w[r-1],w[r]);w}}['The quick brown fox jumps over the lazy dog.']
=> "The qiuck borwn fox jumsp over the lazy dog."

Try it online!

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

Bash (GNU sed + tr), 188 177 bytes

tr \  \\n|sed -E '/.{5}/!b
1~5s/../ & /
2~5s/(.)(..)/\1 \2 /
3~5{s/.+/ & /
:1 s/ (.)(..+)(.) /\1 \2 \3/
t1}
4~5s/(..)(.)$/ \1 \2/
5~5s/..$/ & /
s/ (.)(.)(.?) /\2\1\3/'|tr \\n \ 

Try it online!

  • rtanslate wrods to liens and back
  • Skip sohrt wodrs immediateyl
  • Tag traget charcaters for each rule by frmaing them with psaces (use loop to move psaces iwnard from both ends for rule #2)
  • Finally swap hcaracters
  • Otpionally add |haed -c-1 to kill traliing spcae (+10 hcars)
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for help. Did edit. \$\endgroup\$ Feb 12 at 19:46
1
\$\begingroup\$

Charcoal, 48 bytes

⪫E⪪S ⭆⟦⁻⊗§⟦¹¦²÷Lι²⁻Lι²⊖Lι⟧κ›Lι⁴⟧⭆ι⎇⊖↔⁻⊗ξλν§ι⁻λξ 

Try it online! Link is to verbose version of code. Explanation:

⪫E⪪S ... 

Split the input on spaces and map over each word separately.

⭆⟦⁻⊗§⟦¹¦²÷Lι²⁻Lι²⊖Lι⟧κ›Lι⁴⟧...

Get the sum of the positions that need to be swapped. This is twice the upper position minus 1, except for words that are fewer than five characters long, in which case any even value will do. The upper position is calculated in a similar way to @enzo's Python answer. The resulting value is wrapped in a list and iterated over so that it can be referred to twice in the expression below.

⭆ι⎇⊖↔⁻⊗ξλν§ι⁻λξ

Map over the characters of the word, swapping the characters at positions -~x/2 and ~-x/2 (if x is odd).

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

Retina 0.8.2, 212 bytes

S` 
((.)(.)(...+)|(.+))((¶.)(.)(.)(..+)|(¶.+))?((¶(?=.{5})(.)+)(.)(.)((?<-14>.)+.?)(?(14)^)|(¶.+))?((¶..+)(.)(.)(.)|(¶.+))?((¶...+)(.)(.)|(¶.+))?
$3$2$4$5$7$9$8$10$11$13$16$15$17$18$20$22$21$23$24$26$28$27$29
¶
 

Try it online! Link includes test cases. This regex is just too ugly to explain, I mean it has 29 capturing groups for goodness sake. So let's move on to the slightly shorter direct Retina 1 port:

S` 
#5`(.)(.)(...+)|(.+)
$2$1$3$4
(.)(.)(.)(..+)|(.+)
$1$3$2$4$5
(?=.{5})((.)+)(.)(.)((?<-2>.)+.?)(?(2)^)|(.+)
$1$4$3$5$6
(..+)(.)(.)(.)|(.+)
$1$3$2$4$5
(...+)(.)(.)|(.+)
$1$3$2$4
¶
 

Try it online! Link includes test cases. Explanation:

S` 
¶
 

Split the input string on spaces before processing and finish by joining the words with spaces.

#5`

Perform each of 5 substitutions in turn. What this does is that after each replacement is made, the next match is performed using the next substitution's regex. This also needs to happen for the short words, which is why the matches all have to include a "default case", plus also they must match the whole word exactly, rather than just the parts of the word being substituted.

(.)(.)(...+)|(.+)
$2$1$3$4

The 1st, 6th, 11th etc. words have their first two characters exchanged if there are at least three more characters left.

(.)(.)(.)(..+)|(.+)
$1$3$2$4$5

The 2nd, 7th, 12th etc. words have their second and third characters exchanged if there are at least two more characters left.

(?=.{5})((.)+)(.)(.)((?<-2>.)+.?)(?(2)^)|(.+)
$1$4$3$5$6

The 3rd, 8th, 13th etc. words have their middle characters exchanged if there are at least five characters in the word. A .NET balancing group is used to ensure that there are at least as many characters after the middle characters as there were before.

(..+)(.)(.)(.)|(.+)
$1$3$2$4$5

The 4th, 9th, 14th etc. words have their second and third last characters exchanged if they follow at least two characters.

(...+)(.)(.)|(.+)
$1$3$2$4

The 5th, 10th, 15th etc. words have their last two characters exchanged if they follow at least three characters.

However, Retina 1 can do better than this - you can iterate over every 5th line starting at the line of your choice using a per-line compound stage with a step limit, like this:

S` 
,5,%V`^..(?=...)
1,5,%V`(?<=^.)..(?=..)
2,5,%V`(?<=(?=.{5})(.)+)..(?=(?<-1>.)+.?$)(?(1)^)
3,5,%V`(?<=..)..(?=.$)
4,5,%V`(?<=...)..$
¶
 

Try it online! Link includes test cases. Explanation: Here because the step limits on the per-line stages guarantee that the right regex runs on the right lines, we can simply run reVerse stages that match the appropriate characters of each word.

\$\endgroup\$
1
  • \$\begingroup\$ Nice. The code looks like an alien transmission from space. :) \$\endgroup\$
    – vengy
    Feb 9 at 12:12
1
\$\begingroup\$

Jelly, 25 bytes

ḲẈ’_‘:¥ṛṠ5ƭ€2!a@>ʋ4‘œ?"ḲK

A monadic Link that accepts a list of characters and yields a list of characters reordered as described by the rules.

Try it online!

How?

Swapping the \$i^{\text{th}}\$ and \$(i+1)^{\text{th}}\$ characters of a length \$N\$ string gives the \$((N-i)!+1)^{\text{th}}\$ permutation of the string in a list of all permutations of that string ordered by the original characters' indices. The code calculates these indices, forces the values for short words to \$1\$, and then uses the œ? atom to calculate the required permutations of each word.

ḲẈ’_‘:¥ṛṠ5ƭ€2!a@>ʋ4‘œ?"ḲK - Link: list of characters, Text
Ḳ                         - {Text} split at spaces
 Ẉ                        - {that} length of each -> Sizes
                 ʋ4       - last four links as a dyad - f(Sizes, 4):
           €              -   for each {Size in Sizes}:
         5ƭ 2             -     apply the last five links in turn - f(Size, 2):
  ’                       -       {Size} decrement        -> (R0): Size - 1
   _                      -       {Size} subtract {2}     -> (R1): Size - 2
      ¥                   -       last two links as a dyad - f(Size, 2):
    ‘                     -         {Size} increment
     :                    -         integer divide by {2} -> (R2): (Size + 1) div 2
       ṛ                  -       right argument          -> (R3): 2
        Ṡ                 -       {Size} sign             -> (R4): 1
                                 -> N-i from the description above this code-block
             !            -   {that} factorial (vectorises)
                >         -   {Size} greater than {4}?
               @          -   with swapped arguments:
              a           -     {isLong} logical AND {the factorial} (vectorises)
                               -> replaces the factorial with 0 when Size<5
                   ‘      - increment (vectorises) -> WordPermValues
                       Ḳ  - {Text} split at spaces -> Words
                      "   - zip with:
                    œ?    -   permutation at index {WordPermValue} of {Word}
                        K - {that} joined with spaces
\$\endgroup\$
1
\$\begingroup\$

J, 61 60 bytes

;:inv@(A.&.>~[:(<@0 1|:4&<*#!@$1,~2,~>.@-:,~1 2-~/])#&>)&cut

Try it online!

'The quick brown fox jumps over the lazy dog.', eg:

  • &cut Chop input into boxed words:

    ┌───┬─────┬─────┬───┬─────┬────┬───┬────┬────┐
    │The│quick│brown│fox│jumps│over│the│lazy│dog.│
    └───┴─────┴─────┴───┴─────┴────┴───┴────┴────┘
    
  • #&> Lengths of each word:

    3 5 5 3 5 4 3 4 4
    
  • J has an "anagram" primitive A., which associates a single number to every possible permutation of a list. We now notice the following:

    • Swapping the final two elements of any list has anagram number 1.
    • Swapping the two before that has anagram number 2.
    • Swapping the "middle two" (with left bias) has number factorial(ceiling(length/2)).
    • Swapping indexes 1 and 2 has number factorial(length-2)
    • Swapping indexes 0 and 1 has number factorial(length-1)
  • 1,~2,~>.@-:,~1 2-~/] This constructs a 5 row matrix where each row represents the transforms described above (without factorial applied yet -- we'll do that momentarily) applied to every element of the length list:

    2 4 4 2 4 3 2 3 3 <-- length - 1
    1 3 3 1 3 2 1 2 2 <-- length - 2
    2 3 3 2 3 2 2 2 2 <-- ceil(length/2)
    2 2 2 2 2 2 2 2 2 <-- 2
    1 1 1 1 1 1 1 1 1 <-- 1
    
  • #$ Extend the rows cyclically until the matrix is square:

    2 4 4 2 4 3 2 3 3
    1 3 3 1 3 2 1 2 2
    2 3 3 2 3 2 2 2 2
    2 2 2 2 2 2 2 2 2
    1 1 1 1 1 1 1 1 1
    2 4 4 2 4 3 2 3 3
    1 3 3 1 3 2 1 2 2
    2 3 3 2 3 2 2 2 2
    2 2 2 2 2 2 2 2 2
    
  • !@ Take the factorial of each:

    2 24 24 2 24 6 2 6 6
    1  6  6 1  6 2 1 2 2
    2  6  6 2  6 2 2 2 2
    2  2  2 2  2 2 2 2 2
    1  1  1 1  1 1 1 1 1
    2 24 24 2 24 6 2 6 6
    1  6  6 1  6 2 1 2 2
    2  6  6 2  6 2 2 2 2
    2  2  2 2  2 2 2 2 2
    
  • 4&<* Zero out any rows where the words have length 4 or less:

    0 0 0 0 0 0 0 0 0
    1 6 6 1 6 2 1 2 2
    2 6 6 2 6 2 2 2 2
    0 0 0 0 0 0 0 0 0
    1 1 1 1 1 1 1 1 1
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0
    
  • <@0 1|: And take the main diagonal of the above matrix:

    0 6 6 0 1 0 0 0 0
    

    We now have the anagram number we need for each word in the list.

  • A.&.>~ Apply the anagram to each boxed word:

    ┌───┬─────┬─────┬───┬─────┬────┬───┬────┬────┐
    │The│qiuck│borwn│fox│jumsp│over│the│lazy│dog.│
    └───┴─────┴─────┴───┴─────┴────┴───┴────┴────┘
    
  • ;:inv@ Unbox and join with spaces (weirdly cut as a monad does not have its natural inverse (join on spaces) defined, otherwise we could save 5 bytes):

    The qiuck borwn fox jumsp over the lazy dog.
    
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 106 bytes

s=>s.replace(/\S+/g,w=>w[s=++s%5|0,4]?w.slice(0,q=s<2?s:(w.length-2>>2/s)-s%2)+w[q+1]+w[q]+w.slice(q+2):w)

Try it online!

Commented

s =>               // s = input string, re-used as the rule counter
s.replace(         // replace in s,
  /\S+/g,          // looking for 'words' (punctuation included)
  w =>             // for each word w in s:
  w[               //
    s = ++s % 5    //   increment the rule counter,
        | 0,       //   or set it to 0 if it's still NaN'ish
    4              //   test the 5th character
  ] ?              //   if the word contains at least 5 characters:
    w.slice(       //     extract the left part:
      0,           //       from 0
      q =          //       to q - 1, where q is defined as:
      s < 2 ?      //         if s < 2:
        s          //           use s (rules 0 and 1)
      :            //         else:
        ( w.length //           use the word length 
          - 2      //           minus 2 (default value for rule 4)
          >> 2 / s //           halved and floored if this is rule 2
        ) - s % 2  //           minus 1 if this is rule 3
    ) +            //     end of slice()
    w[q + 1] +     //     \__ followed by the characters at q and q+1,
    w[q] +         //     /   swapped
    w.slice(q + 2) //     followed by the right part
  :                //   else:
    w              //     leave w unchanged
)                  // end of replace()
\$\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.