20
\$\begingroup\$

Given a string, replace all left-double-quotes into two backticks and all right-double-quotes into two single-quotes.

Left-quotes means the quotes that starts a quote. Right-quotes means the quotes that ends a quote. Quotes cannot be nested. You may assume that there are an even number of double-quotes in the string.

Examples

Input:

"To be or not to be," quoth the Bard, "that
is the question".
The programming contestant replied: "I must disagree.
To `C' or not to `C', that is The Question!"

Output:

``To be or not to be,'' quoth the Bard, ``that
is the question''.
The programming contestant replied: ``I must disagree.
To `C' or not to `C', that is The Question!''
\$\endgroup\$
9
  • \$\begingroup\$ What are left double quotes and right double quotes? \$\endgroup\$ Aug 24, 2019 at 7:35
  • 1
    \$\begingroup\$ @someone Left double quotes are the quotes that begins a quote. Right double quotes are the quotes that ends a quote. \$\endgroup\$ Aug 24, 2019 at 7:36
  • \$\begingroup\$ Can quotes be nested? \$\endgroup\$ Aug 24, 2019 at 7:38
  • \$\begingroup\$ @someone Nope. They can't. \$\endgroup\$ Aug 24, 2019 at 7:39
  • 3
    \$\begingroup\$ @LegionMammal978 "Can quotes be nested?" ... "@someone Nope. They can't." \$\endgroup\$ Aug 24, 2019 at 22:56

29 Answers 29

21
\$\begingroup\$

Unreadable, 789 777 bytes

-12 bytes by using variable X34 rather than X6.

'""""""'""'"""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'"""'""""""'""'""'""'""'"""'""'""'""'""'""'"""""""'""'"""'"""""'""'""""""'"""'""""""""""'""""'""""""'""'""'""'"""'"""""""'""'"""'""""'""""""'""'""'"""'"""""""'"""'""""'"""""'"""""""'""'""'""'"""'""""'""""""'""'""'""'"""'""""""""'"""""""'""'""'""'"""'""""""'""'""'"""'""""""""'"""""""'""'""'"""'"""""""""'"""""""'""'""'"""'"'"""""""'"""'"'"""""""""'"""""""'"""""""'""'"""'""""'""""""'"""""""'""'"""'""""""""'"""'"'"""""""'""'""'""'""'"""'""""'""""""'"""""""'""'"""'"""'"'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'"""""""'""'""'""'""'"""

Try it online!

Displayed in variable-width font, per the traditional tribute to the language name.

I learnt Unreadable for this challenge, because it is obviously the best tool for the job. The only characters allowed in Unreadable are ' and ", so surely it is perfectly suited to a challenge which involves changing " into ''. Isn't it?

Explanation:

