24
\$\begingroup\$

Elixir is a programming language with a feature called the pipe operator, |>, similar to the pipe in Bash and other languages. It passes the result of an expression on the left as the first parameter of a given function on the right.

To clarify, here are some examples.

2 |> myFunction()

is equivalent to

myFunction(2)

Here, the expression 2 is passed as the first parameter of the function myFunction().

Now, consider how an expression with multiple pipes is evaluated. Multiple pipes are evaluated left to right, so all of these lines are equivalent:

other_function() |> new_function() |> baz() |> bar() |> foo()
new_function(other_function()) |> baz() |> bar() |> foo()
baz(new_function(other_function())) |> bar() |> foo()
bar(baz(new_function(other_function()))) |> foo()
foo(bar(baz(new_function(other_function()))))

Here, in each line the leftmost pipe is calculated, which takes the first expression and passes it to the second expression (which is a function).

Challenge

Your challenge will be to write a program or function which, when given an Elixir expression with one or more pipes, will return or output an equivalent expression with no pipes. In real Elixir code the functions may have multiple parameters but to keep this challenge simpler, you may assume all functions will take only one parameter.

Examples

Input -> Output
2 |> myFunction() -> myFunction(2)
otherfunction() |> newfunction() |> baz() |> bar() |> foo() -> foo(bar(baz(newfunction(otherfunction()))))

Rules

  • Function names will only contain ASCII letters and underscores, and end in ()
  • The leftmost expression will only contain alphanumeric ASCII, underscores, and parentheses
  • You may assume there is no whitespace in the input (the examples here have spaces for readability)
  • You may also assume there are spaces surrounding the pipe operators like in the examples, if you wish
  • All functions only take one parameter
  • Leading or trailing whitespace is allowed in output
  • Whitespace around parentheses is allowed in output
  • Any reasonable form of input/output is allowed
  • No standard loopholes
  • Shortest code in bytes for each language wins
asked Mar 30, 2021 at 14:36
\$\endgroup\$
10
  • \$\begingroup\$ Can we assume that numbers will only appear at the start, before the first pipe? \$\endgroup\$ Commented Mar 30, 2021 at 14:40
  • \$\begingroup\$ @ChartZBelatedly Yes. As the rules say, function names (i.e. all expressions after the first pipe) will only include ASCII letters and underscores, and end in (). \$\endgroup\$ Commented Mar 30, 2021 at 14:42
  • \$\begingroup\$ Is excess whitespace around the parentheses ok? \$\endgroup\$ Commented Mar 30, 2021 at 15:44
  • 1
    \$\begingroup\$ @JonathanAllan No, bar(baz(new_function(other_function()))) is not a function (for the purpose of this challenge). \$\endgroup\$ Commented Mar 30, 2021 at 19:21
  • 2
    \$\begingroup\$ @hakr14 That is not allowed. \$\endgroup\$ Commented Mar 30, 2021 at 21:09

27 Answers 27

12
\$\begingroup\$

J, (削除) 23 (削除ここまで) 22 bytes

