19
\$\begingroup\$

Background

In Haskell and many other functional languages, function application f(x) is simply written as f x. Also, this form of function application is left-associative, which means f x y z is ((f x) y) z, or ((f(x))(y))(z).

Haskell also has a binary operator called $. f $ x does function application just like f x, but it is right-associative, which means you can write f $ g $ h $ x to mean f(g(h(x))). If you used Haskell enough, you might have once wondered, "would it be nice if f x itself were right-associative?"

Now it's about time to see this in action. For the sake of simplicity, let's assume all the identifiers are single-character and omit the spaces entirely.

Challenge

Given a valid expression written using left-associative function application, convert it to the minimal equivalent expression where function application is right-associative. The result must not contain any unnecessary parentheses.

An expression is defined using the following grammar:

expr := [a-z] | "(" expr ")" | expr expr

To explain this in plain English, a valid expression is a lowercase English letter, another expression wrapped in a pair of parens, or multiple expressions concatenated.

I/O can be done as a string, a list of chars, or a list of codepoints. The input is guaranteed to have minimal number of parens under left-associative system.

Standard rules apply. The shortest code in bytes wins.

Test cases

input -> output
---------------
foo -> (fo)o
b(ar) -> bar
q(uu)x -> (quu)x
abcde -> (((ab)c)d)e
f(g(hx)) -> fghx
g(fx)(hy) -> (gfx)hy
\$\endgroup\$
1
  • \$\begingroup\$ I've never once wondered that :) f . g . h $ x. \$\endgroup\$
    – chepner
    Jul 23 at 11:51
8
\$\begingroup\$

JavaScript, 71 bytes

Saved 2 bytes by Arnauld.

f=(e,l='',r=e.shift())=>(r=r>{}?r:r<f&&f(e))?f(e,l[1]?`(${l})`+r:l+r):l

Try it online!

  • l, r are two operand
\$\endgroup\$
2
  • \$\begingroup\$ I think you can use r<f instead of r<')'. \$\endgroup\$
    – Arnauld
    Jul 23 at 9:12
  • \$\begingroup\$ @Arnauld It works. \$\endgroup\$
    – tsh
    Jul 23 at 9:16
6
\$\begingroup\$

Perl 5 -p, 73 bytes

1while$e='(\w|\((?1)*\))',s/$e$e(?=$e)/($&)/;1while s/\(($e*)\)(?!$e)/$1/

Try it online!

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

Jelly, 60 bytes

;Ṫ$FL$¡1ĿØ(jƊ¹ŒḊ?€
=þØ(Ä_Ż}ỊṖʋ/aSƲœp⁸;2ĿW$}¥2/Ẏ3œṖW;¥2/ẎƲÐLÇ

Try it online!

A full program taking a string argument and printing the result to STDOUT. Uses recursion in both links, but in both cases replacing 1Ŀ or 2Ŀ with ß fails to work.

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

Retina 0.8.2, 94 bytes

+1`((\w|(\()|(?<-3>\)))+?(?(3)^)){2}(?!\))
($&)
+`\(((\w|(\()|(?<-3>\)))+)\)(?(3)^)(?=\)|$)
$1

Try it online! Link includes test cases. Explanation:

+1`

Make the first possible substitution each time, looping until no more substitutions are possible. This means that in the case of abcde, only ab is surrounded the first time, then (ab)c the second time, et cetera.

((\w|(\()|(?<-3>\)))+?(?(3)^)){2}(?!\))
($&)

Put parentheses around any pair of expressions that does not already have one.

+`\(((\w|(\()|(?<-3>\)))+)\)(?(3)^)(?=\)|$)
$1

Remove any parentheses not needed under right association.

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

Charcoal, 53 bytes

F⁺(S¿⁼ι(⊞υ⟦⟧«F⁼ι)≔⪫⊟υωιF‹¹L§υ±¹⊞υ⟦⪫()⪫⊟υω⟧⊞§υ±¹ι»⪫⊟υω

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

F⁺(S

Loop over the input with an extra ( prefixed as this is golfier then setting up the stack manually.

¿⁼ι(⊞υ⟦⟧«

For each (, push a new empty list to the stack.

F⁼ι)

If the next character is a ), then...

≔⪫⊟υωι

the next term is actually the joined list at the top of the stack.

F‹¹L§υ±¹

If the list at the top of the stack already has two terms, then...

⊞υ⟦⪫()⪫⊟υω⟧

... replace it with a list of a () wrapped term.

⊞§υ±¹ι

Push the current term to the list at the top of the stack.

»⪫⊟υω

Join and output any remaining terms.

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