# Rules

In this challenge, I'm going to redefine the definition of "quotes" a bit.

• Quotation marks (AKA quotes) are any identical characters used in pairs in various writing systems to set off direct speech, a quotation, or a phrase. The pair consists of an opening quotation mark and a closing quotation mark, which is the same character(case-sensitive).

• If there are quote-pairs overlapping each other,

• If a pair nesting another, both pairs are still valid.
• If a pair not nesting another, the first starting pair remains valid. The other is no longer considered as a pair.
• When counting quoted characters(length of a pair of quotes),

• The quotes themselves don't count.
• Each pair's length is counted independently. Overlapping doesn't affect another.

# Goal

Your goal is to print the total length of all valid quotes. This is code golf, therefore the code with the fewest bytes wins.

# Examples

Legend:
<foo>: Valid quotes
^    : Cannot be paired character

Input   : ABCDDCBA
A  (6): <BCDDCB>
B  (4):  <CDDC>
C  (2):   <DD>
D  (0):    <>
Output  : 12

Input   : ABCDABCD
A  (3): <BCD>
B  (0):  ^   ^
C  (0):   ^   ^
D  (0):    ^   ^
Output  : 3

Input   : AABBBBAAAABA
A  (0): <>    <><> ^
B  (0):   <><>    ^
Output  : 0

Input   : ABCDE
Output  : 0

Input   : Print the total length of all "quoted" characters
r (40):  <int the total length of all "quoted" cha>
n (14):    <t the total le>
t (15):     < >   <o>       <h of all "quo>
   (7):      ^   <total>      <of>   ^        ^
h  (0):        ^             ^                  ^
e  (8):         < total l>                 ^          ^
o  (0):            ^           ^         ^
a  (0):              ^            ^              ^ ^
l  (0):               ^ ^          <>
"  (0):                               ^      ^
c  (0):                                        ^    ^
Output  : 84

Input   : Peter Piper picked a peck of pickled peppers
P  (5): <eter >
e  (9):  <t>     ^      <d a p>           <d p>  ^
r  (0):     ^     ^
   (3):      ^     ^      <a>    <of>       ^
i  (5):        <per p>
p  (3):         <er >        ^       ^       ^ <>
c  (8):               <ked a pe>       ^
k  (7):                ^        < of pic>
d  (0):                  ^                 ^
Output  : 40

h (27): <ttps://www.youtube.com/watc>
t  (0):  <>            ^          ^
/  (0):       <>               ^
w (14):         <><.youtube.com/>         <4>
.  (7):            <youtube>
o  (0):              ^       ^
u  (1):               <t>
c  (0):                     ^      ^             ^
Q  (8):                                  <w4w9WgXc>
Output  : 57
• @NickKennedy I fixed the rules to be more like actual quotes. I think this is what you expected. Can you review this? Jun 19, 2019 at 9:24
• looks good! Thanks for listening to my feedback. Jun 20, 2019 at 21:29

# APL (Dyalog Unicode), 36 bytesSBCS

Full program. Prompts for input from stdin.

≢∊t⊣{t,←'(.)(.*?)\1'⎕S'\2'⊢⍵}⍣≡⍞⊣t←⍬

Try it online!

t←⍬ set up an accumulator t (for total)

⍞⊣ discard that in favour of string input from stdin (symbol: quote in console)

{}⍣≡ apply the following anonymous lambda until stable (fix-point; previous ≡ next)

⊢⍵ on the argument

…⎕S'\2' PCRE Search for the following, returning group 2 for each match:

(.) any character (we'll call this group 1)
(.*?) as few characters as possible (we'll call this group 2)
\1 the group 1 character

t,← update t by append that to t's current value

t⊣ discard that (the final list of no matches) in favour of t

count the number of characters in that

# JavaScript (ES6), 64 bytes

f=([c,...a],i=a.indexOf(c))=>c?(~i&&i+f(a.splice(0,i+1)))+f(a):0

Try it online!

### Commented

f = (                       // f is a recursive function taking either the input string
// or an array of characters, split into
[c, ...a],                // c = next character and a[] = all remaining characters
i = a.indexOf(c)          // i = index of the 1st occurrence of c in a[] (-1 if not found)
) =>                        //
c ?                       // if c is defined:
( ~i &&                 //   if i is not equal to -1:
i +                   //     add i to the final result
f(a.splice(0, i + 1)) //     remove the left part of a[] up to i (included) and
)                       //     do a recursive call on it
+ f(a)                  //   add the result of a recursive call on a[]
:                         // else:
0                       //   stop recursion

# Ruby, 49 bytes

Recursive solution. Find quote groups, count their lengths, and then recursively look for sub-group lengths and sum everything together.

f=->s{s.scan(/(.)(.*?)\1/).sum{|a,b|b.size+f[b]}}

Try it online!

# Brain-Flak, 100 bytes

({{<({}<>)<>(({<>(({}({})<>[({}<>)]))(){[{}()](<>)}{}}{}){(<>)})<>{}>{<>({}<<>({}<>)>)<>}<>[{}]}{}})

Try it online!

### Commented

# Loop over each character in input and sum iterations:
({{

# Evaluate matching quote search as zero
<

# Move opening "quote" to right stack
({}<>)<>

# Until match or end of search string found:
# Note that the character to search for is stored as the sum of the top two entries in the right stack.
(

({

<>((

# Character to search for
{}({})

# Subtract and move next character
<>[({}<>)]

# Push difference twice
))

# Add 1 to evaluation of this loop
()

# If no match, cancel out both 1 and pushed difference to evaluate iteration as zero (keep one copy of difference for next iteration)
# (compare to the standard "not" snippet, ((){[()](<{}>)}{}) )
# Then move to other stack
{[{}()](<>)}{}

# If a match was found, this will instead pop a single zero and leave a zero to terminate the loop, evaluating this iteration as 0+1=1.

# Push 1 if match found, 0 otherwise
}{})

# If match found, move to left stack and push 0 denote end of "quoted" area.
{(<>)}

# Push the same 1 or 0 as before
)

# Remove representation of opening "quote" searched for
# The closing quote is *not* removed if there is a match, but this is not a problem because it will never match anything.
<>{}

>

# Move searched text back to left stack, evaluating each iteration as either the 1 or 0 from before.
# This counts characters enclosed in "quotes" if a match is found, and evaluates as 0 otherwise.
{<>({}<<>({}<>)>)<>}

# Remove 0/1 from stack; if 1, cancel out the 1 added by the closing "quote"
<>[{}]

# Repeat until two consecutive zeroes show up, denoting the end of the stack.
# (Because closing quotes are not removed, it can be shown that all other zeroes are isolated on the stack.)
}{}})

œṡ¹¡ḢṖẈ;ß€ƲS

Try it online!

# JavaScript (Node.js), 6564 62 bytes

f=s=>(s=/(.)(.*?)\1(.*)/.exec(s))?f(s[3])+f(s=s[2])+s.length:0

Try it online!

Original approach (64 bytes):

f=(s,r=/(.)(.*?)\1/g,t=r.exec(s))=>t?f(t=t[2])+t.length+f(s,r):0

Try it online!

f=s=>                              // Main function:
(s=/(.)(.*?)\1(.*)/.exec(s))?     //  If a "quoted" segment can be found:
f(s[3])                          //   Return the recursive result outside this segment,
+f(s=s[2])                       //   plus the recursive result of this segment,
+s.length                        //   plus the length of this segment
:0                                //  If not: no quoted segment, return 0.

# Jelly, 17 bytes

œṡḢẈṖ$Ḣ+ɼṛƲ)Ẏ$F¿®

Try it online!

A full program that takes a single argument, the input string wrapped in a list, and returns the number of quotes characters as an integer.