'""""""'""'""" assign to X2
'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""" 34 (double quote sign)
'""""""'""'""'""'""'""" assign to X5
'""'""'""'""'""'"""""""'""'""" X2+5 (apostrophe sign)
'"""""'""'""""""'"""'"""""""""" while (1+ (assign to X1 a value read from stdin, or -1 if stdin is empty) != 0)
 '"""" do 2 things
 '""""""'""'""'""'""" assign to X4
 '"""""""'""'""" the value of X2
 AND
 '"""" do 2 things
 '""""""'""'""'""" assign to X3
 '"""""""'""" the value of X1
 AND
 '"""" do 2 things
 '"""""'"""""""'""'""'""'""" while(X4 != 0)
  '"""" do 2 things
  '""""""'""'""'""'""" assign to X4
  '""""""""'"""""""'""'""'""'""" X4-1
  AND
  '""""""'""'""'""" assign to X3
  '""""""""'"""""""'""'""'""" X3-1
 end while
 AND
 '"""""""""'"""""""'""'""'""" if(X3 != 0)
  '"'"""""""'""" print X1
 else
  '" print the output of
  '"""""""""'"""""""'"""""""'""'""" if(X34 !=0)
   '"""" do 2 things
   '""""""'"""""""'""'"""'""""""""'""" assign X34=0
   AND
   '"'"""""""'""'""'""'""'""" print X5
  else
   '"""" do 2 things
   '""""""'"""""""'""'"""'""" assign X34=1
   AND
   '"'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'"""""""'""'""'""'""'""" print X5+57
 end if
end while

(Calls to X34 are actually calls to X(X5), since X5=34.)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ A quoty language in a quoty challenge LOL \$\endgroup\$ Aug 27, 2019 at 9:45
6
\$\begingroup\$

TeX, 54 32 bytes

For a TeX quotes replacement challenge we also need a TeX version of course!

\catcode`"13\def"#1"{``#1''}...\bye

... is the input string, so it doesn't add to the byte count.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Why not the simpler \def"#1"{``#1''}? (or \long\def if you expect a quote to cross a paragraph boundary) \$\endgroup\$ Aug 26, 2019 at 10:11
  • 1
    \$\begingroup\$ For the obvious reason that I didn't think of that :-) \$\endgroup\$
    – siracusa
    Aug 26, 2019 at 19:47
5
\$\begingroup\$

Retina, 13 bytes

Learning Retina quickly because for some reason I don't like Japt winning and feel like a C# solution would use regular expressions anyway. I know there is a Retina answer, but I haven't used it when creating this, and I found it (exactly) too anyway.

#2$`"
``
"
''

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Why the hate for Japt?! :p \$\endgroup\$
    – Shaggy
    Aug 24, 2019 at 13:11
5
\$\begingroup\$

JavaScript (ES9), 34 bytes

Working on quoted blocks:

s=>s.replace(/"(.*?)"/gs,"``$1''")

Try it online!


JavaScript (ES6), 38 bytes

Working on each double-quote separately:

s=>s.replace(/"/g,_=>(c="'`"[s^=1])+c)

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ dotAll flag for RegExp is new feature of ECMAScript 2018, not included in ES6. \$\endgroup\$
    – tsh
    Aug 26, 2019 at 2:10
  • \$\begingroup\$ @tsh Good catch. Updated. \$\endgroup\$
    – Arnauld
    Aug 26, 2019 at 9:11
4
\$\begingroup\$

Jelly, 15 13 bytes

⁾``⁾''2ƭ”"Ƒ¡€

Try it online!

Full program.

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

Python 3, 65 bytes

f=lambda s:s and(s[0],"`'"[s.count('"')%2]*2)[s[0]=='"']+f(s[1:])

Try it online!

-8 bytes thanks to Erik the Outgolfer

\$\endgroup\$
2
  • \$\begingroup\$ As for the second function, you can remove 8 bytes (it's not as different as it may seem, I just replaced the s[0].replace with an explicit s[0]=='"' check, along with some other modifications). \$\endgroup\$ Aug 24, 2019 at 13:08
  • \$\begingroup\$ @EriktheOutgolfer Nice finds, thanks! \$\endgroup\$
    – Jitse
    Aug 24, 2019 at 13:42
4
\$\begingroup\$

Japt, 12 bytes

Would be 11 only for a limitation of (or maybe it's a bug in) Japt.

r'"ȲîT°g"`'

Try it

r'"ȲîT°g"`'     :Implicit input of string
r'"              :Replace double quotes
   È             :Pass each match through a function
    ²            :  Duplicate
     î           :  Replace each character with
      T°         :    Postfix increment T (initially 0)
        g"`'     :    Index into "`'" with wrapping
\$\endgroup\$
3
  • \$\begingroup\$ It's too bad you can't use Q here :\ \$\endgroup\$
    – Oliver
    Aug 26, 2019 at 19:56
  • \$\begingroup\$ @Oliver, I can (and I originally did); I'd just need a , too. \$\endgroup\$
    – Shaggy
    Aug 26, 2019 at 20:07
  • \$\begingroup\$ I mean it's too bad you couldn't simply use Q in place of '" \$\endgroup\$
    – Oliver
    Aug 26, 2019 at 20:11
3
\$\begingroup\$

!@#$%^&*()_+, 22 21 bytes

`'("_*("+@"_*)+$!!@@)

Try it online!

Terminates with an error. 21 looks like an impressive score, beating quite a few languages including Charcoal. Inspired by this.

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

Charcoal, 23 bytes

WS⊞υι⭆⪪⪫υ¶¦"⎇κ⁺ײ§'`κιι

Try it online! Link is to verbose version of code. Includes 8 bytes to avoid a cumbersome input format. Explanation:

WS⊞υι

Collect input lines until an empty line is reached.

⪫υ¶¦

Join the lines on newline characters.

⪪..."

Split the input on quotes.

⭆...

Map over each part and concatenate the results for implicit print.

⎇κ...ι

Leave the first part unchanged.

⁺ײ§'`κι

Prefix the appropriate quote, doubled.

\$\endgroup\$
1
  • \$\begingroup\$ I was waiting for a Charcoal solution. Nice! \$\endgroup\$ Aug 24, 2019 at 11:24
2
\$\begingroup\$

R, 40 bytes

cat(scan(,"",,,'"',""),sep=c("``","''"))

Try it online!

Reads string input, separating at each ", giving a vector of strings. Then pastes those strings, alternating between the double backticks and the double apostrophes as separators, recycling them as needed.

Someone will probably post a shorter R answer based on a regex... Still, this answer is more typical of R, I think.

Explanation of the scan(,"",,,'"',"") part:

scan(, # empty first parameter: read from STDIN
  "",  # type of input is a string
  ,    # default 3rd parameter nmax
  ,    # default 4th parameter n
  '"', # separate on character "
  "")  # do not treat any characters as quotations marks (necessary to handle ' in the input)
\$\endgroup\$
0
2
\$\begingroup\$

Jelly, 13 bytes

ṣ”"µJḊ⁾`'ṁḤż@

A full program.

Try it online!

How?

ṣ”"µJḊ⁾`'ṁḤż@ - Main Link: list of characters, T   e.g. ..."hi" - she "said"...
 ”"           - character '"'                           '"'
ṣ             - split (T) at ('"')                      ["...","hi"," - she ","said","..."]
   µ          - (call that X) start a new monadic chain
    J         - range of length (of X)                  [1,2,3,4,5]
     Ḋ        - dequeue                                 [2,3,4,5]
      ⁾`'     - list of characters                      ["`","'"]
         ṁ    - mould like                              ["`","'","`","'"]
          Ḥ   - double                                  ["``","''","``","''"]
           ż@ - (with reversed @rguments) zip (with X)  [["...","``"],["hi","''"],[" - she ","``"],["said","''"],["..."]]
              - implicit (smashing) print               ...``hi'' - she ``said''...
\$\endgroup\$
2
\$\begingroup\$

Labyrinth, (43?) 53 bytes

396"
 } "",)@
  ~"  (
 "~ 3_:
""" 4
" .;-
=   ;
..::;

