18
\$\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\$
  • \$\begingroup\$ What are left double quotes and right double quotes? \$\endgroup\$ – my pronoun is monicareinstate Aug 24 '19 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\$ – HighlyRadioactive Aug 24 '19 at 7:36
  • \$\begingroup\$ Can quotes be nested? \$\endgroup\$ – my pronoun is monicareinstate Aug 24 '19 at 7:38
  • \$\begingroup\$ @someone Nope. They can't. \$\endgroup\$ – HighlyRadioactive Aug 24 '19 at 7:39
  • 3
    \$\begingroup\$ @LegionMammal978 "Can quotes be nested?" ... "@someone Nope. They can't." \$\endgroup\$ – Jonathan Allan Aug 24 '19 at 22:56

27 Answers 27

18
\$\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.)

|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ A quoty language in a quoty challenge LOL \$\endgroup\$ – HighlyRadioactive Aug 27 '19 at 9:45
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!

|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ Why the hate for Japt?! :p \$\endgroup\$ – Shaggy Aug 24 '19 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!

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

Jelly, 15 13 bytes

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

Try it online!

Full program.

|improve this answer|||||
\$\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

|improve this answer|||||
\$\endgroup\$
  • \$\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\$ – Erik the Outgolfer Aug 24 '19 at 13:08
  • \$\begingroup\$ @EriktheOutgolfer Nice finds, thanks! \$\endgroup\$ – Jitse Aug 24 '19 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
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ It's too bad you can't use Q here :\ \$\endgroup\$ – Oliver Aug 26 '19 at 19:56
  • \$\begingroup\$ @Oliver, I can (and I originally did); I'd just need a , too. \$\endgroup\$ – Shaggy Aug 26 '19 at 20:07
  • \$\begingroup\$ I mean it's too bad you couldn't simply use Q in place of '" \$\endgroup\$ – Oliver Aug 26 '19 at 20:11
4
\$\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.

|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ Why not the simpler \def"#1"{``#1''}? (or \long\def if you expect a quote to cross a paragraph boundary) \$\endgroup\$ – Phelype Oleinik Aug 26 '19 at 10:11
  • 1
    \$\begingroup\$ For the obvious reason that I didn't think of that :-) \$\endgroup\$ – siracusa Aug 26 '19 at 19:47
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.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ I was waiting for a Charcoal solution. Nice! \$\endgroup\$ – HighlyRadioactive Aug 24 '19 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)
|improve this answer|||||
\$\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.

|improve this answer|||||
\$\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!

|improve this answer|||||
\$\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!

|improve this answer|||||
\$\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!

|improve this answer|||||
\$\endgroup\$
1
\$\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-;;::
|improve this answer|||||
\$\endgroup\$
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.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ -4 Bytes if you use inline flags instead of the flags argument: r'(?s)"(.*?)"' \$\endgroup\$ – Triggernometry Aug 27 '19 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. 
|improve this answer|||||
\$\endgroup\$
  • 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 '19 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\$ – GammaFunction Aug 25 '19 at 14:17
  • \$\begingroup\$ Nicely done, I am always glad to see a sed answer \$\endgroup\$ – user41805 Aug 25 '19 at 14:59
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.

|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ Ok, looks like I don't have to fix and undelete my answer. ;) \$\endgroup\$ – Kevin Cruijssen Aug 26 '19 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!

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ "\"" should be "''" (two apostrophes) \$\endgroup\$ – siracusa Aug 26 '19 at 3:23
  • \$\begingroup\$ @siracusa Thanks, I assumed since you can use " in tex you could use it here. \$\endgroup\$ – Ad Hoc Garf Hunter Aug 26 '19 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''.
|improve this answer|||||
\$\endgroup\$
0
\$\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!

|improve this answer|||||
\$\endgroup\$
0
\$\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''...
|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Lua, 36 bytes

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

Try it online!

Wow, only two chars longer than js solution.

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Perl 5 -p0, 19 bytes

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

Try it online!

|improve this answer|||||
\$\endgroup\$
0
\$\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(?)
|improve this answer|||||
\$\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 ''
|improve this answer|||||
\$\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
}
|improve this answer|||||
\$\endgroup\$
0
\$\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
|improve this answer|||||
\$\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.