(];/:')'=;)&|._2{.\cut

Try it online!

 cut split by space
 _2{.\ only odds
 |. reverse
 ;/:')'=; join and sort by equality with ')'
answered Mar 30, 2021 at 16:07
\$\endgroup\$
3
  • 2
    \$\begingroup\$ Technically this breaks the rules due to it not working with whitespace-less inputs. However this is an edge case I didn't think about, and my intention was to allow submissions to assume there are spaces around the pipe operators. Therefore I will retroactively change the rules to allow this. \$\endgroup\$ Commented Mar 30, 2021 at 16:15
  • \$\begingroup\$ I didn't read carefully at all, my bad. \$\endgroup\$ Commented Mar 30, 2021 at 16:21
  • 3
    \$\begingroup\$ Sorting the close parentheses to the right is clever. \$\endgroup\$ Commented Mar 30, 2021 at 16:31
9
\$\begingroup\$

Stax, 8 bytes

ßN¶e╣╨j,

Run and debug it

Explanation(unpacked)

.|>/kNas++
.|>/ split the string on "|>"
 k reduce the list by:
 N push the 2nd string with the last element popped, then push the last element
 a put the previous iteration on top of the stack
 s swap the bracket with the prev iteration
 ++ concatenate into one string
answered Mar 30, 2021 at 14:51
\$\endgroup\$
0
8
\$\begingroup\$

Excel VBA (Immediate Window), (削除) 85 (削除ここまで) 75 bytes

-10 bytes thanks to @TaylorScott

For Each s In Split([A1],"|>"):o=IIf(o="",s,Left(s,len(s)-1)+o+")"):Next:?o

Excel, (削除) 165 (削除ここまで) 154 bytes

-11 bytes rethought the Excel based on changes to VBA

=LET(x,FILTERXML("<a><b>"&SUBSTITUTE(A1,"|>","</b><b>")&"</b></a>","//b"),n,ROWS(x),a,n+1-SEQUENCE(n),CONCAT(INDEX(LEFT(x,LEN(x)-(a<n)),a),REPT(")",n-1)))

Spreadsheet

=LET( 'define variables
 return last parameter
 "<a><b>"&SUBSTITUTE(A1,"|>","</b><b>")&"</b></a>" 'Convert piped string to XML 
x,FILTERXML( ,"//b") 'x = XML converted to array
n,ROWS(x) 'n = # rows in x
a,n+1-SEQUENCE(n) 'a = n .. 1
CONCAT(INDEX(LEFT(x,LEN(x)-(a<n)),a),REPT(")",n-1)) 'final calculation
 INDEX( ,a) 'x in reverse order
 LEFT(x,LEN(x)-(a<n)) 'if not first element delete 
 rightmost char
 REPT(")",n-1) 'n-1 ")"
CONCAT( ) 'concatenate everything

Original

=LET(s,SUBSTITUTE(A7,")",""),x,FILTERXML("<a><b>"&SUBSTITUTE(s,"|>","</b><b>")&"</b></a>","//b"),n,ROWS(x),CONCAT(INDEX(x,n+1-SEQUENCE(n)),REPT(")",LEN(A7)-LEN(s))))
answered Mar 30, 2021 at 16:28
\$\endgroup\$
5
  • 3
    \$\begingroup\$ +1, You always make ultimate usage of Excel functions and teach us that VBA is no use \$\endgroup\$ Commented Mar 30, 2021 at 17:00
  • 2
    \$\begingroup\$ Thanks, @Wasif. I wouldn't say VBA is completely useless. However, the recent addition of the LET has allowed Excel to do a lot more without VBA. \$\endgroup\$ Commented Mar 30, 2021 at 19:55
  • \$\begingroup\$ Nice usage of Excel, I'm amazed @Axuary \$\endgroup\$ Commented Mar 31, 2021 at 21:21
  • \$\begingroup\$ You can get this down to 75 bytes by switching to For Each, dropping the intermediate variable a, and using string addition rather than concatentation - For Each s In Split([A1],"|>"):o=IIf(o="",s,Left(s,len(s)-1)+o+")"):Next:?o - I would also explicitly state that this answer depends upon the assumption of no whitespace; And you can make the VBA answer look a little bit better by adding syntax highlighting with the HTML tag <!-- language: lang-vb --> \$\endgroup\$ Commented Apr 2, 2021 at 17:05
  • \$\begingroup\$ And you should also probably change the title of your response to specify that this is and Excel VBA answer, rather than a generic VBA answer \$\endgroup\$ Commented Apr 2, 2021 at 17:05
7
\$\begingroup\$

Jelly, (削除) 11 (削除ここまで) 9 bytes

Ḳm2ɓṪṭ;μ/

Try it online!

-2 bytes thanks to Jonathan Allan!

The |> must be surrounded by spaces

How it works

Ḳm2ɓṪṭ;μ/ - Main link. Takes a string S on the left
Ḳ - Split S on spaces
 m2 - Take every second element, ignoring the "|>" elements
 ɓ μ - Create a new dyadic chain f(a, b):
 Ṫ - Remove the trailing ")" from a and yield it
 ; - Concatenate the modified a and b
 ṭ - Tack the ")" to the end
 / - Reduce the split S by this. The ɓ in the chain tells
 the quick to reduce from the left with arguments reversed
answered Mar 30, 2021 at 14:42
\$\endgroup\$
0
7
\$\begingroup\$

SNOBOL4 (CSNOBOL4), (削除) 105 (削除ここまで) (削除) 98 (削除ここまで) (削除) 87 (削除ここまで) 78 bytes

	I =INPUT
S	I ARB . L '|>' ARB . F ')' REM . R =F L ')' R	:S(S)
	OUTPUT =I
END

Try it online!

Thanks to Razetime for -2 bytes.

Explanation:

	I =INPUT	;* read input, assign to I
S			;* label S
	I [lhs] = [rhs]	;* replace the part of I matching the following pattern:	
	ARB . L '|>'	;* something followed by '|>' (assign to L)
	ARB . F ')'	;* followed by something followed by a ')' (assign to F)
	REM . R		;* and the rest of the string (assign to R)
			;* with:
	F L ')' R	;* F, L, ')', and R concatenated together
		:S(S)	;* on SUCCESS (a match was found), goto S
	OUTPUT =I	;* on FAILURE, proceed to output and end the program
END
answered Mar 30, 2021 at 14:50
\$\endgroup\$
0
5
\$\begingroup\$

Elixir, 64 bytes

&Macro.to_string Macro.expand Code.string_to_quoted!(&1),__ENV__

Try it online!

Well, this looks a bit longish for a solution relying on built-in functionality, but I guess we need a "reference" implementation with Elixir doing it itself.

answered Mar 30, 2021 at 16:48
\$\endgroup\$
3
  • \$\begingroup\$ Alas Elixir function names tend to be very long compared to other languages since they're all prefixed with Something.. \$\endgroup\$ Commented Mar 30, 2021 at 20:49
  • \$\begingroup\$ @79037662 I guess that's why we don't see Elixir golfs very often. \$\endgroup\$ Commented Mar 31, 2021 at 7:42
  • 1
    \$\begingroup\$ That, and it's simply not a very popular language, outside of golfing. \$\endgroup\$ Commented Mar 31, 2021 at 13:10
5
\$\begingroup\$

R, (削除) 94 (削除ここまで) (削除) 92 (削除ここまで) 86 bytes

Edit: -2 bytes thanks to Giuseppe

function(s,t=el(strsplit(s,"[)]?(.>|$)")))Reduce(paste,c(rev(t),")"[+grepl("[(]",t)]))

Try it online!

answered Mar 30, 2021 at 17:10
\$\endgroup\$
4
  • \$\begingroup\$ "[)]?(.>|$)" instead? Assuming > only ever appears in pipes... \$\endgroup\$ Commented Mar 30, 2021 at 17:34
  • \$\begingroup\$ @Giuseppe It is true, by the challenge specifications, that | and > characters only appear in the pipe operators. \$\endgroup\$ Commented Mar 30, 2021 at 18:03
  • 1
    \$\begingroup\$ @79037662 that's the second time I've missed something in the spec, I think I need to go back to the first grade and learn how to read again. \$\endgroup\$ Commented Mar 30, 2021 at 18:06
  • 1
    \$\begingroup\$ @Giuseppe - Thanks! I missed that, too. See you back in school! \$\endgroup\$ Commented Mar 30, 2021 at 20:51
5
\$\begingroup\$

Retina 0.8.2, (削除) 30 (削除ここまで) (削除) 23 (削除ここまで) 22 bytes

+`^(.+?).>(.+?\()
2ドル1ドル

Try it online! Link includes test cases. Edit: Saved (削除) 7 (削除ここまで) 8 bytes thanks to @tsh. Explanation:

+`

Repeat until all pipes have been processed.

+`^(.+?).>(.+?\()

Match the first two terms up to the second term's opening bracket.

2ドル1ドル

Move the first term into the second term's argument.

answered Mar 30, 2021 at 19:45
\$\endgroup\$
4
  • \$\begingroup\$ +`(.*?).>(.*?\()(.*); Also, is there any flags to make it replace it only first occurrence every time? (So (.*) and 3ドル may be removed) \$\endgroup\$ Commented Mar 31, 2021 at 2:29
  • \$\begingroup\$ @tsh Nothing better than my existing ^ to anchor the match at the start of the string... \$\endgroup\$ Commented Mar 31, 2021 at 9:00
  • \$\begingroup\$ So maybe +`^(.*?).>(.*?\() -> 2ドル1ドル? \$\endgroup\$ Commented Mar 31, 2021 at 9:13
  • \$\begingroup\$ @tsh Ah yes, I was overthinking the removal of 3ドル and overlooked the removal of the ). \$\endgroup\$ Commented Mar 31, 2021 at 9:27
4
\$\begingroup\$

JavaScript (Node.js), 60 bytes

s=>s.match(/\w+\(?/g).reverse().join``+s.match(/\)/g).join``

Try it online!

This would fail if there were no pipes (not possible according to challenge rules) but here's an alternative version which can also handle that:

JavaScript (Node.js), 61 bytes

s=>(f=a=>a[1]?a.pop().slice(0,-1)+f(a)+')':a[0])(s.split`|>`)

Try it online!

answered Mar 30, 2021 at 15:09
\$\endgroup\$
4
\$\begingroup\$

Charcoal, 20 bytes

≔⪪S|>θ⭆⮌θ...ι⊖Lι⭆θ✂ι±1

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

≔⪪S|>θ

Split the input on |>.

⭆⮌θ...ι⊖Lι

Print the strings in reverse order without their last character.

⭆θ✂ι±1

Print the last characters of the strings. This means that the first term gets reunited, while the remaining terms have their brackets moved to the end.

answered Mar 30, 2021 at 20:05
\$\endgroup\$
4
\$\begingroup\$

Python 2, 54 bytes

lambda s:reduce(lambda r,x:x[:-1]+r+')',s.split('|>'))

Try it online!

For each function going to left to right, insert the string r we have so far between the parens of the function x.

string |> new_function() = new_function(string)

This is done by removing the last character (a close paren), appending the string, then adding back the close paren. Because reduce starts the accumulator at the first element by default, we don't need any special handling if it's not a function.

This is longer in Python 3, which lacks reduce but can use a starred assignment to extract the initial value.

Python 3, 59 bytes

r,*l=input().split('|>')
for x in l:r=x[:-1]+r+')'
print(r)

Try it online!

Alternatively:

Python 3, 59 bytes

r=''
for x in input().split('|>'):r=x[:-1]+r+x[-1]
print(r)

Try it online!

answered Mar 31, 2021 at 8:30
\$\endgroup\$
3
\$\begingroup\$

Zsh, 41 bytes

for a (${(s:|>:)1})x=${a//\()/($x)}
<<<$x

Try it online!

  • ${1} - take the input
  • (s:|>:) - split on |>
  • for a () - for each element:
    • ${a} - take the element
    • /// - replace:
      • \() - empty parentheses
      • ($x) - with the current value of $x, in more parentheses
    • x= and assign that to $x (it starts as an empty string by default)
  • <<<$x - print $x
answered Mar 30, 2021 at 15:58
\$\endgroup\$
3
\$\begingroup\$

Jelly, 9 bytes

Port of FrownyFrog's clever J answer!

Ḳm2ṚF=Þ")

A monadic Link accepting and yielding a list of characters (with the |> surrounded by a space on each side like the examples).

Try it online!

How?

Ḳm2ṚF=Þ") - Link: list of characters, S
Ḳ - split at spaces
 m2 - modulo-2 slice [1st, 3rd, 5th, ...]
 Ṛ - reverse
 F - flatten
 Þ - sort by:
 = ") - equals ')'?
answered Mar 30, 2021 at 19:13
\$\endgroup\$
3
\$\begingroup\$

C (gcc), 90 bytes

f(s,l,t)char*s;{for(t=0;--l&&s[l-1]-62;t++);s=printf("%.*s",t+!l,s+l)-t||f(")",f(s,l-2));}

Try it online!

Expects no spacing.

answered Mar 31, 2021 at 5:18
\$\endgroup\$
3
\$\begingroup\$

V (vim), 11 bytes

òf|xxd0f(pò

Try it online!

ò...ò repeats the commands until the first error, the rest are normal Vim commands.

answered Mar 31, 2021 at 17:48
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 13 bytes

„|>¡Å» ̈ì')«}θ

Try it online! The annoying thing here is only reduces by the first command after it, not a } or ]-terminated function. And macros don't exist, so... ̄\_(ツ)_/ ̄

„|>¡Å» ̈ì')«}θ # full program
 θ # last element of...
 Å» # cumulatively reduced...
 # implicit input...
 ¡ # split by...
„|> # literal...
 » # to the right by...
 ') # literal...
 « # concatenated to...
 ̈ # all characters of...
 # (implicit) second element in current reduction step...
 ̈ # excluding the last...
 ì # prepended to...
 # (implicit) first element in current reduction step
 } # end cumulative reduce
 # implicit output

') can also be , , or , } can also be ], and θ (only the one at the end) can be ¤ with no change in functionality.

answered Mar 30, 2021 at 16:03
\$\endgroup\$
0
2
\$\begingroup\$

Java, (削除) 103 (削除ここまで) (削除) 84 (削除ここまで) (削除) 80 (削除ここまで) 77 bytes

s->{var p="";for(var c:s.split("\\|>"))p=c.replace("()","("+p+")");return p;}

Saved 19 bytes thanks to 79037662.

Saved 4 bytes thanks to pxeger.

Try it online!

A positive lookahead can be used for a solution of the same length.

s->{var p="";for(var c:s.split("\\|>"))p=c.replaceAll("(?=\\))",p);return p;}

Try it online!

answered Mar 30, 2021 at 15:06
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Save some bytes with a for-each loop: tio.run/… \$\endgroup\$ Commented Mar 30, 2021 at 15:26
  • \$\begingroup\$ @79037662 Good idea. \$\endgroup\$ Commented Mar 30, 2021 at 15:30
  • 1
    \$\begingroup\$ -4 Try it online! \$\endgroup\$ Commented Mar 30, 2021 at 15:31
2
\$\begingroup\$

JavaScript (Node.js), 49 bytes

f=a=>a.replace(/(.*).>(.*)./,(_,x,y)=>y+f(x)+')')

Try it online!

Only works if no extra spaces are there.


JavaScript (Node.js), 50 bytes

a=>a.split`|>`.reduce((p,q)=>q.replace('(','('+p))

Try it online!

This works if the input does not contais "$" character. Otherwise, '('+ need to be replaced by x=>x+ with +1 byte cost.

answered Mar 31, 2021 at 2:10
\$\endgroup\$
3
  • \$\begingroup\$ Indeed, the input will not contain the $ character. \$\endgroup\$ Commented Mar 31, 2021 at 2:37
  • \$\begingroup\$ And what exactly happens if $ is in fact there? \$\endgroup\$ Commented Mar 31, 2021 at 20:27
  • \$\begingroup\$ @RomanOdaisky $$ will become a single $, and $& will become a (, \$\endgroup\$ Commented Apr 2, 2021 at 6:58
2
\$\begingroup\$

PowerShell Core, 81 bytes

-join($t=$args|% Sp* "|>"|% *m ')')[($l=$t.Count)..0]+")"*($l-!($t[0]|% e*h '('))

Try it online!

Thanks to @Julian!

PowerShell, 108 bytes

param($s)$n=$s.split("|>");$k=(($n|%{$n[--$q]})|%{$_-replace"\)$"})-join"";$k+")"*($k-replace"[^\(]").length

Try it online!

  • Take a string
  • Split it by |>
  • Save ^ to an array
  • Reverse the array
  • Loop on each element
  • Remove trailing )
  • Join array
  • Append number of ( in the joined string amount )
  • Print and bye bye!
answered Mar 30, 2021 at 16:47
\$\endgroup\$
1
  • 2
    \$\begingroup\$ 81 bytes? \$\endgroup\$ Commented Mar 31, 2021 at 4:01
2
\$\begingroup\$

Red, 85 bytes

func[s][t: take s: split s"|>"forall s[t: rejoin[replace s/1"()"""mold to-paren t]]t]

Try it online!

answered Mar 31, 2021 at 10:28
\$\endgroup\$
2
\$\begingroup\$

PowerShell Core, (削除) 67 (削除ここまで) (削除) 57 (削除ここまで) (削除) 45 (削除ここまで) 44 bytes

$args-split'.>'|%{$r=$_|% rep* '(' "($r"}
$r

Try it online!

The rep* is the shortcut for the replace method.

answered Mar 31, 2021 at 20:18
\$\endgroup\$
2
\$\begingroup\$

Python 3, (削除) 84 (削除ここまで) 79 bytes

import re;r=re.findall;i=input()
print(''.join(r('[\w(]+',i)[::-1]+r('\)*',i)))

Try it online!

  • Seems to be a complete solution: works whether there are spaces around the functions/constants/pipes or not, works whether first position contains constant or function.
  • Doesn't technically look for pipes, so you could replace |> with |< and it would return the same output. Could add a positive lookforward to the regex but that would eat another ~10 bytes and the contest didn't specify.
  • Pays a (削除) 27-byte (削除ここまで) 22-byte penalty just for importing one regex method. Thanks Python.
  • Edited for small improvement.
answered Apr 1, 2021 at 0:13
\$\endgroup\$
2
  • \$\begingroup\$ Welcome to the site. You can use from re import*;r=findall for a shorter input. I count 2 bytes saved this way. \$\endgroup\$ Commented Apr 1, 2021 at 2:13
  • \$\begingroup\$ Welcome to code golf stack exchange. You can save a few bytes by using a lambda function: tio.run/… \$\endgroup\$ Commented Apr 1, 2021 at 3:12
1
\$\begingroup\$

Japt, (削除) 15 (削除ここまで) 12 bytes

q"|>" rÏiXJÉ

Try it

  • saved 3 by assuming no whitespaces as suggested by OP @79037662
 q"|>" - split on pipe
 r - reduce by
 ÏiXJÉ - inserting before )
answered Mar 30, 2021 at 16:33
\$\endgroup\$
1
  • \$\begingroup\$ The rules say you can assume the input has no whitespace, so you don't need to remove spaces. \$\endgroup\$ Commented Mar 30, 2021 at 18:04
1
\$\begingroup\$

Python 3, 70 bytes

*a,b=input().split("|>")[::-1]
print(*[f[:-1]for f in a],b,")"*len(a))

The program first splits the input into a list using the pipe operator, "|>", as the separator. Using multiple assignment, b is set equal to the last element of the list (previously the first element prior to being reversed). b contains a string of the first element in the pipe, which may or may not be a function. The rest of the list is assigned to a. All of the elements of a are strings of functions. Next, the program outputs all the elements of a with ) removed from each, b, and ")"*len(a).

Try it online!

If we're allowed to require that only the first item in the pipe has a space after it, but none of others, we can save 1 byte.

69 bytes

a=input().split("|>")[::-1]
print(*[f[:-1]for f in a],")"*(len(a)-1))

Try it online!

answered Mar 30, 2021 at 18:10
\$\endgroup\$
4
  • \$\begingroup\$ Neat strategy, but I think your b variable isn't doing anything for -5 bytes \$\endgroup\$ Commented Mar 30, 2021 at 19:56
  • \$\begingroup\$ @kops Doesn't work for the first test case 2|>myFunction(). \$\endgroup\$ Commented Mar 30, 2021 at 20:00
  • \$\begingroup\$ @Neil shoot, thanks I missed that case in my answer as well... will have to go fix \$\endgroup\$ Commented Mar 30, 2021 at 20:03
  • \$\begingroup\$ @kops You're mostly right. If the first item in the pipe is a function the b variable isn't needed, but if it is a variable or number the last character of the variable will be removed and there will be an extra ) at the end. But I still think you're right about the b variable being unnecessary. I've been experimenting with it and I've found this 81 byte solution. \$\endgroup\$ Commented Mar 30, 2021 at 20:27
1
\$\begingroup\$

Pyth, 13 bytes

.UXtlZZbcQ"|>

Test suite


Explanation:

.U cQ"|> | Reduce the input split at "|>" on the following lambda, where b is the current value and Z is the next item:
 XtlZZb | Insert b into Z at index len(Z)-1
answered Mar 30, 2021 at 20:43
\$\endgroup\$
1
\$\begingroup\$

Wolfram Language (Mathematica), 42 bytes

#//.{a__,"|",_,b__,"(",c___}:>{b,"(",a,c}&

Try it online!

Takes and returns a list of characters. Requires no spacing.

answered Mar 31, 2021 at 3:52
\$\endgroup\$
1
\$\begingroup\$

Twue, 123 bytes

@::>*
^()::=()!
^_ ::=_ !
^_::=_^
!()::=!
!_::=_!
$!::=$;
 |> $;::= $#(;%
##_::~_
 $#::= $##
 $::=$
_$::=$#_
%::~)
::=
^ @$

Try it on the website!

animation of the code running successfully


Twue is a spiritual successor to Thue I made. I initially tried answering this challenge in Thue, and had to manually describe moving each character one byte to the left, individually, so the byte count came out to ~1kb. Then, I realize I didn't properly handle constants and abandoned the code, not wanting to rewrite that mess from scratch. Enter Twue, which allows wildcards to be used (_) to refer to generic characters. Furthermore, it removes the random rule selection from the language, and creates a better standard for input/output.

The language is still a bit of a work in progress, but most of the bugs have been ironed out, and most of the spec has been implemented.

Explanation

@::>*

This replaces all @ in the workspace with a line of input. Basically: readline. For an input of 1234 |> foo() |> bar(), this populates the workspace with:

^ 1234 |> foo() |> bar()$

^ and $ are characters we'll be using as pointers, of sorts, for iterating forward and backward through the code.

^()::=()!
^_ ::=_ !
^_::=_^

This section moves the ^ pointer after the first expression, which may or may not contain parentheses. We want to preserve these. This inserts ! after the first expression, and we are ready to parse.

!()::=!
!_::=_!
$!::=$;!

Now, for every expression afterwards, we want to strip the () from it. So, we move ! character by character through the input, removing () in front of it as we go. After these steps, the input will look like this:

 1234 |> foo |> bar$;!

Now we are ready for the second stage of parsing. We will use ! later in the final stages of printing. Now, we have two pointers, $ and ;, which will define the range we're operating on.

 |> $;::= $#(;%
##_::~_
 $#::= $##
 $::=$
_$::=$#_

_$::=$#_ simply moves every character in front of a $ after it, prepending a # to it. This signifies we want to print that character. We repeat this until the $ pointer is at the leftmost part of the word, after a space. Since we are at the beginning of the word, we start printing the characters after $#, by first duplicating the #, and printing the character after #__. This allows us to only print when we want to—if we didn't duplicate, we'd print the strings in reverse, or lose track of the $ pointer. If we find the string |> $;, we've printed all the characters we could, and we still have more things to parse. We remove the |> and append a %, signifying we need to print a corresponding closing parenthesis.

These replacements repeat until they can't anymore.

%::~)

If there are no other substitutions we can possibly make, we simply take each % and output a corresponding ).

answered Apr 3, 2021 at 23:52
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.