Try it online!

A golfed version of this, much simpler, 92 byte program:

3 """
9 " ",)@
}96 " (
    " :_34-;;
    "     ; :
   """"""". :
   "        .
   """"""""=.

If we don't need to handle input containing the zero byte then 43 bytes:

39}9
@  6
`,""
`  "
: ."=..
_ ;   "
34-;;::
\$\endgroup\$
2
\$\begingroup\$

Perl 6, 23 bytes

{S:g/\"(.*?)\"/``$0''/}

Try it online!

Darn, the obvious solution is shorter. Replaces each quoted portion with a version with the appropriate quotes.

Perl 6, 24 bytes

{S:g{\"}=<`` ''>[$++%2]}

Try it online!

Replaces each double quote, alternating between the two sets of characters.

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

Red, 79 bytes

func[s][q:"^""parse s[any[to change[q copy t to q q](rejoin["``"t"''"])skip]]s]

Try it online!

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

Retina, 15 bytes

"
""
Y`"`\`\`''

Try it online! Edges out the boring Retina 0.8.2 answer by 1 byte. Explanation:

"
""

Duplicate all of the quotes.

Y`"`\`\`''

Cyclically replace the quotes with pairs of backticks and single quotes.

Boring 16-byte Retina 0.8.2 answer for completeness:

s`"(.*?)"
``$1''

Try it online!

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

PHP, 62 bytes

Non-RegEx solution:

for(;''<$l=$argv[1][$i++];)echo$l=='"'?["''","``"][++$j%2]:$l;

Try it online!


PHP, 48 bytes

Port of Arnauld's RegEx solution:

<?=preg_replace('/"(.*?)"/s',"``$1''",$argv[1]);

Try it online!

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

C (gcc), 69 68 bytes

t=39,z;f(char*s){z=*s-34?*s:257*(t^=71);printf("%s",&z);*++s&&f(s);}

Try it online!

One byte shaved off by @ceilingcat!

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

Python 2, 57 bytes

lambda s:re.sub('"(.*?)"',r"``\1''",s,flags=16)
import re

Try it online!

Although I really like Jitse's answer.

\$\endgroup\$
1
  • \$\begingroup\$ -4 Bytes if you use inline flags instead of the flags argument: r'(?s)"(.*?)"' \$\endgroup\$ Aug 27, 2019 at 14:27
1
\$\begingroup\$

(GNU) sed, 38 33 30 bytes

-4 by removing the -n flag and implicitly printing on n, -1 by reusing previous /expression/, thanks @Cowsquack. -3 by using implicit branch-to-end.

:a
s/"/``/;T
:b
s//''/;ta
n;bb

Try it online! Try it online! Try it online!

Some pretty basic label jumping. This can probably be golfed by a byte or two.

:a          # label a
s/"/``/;T   # replace " -> ``. If unsuccessful, move to next line
:b          # label b
s//''/;ta   # replace " (implicit) -> ''. If successful, jump to a (w/o reading new line)
n;bb        # read in the next line, but jump to label b. 
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Btw typically the flags used are specified in the header. You can golf a byte using codegolf.stackexchange.com/a/167295/41805, in addition some of the branching logic can be removed. Then making the solution work without the -n flag should save a bit more. (And of course there is the trivial sed -z solution which I presume you to have intentionally avoided) \$\endgroup\$
    – user41805
    Aug 25, 2019 at 13:56
  • \$\begingroup\$ Alright, I dug back into man sed for a bit and got to 30. Feel free to let me know anything I missed, you've got the golf experience on this lang. (Oh, -z is new to me, but I agree. I'll stay without it.) \$\endgroup\$ Aug 25, 2019 at 14:17
  • \$\begingroup\$ Nicely done, I am always glad to see a sed answer \$\endgroup\$
    – user41805
    Aug 25, 2019 at 14:59
1
\$\begingroup\$

Stax, 11 bytes

û╩↕H£ñ╟Uzay

Run and debug it

Procedure:

  1. Take all input, newlines and all.
  2. Regex replace '"' with a block that produces alternating outputs of pairs of backticks and foreticks(?)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ -1 if you take a triple quoted string? \$\endgroup\$
    – Razetime
    Jun 15, 2021 at 7:30
1
\$\begingroup\$

05AB1E, 15 bytes

'"¡ā¨„'`sè2×.ιJ

Try it online!

No regexes in 05AB1E, so we split on ", make a list of alternating `` and '', then interleave the two.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Ok, looks like I don't have to fix and undelete my answer. ;) \$\endgroup\$ Aug 26, 2019 at 11:57
1
\$\begingroup\$

Haskell, 67 60 58 bytes

(#0)
('"':x)#n=["``","''"]!!n++x#(1-n)
(a:b)#n=a:b#n
x#n=x

Try it online!

The relevant function is (#0).

Since I originally thought the question also required us to convert single quotes here is a version that handles both:

Haskell, 125 bytes

(#(1<0,1<0))
('"':x)#(m,n)=last("``":["\""|m])++x#(not m,n)
('\'':x)#(m,n)=last('`':['\''|n]):x#(m,not n)
(a:x)#n=a:x#n
x#n=x

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ "\"" should be "''" (two apostrophes) \$\endgroup\$
    – siracusa
    Aug 26, 2019 at 3:23
  • \$\begingroup\$ @siracusa Thanks, I assumed since you can use " in tex you could use it here. \$\endgroup\$
    – Wheat Wizard
    Aug 26, 2019 at 14:31
1
\$\begingroup\$

QuadR, 14 bytes

"(.*?)"
``\1''

Try it online!

Simple find/replace using @Adám's wrapper for Dyalog APL's ⎕Replace function.

How:

"(.*?)" ⍝ PCRE, finding anything between two double quotes and assigning it to group 1
``\1''  ⍝ Transformation string, replacing the match with ``group_1''.
\$\endgroup\$
1
\$\begingroup\$

GolfScript, 35 34 bytes

1:c;{.34={;c)2%:c'""'"``"if}""if}%

Try it online!

Explanation

1:c;                                # Set 1 to the current item counter

    {                            }% # Map for every character in the input:
     .34=                      if   #     If the character isn't the quote,
                             ""     #         Just leave it alone
         {                  }       #     Otherwise:
          ;                         #         Remove the copy of the input
           c):c                     #         Increment the counter
                2%        if        #         If the counter isn't divisible by 2, 
                  '""'              #             Output the double-quote
                      "``"          #         Otherwise: Output the double backtick
\$\endgroup\$
1
\$\begingroup\$

Vyxal Ṡs, 18 bytes

\"Ẇƛ\"=[&›¥₂[\'|\`

Try it Online!

\"Ẇ                # Split on ", keeping delimiter
   ƛ               # Map...
    \"=[           # If a "
        &›         # Increment the register
          ¥₂[      # If even...
             \'    # Single quote, 
               |\` # Else backtick. 
\$\endgroup\$
0
\$\begingroup\$

Lua, 36 bytes

print((...):gsub('"(.-)"',"``%1''"))

Try it online!

Wow, only two chars longer than js solution.

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

Perl 5 -p0, 19 bytes

s/"(.*?)"/``$1''/gs

Try it online!

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

Java 8, 40 bytes

s->s.replaceAll("\"([^\"]+)\"","``$1''")

Try it online.

Explanation:

s->                             // Method with String as both parameter and return-type
  s.replaceAll("\"([^\"]+)\"",  //  Replace all these matches,
               "``$1''")        //  with this replacement 

Regex explanation:

 "([^"]+)"                      // MATCH:
 "                             "//  A literal "
   [^"]+                       "//  Followed by 1 or more non-" characters
  (     )                       //  (captured in capture group 1)
         "                     "//  Followed by a literal " again

``$1''                          // REPLACEMENT:
``                              //  Literal ``
  $1                            //  Followed by the match of capture group 1
    ''                          //  Followed by a literal ''
\$\endgroup\$
0
\$\begingroup\$

Wren, 91 bytes

Fn.new{|n|
var c=1
for(i in n.split("\"")[1..-1])System.write(((c=-~c)%2==0?"``":"''")+i)
}

Try it online!

Explanation

Fn.new{|n| // New anonymous function
var c=1    // Set the index counter as 1
for(i in n.split("\"")                                                 // For each over n splitted with quotes
                      [1..-1])                                         // Get rid of the first quote
                              System.write(                          ) // Output this to the console
                                           (
                                            (c=-~c)                    // Increment the counter
                                                   %2==0?"``"          // If that's divisible by 2, output a backquote
                                                             :"''"     // Otherwise, output a frontquote
                                                                  )+i  // Join the result with i
}
\$\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.