| Bytes | Lang | Time | Link |
|---|---|---|---|
| 023 | Pip | 210630T200842Z | DLosc |
| 020 | ><> | 210831T204401Z | tjjfvi |
| 073 | Python 3.8 prerelease | 210831T095121Z | Jitse |
| 030 | ><> | 210828T234833Z | Jo King |
| 121 | ><> | 210704T074315Z | cnamejj |
| 024 | Pip | 210630T230501Z | DLosc |
| 196 | Nim + npeg | 210630T212835Z | Adam |
| 044 | Ruby | 210205T094917Z | ovs |
| 143 | C gcc no builtins | 210205T183228Z | Conor O& |
| 015 | Jelly | 210206T150014Z | Jonathan |
| 098 | C gcc | 210205T131735Z | Noodle9 |
| 086 | Red | 210205T131100Z | Galen Iv |
| 022 | x8616 machine code | 210205T065727Z | user9915 |
| 052 | PCRE | 210206T013311Z | Neil |
| 032 | Perl 5 p | 210205T215340Z | Xcali |
| 027 | APL Dyalog Unicode | 210205T184209Z | user |
| 027 | sed r 4.2.2 | 210205T191948Z | Digital |
| 067 | JavaScript ES6 | 210205T015716Z | Arnauld |
| 061 | Julia | 210205T153415Z | MarcMush |
| 076 | Java JDK | 210205T114932Z | Olivier |
| 027 | Charcoal | 210205T114620Z | Neil |
| 020 | 05AB1E | 210205T080005Z | Kevin Cr |
| 074 | Python 3 | 210205T075112Z | Noodle9 |
| 054 | Wolfram Language Mathematica | 210205T082622Z | att |
| 050 | JavaScript Node.js | 210205T020337Z | tsh |
| 025 | Pyth | 210205T042425Z | hakr14 |
| 030 | J | 210205T035351Z | Jonah |
| 023 | Stax | 210205T035340Z | Razetime |
| 017 | Jelly | 210205T031515Z | Unrelate |
| 022 | Retina 0.8.2 | 210205T025827Z | tsh |
| 023 | APL Dyalog Extended | 210205T020536Z | rak1507 |
Pip, 27 23 bytes
VaR^"<>"''._R'("(G@A B"
Takes input with outer parentheses. Attempt This Online! Or, verify all test cases.
Explanation
Translates the input into a Pip expression and evaluates it. In Pip, function call syntax is (f a b c), so all we have to do is quote the angle brackets and insert an appropriate function inside each opening parenthesis:
VaR^"<>"''._R'("(G@A B"
a Command-line input
R Replace
^"<>" either of < and > with
''._ itself with a single quote prepended
R Replace
'( open parenthesis with
"( " open parenthesis followed by a string representation
of this function:
A ASCII code of
B the second argument
(60 for < or 62 for >)
@ Use that as a (cyclical) index into
G the full argument list
(which contains 3 items, so we get either index 0
for < or index 2 for >)
V Evaluate as Pip code
><>, 22 20 bytes
-2 bytes thanks to Jo King
i:2%?\
?$~$~\0(?o$6%
Try it online! or verify all test cases
Explanation
i:2%?\ main loop:
i Read a character from the input and push it onto the stack
:2%? If it's not a multiple of two (")" or EOF),
\ Swap to the branch
IP wraps around, repeat
?$~$~\0(?o$6% branch:
\ Entrance
0(? If the character is less than 0 (EOF),
o$ Output the result and error
Otherwise,
$ Check the middle value
? 6% If it's not a multiple of 6 (">"), [the IP wraps around]
$ $ Reverse the other two values
~ Pop the right value
$~ Remove the "(" from the stack
\ Return to the main loop
Python 3.8 (pre-release), 73 bytes
f=lambda s:~(q:=s.rfind('('))and f(s[:q]+s[q+ord(s[q+2])-59]+s[q+5:])or s
Python 3, 77 bytes
def f(s):q=s.rfind('(');return~q and f(s[:q]+s[q+ord(s[q+2])-59]+s[q+5:])or s
Solution without regex. Requires the whole input be parenthesized.
-1 byte thanks to ovs
><>, 36 31 30 bytes
>i:6%0$.
v
v~0[
v0(?o$6%?$~]
Try it online! Verification of test cases
Takes input surrounded by parenthesis, and outputs a single character before terminating with an error.
Explanation:
>i: Take input and make a copy
6% Map the possible codepoints through modulo: EOF,<,>,(,) => 5,0,2,4,5
0$. Jump to that line
> Line 0 ('<'): This just jumps back to the first line again
v Line 2 ('>'): Does nothing and goes back to the first line again
v~0[ Line 4 ('('): Pop the extra copy of input and create a new stack
0(? Line 5 (')'): If the input is EOF (-1)
o Output the top of stack (and error later)
$6% Otherwise, check what the middle character is
?$ If it is a >, swap the other two
v ~] Discard the right character and leave the other other one on top of the next stack
o~ Line 1 (EOF): If there is no more input, pop the copy and output the remaining character
><>, 121 bytes
0&v
>o ;
^? <=1l~<;o~$?=">"$
<<v<<<&0 ~&~$?=">"$<
~]v&0[0~ < >
>>>i:0(?^ :>>>v
<< v<<<<<^? ="("<
+&^>>:")"=?^&:&2= ?^&1
This code takes advantage of the ><> functionality where a new stack/register can be created, code can operate on that new stack, then once that stack is closed, the results are merged back into the lower level stack.
It reads one character (codepoint really) at a time creating new stacks whenever it hits a ( and closing them when a ) is encountered.
The other logic use is a simple state machine, based on the contents of the register associated with the current stack.
When the value of the register is 0 the char just read is the left hand side of the statement, a value of 1 means it's the operator (< or >), and a value of 2 means we have the right hand side.
Anytime the state is 2, the code can resolve the 3 character on the stack (RHS, OP, LHS) to get an answer for that operation.
When the input is exhausted, we'll be back at the base stack with either 1 or 3 entries on the stack. If there are 3 entries on the stack, the code does one final operation to resolve the stack, then the sole entry on the stack is printed as a character.
The code is broken up to save characters, but I'm going to explain it using the original code. The only difference is that direction shifts, extraneous spaces and directional indicators have been removed to make it easier to see what's happening. Well, unless I goofed when formatting it...
# initialization
0&v # Set the register (state) to 0, call input loop
[0]
# [0] loop to read input and process each char
[1] [2] [3] [4]
>>>i:0(?^:"("=?^:")"=?^&:&2=?^&1+&
.. i # Read next char/codepoint
:0( # Check it codepoint < 0
?^ # If true, all input done call [1]
:"("= # Compare char to "("
?^ # If true, call [2] to open new stack
:")"= # Compare char to ")"
?^ # If true, call [3] to close stack
&:& # Load and resave the register
2= # Compare state to 2 (RHS,OP,LHS)
?^ # If true, call [4] to pick answer
&1+& # Increment the register (state)
# [1] code to handle EOF
[5]
>~1l=?^$"<"=?$~o;
.. ~ # Delete top of stack, clean-up
1l= # Compare stack size to 1
?^ # If true, call [5] to print/exit
$ # Flip top two stack entrys, pulls OP to top
">"= # Compare OP to ">"
?$ # If true, flip top two stack entries
~ # Delete top of stack (the choice we don't want)
o; # Print top of stack as char, then exit
# [5] called on EOF if the stack has only 1 entry
>o;
.. o; # Print top of stack as char, then exit
# [2] code to handle "(", stack a new stack
>~0[0&
.. ~ # Delete top of stack, clean-up...
0[ # Open a new stack with 0 entries from the old one
0& # Set the register (state) to 0
# [3] code to handle ")", close the stack
>~]
.. ~] # Delete top of stack, close stack to merge down
# [4] code to resolve a stack with RHS,OP,LHS
>$">"=?$~&~0&
.. $ # Flip top two stack entrys, pulls OP to top
">"= # Compare OP to ">"
?$ # If true, flip top two stack entries
~ # Delete top of stack (the choice we don't want)
&~&0 # Set register (state) to 0
Pip, 24 bytes
L#aaR:`\((...)\)`B@A@>Ba
Explanation
This one is a regex replacement solution:
L#aaR:`\((...)\)`B@A@>Ba
a is command-line argument
L#a Do the following len(a) times:
aR: In a, replace (and assign back to a)
` ` this regex:
\( Literal open paren
(...) Three characters (captured in group 1)
\) Literal close paren
with the result of the following callback function:
@> All but the first character of
B capture group 1
A ASCII code of (the first character of) that string
B@ Use that value to index cyclically into group 1
a After the loop, output the value of a
The replacement works because the charcode of < is 60 and the charcode of > is 62. Using those values as modular 0-based indices into a three-character string gives the first character and the last character, respectively--exactly what we need.
Nim + npeg, 196 bytes
import npeg
let p=peg(t,s:seq[int]):
t<-o[3]:
let a=[s.pop,s.pop,s.pop];s.add a[a[1]*2]
o<-'('*t*')'|a
a<- >'<'| >'>':s.add int $1<">"
var
s= @[4]
m=p.match(stdin.readAll,s)
echo "><"[s[1]]
Using an actual parsing library, yay!
Ruby, 51 49 44 bytes
-1 byte thanks to Neil! (match any character . instead of the opening bracket \()
-4 bytes thanks to Dingus! (String#sub! returns nil if there was no match)
Outputs by modifying the input. This would be 43 bytes with tsh's regex.
->s{s.sub!(/.((.)<.|.>(.))\)/,'\2\3')&&redo}
Ruby -p, 40 39 38 bytes
-1 byte thanks to Sisyphus!
sub /.((.)<.|.>(.))\)/,'\2\3'while/../
C (gcc) (no builtins), 147 143 bytes
4 bytes saved thanks to ceilingcat!
i,m,c,q,w;f(char*s){for(i=m=w=0;c=s[i]%9;i++)if(c-1?c-4?w+=w-~c%3,++m==4:(q=i,m=w=0):0)for(s[q]=w-2&&w<9?62:60;q++<i;)s[q]=1;s=*s%3-1?*s:f(s);}
Function that takes a null-terminated char array as input, and returns a char (int).
Here's a visualization of how it works:
(((>>>)<<)(<(<><)<)((<<(<<<))>(>(><>)<)))
((>....<<)(<<....<)((<<<....)>(>>....<)))
(>........<........(<........><........))
(>........<........<....................)
>........................................
(In the code, it uses 0x01 instead of ., but due to the modulus, they're equivalent even in data representation.)
Essentially it scans the code looking for instances of (data), where data consists of substring of 3 characters, except '.' and '('. (4, in the code, since it tracks the ) as the 4th character.) The program keeps track of the start of this string (q) and a binary representation of the visited characters (w). If we consider '>' to be equivalent to the binary 1, and '<' the binary 0, we simply look at a table of what the results of the binary strings should be. As it turns out, for q=1,4,5,6, the answer is '<', and '>' otherwise. Thus, w-1&&w<5 is a sufficient determiner. (In fact, since we keep track of ) as part of this binary string, we have to consider that everything is doubled, and for no byte cost, we can modify this formula to obtain the w-2&&w<9.)
After we determine what the result should be, we replace the initial ( with the result, and all subsequent characters with .. Then, so long as the initial character of the string is (, we repeat our function. This allows us to skip moving the string around, which, in my head, should save bytes, but I haven't tested the alternative.
Started working on this before I saw the existing (much shorter) C answer. But I enjoyed this nonetheless.
Jelly, 15 bytes
O;1ị“/ṛ ɗḷ”vØ<
A monadic Link accepting a list of characters*, which yields a character.
* Uses the encased in parens option.
How?
Converts the input to Jelly code which will reduce the pair ['<', '>'] to produce the answer. Jelly ignores spaces and has a 1-indexed and modular index-into function, ị, so the Link starts by converting the input characters to their ordinal values and uses ị to form the code:
input character ordinal indexed into "/ṛ ɗḷ" meaning
( 40 (space) ignored
< 60 ḷ yield left argument
> 62 ṛ yield right argument
) 41 ɗ last three links as a dyadic function
(or reduce command) 1 / reduce by
So:
O;1ị“/ṛ ɗḷ”vØ< - Link: list of characters e.g. (<>>)
O - ordinals [40,60,62,62,41]
;1 - concatenate a one [40,60,62,62,41,1]
“/ṛ ɗḷ” - "/ṛ ɗḷ" "/ṛ ɗḷ"
ị - index into " ḷṛṛɗ/"
Ø< - "<>" "<>"
v - evaluate with input '>'
The example above evaluated:
ḷṛṛɗ/ - monadic chain (with left argument ['<', '>'])
/ - reduce (['<', '>']) by - i.e. f('<', '>'):
ɗ - last three links as a dyad - i.e. g('<', '>'):
ḷ - yield left = '<'
ṛ - yield right = '>'
ṛ - (ḷ) yield right (ṛ) = '>'
C (gcc), 117 \$\cdots\$ 101 98 bytes
Saved 10 bytes thanks to an idea from Davide!!!
Saved 3 bytes (and got below 100!) thanks to ceilingcat!!!
i;f(char*p){for(i=0;*p++-40||p[3]-41;++i);p[-1]=p[p[1]-62?0:2];bcopy(p+4,p,strlen(p));i&&f(p+~i);}
Takes an input string with enclosing parentheses and reduces it to either a left (<) or a right (>).
Explanation (before some golfs)
i;f(char*p){ // function taking a string parameter p
for(i=0;p[i++]-40||p[i+3]-41;); // loop until we find chars '(' and ')'
// separated by 3 characters.
// since our input is enclosed in
// parentheses we will always find one.
p[i-1]= // i has gone forward one but set the
// first of these characters - the '('
// to...
p[i+1]-62? // ...depending on whether the middle
// char is a '<' or a '>'...
p[i]: // ...the one before the middle if '<'
p[i+2]; // ...the one after the middle if '>'
memcpy(p+i,p+i+4,strlen(p)); // move the back end of the string forward
// over the other 4 chars.
// now a "(A<B)" is reduced to "A"
// and a "(A>B)" is reduced to "B"
~-i&& // if we didn't just reduce the start of p
f(p); // then recursively call f.
// otherwise p is reduced to the answer
// and we're done.
}
Red, 136 120 86 bytes
This version is courtesy @hiimboris (https://gitter.im/red/parse)!
func[s][r:["<"|">"]while[parse s[to change["("x: r["<"r |">"x: r]")"](x/1)to end]][]s]
x86-16 machine code, 31 26 22 bytes
Saved 5 bytes thanks to @Bubbler.
Saved 4 bytes thanks to @640KB.
0000:0000 AC 3C 29 74 03 50 EB 0A-5A 58 3C 3E 58 74 01 92 .<)t.P..ZX<>Xt..
0000:0010 58 52 E2 EC 58 C3 XR..X.
Callable function.
Expects SI = address of code, CX = length of code.
Expects the code to be enclosed in (...):
You may alternately accept the whole inputs encased in parens like
(><>)or(<(><>)>).
Returns the output at AL.
Disassembly:
LOOP: ; Main loop:
AC LODSB ; AX = [SI++]
3C29 CMP AL, ')' ; AX == ')'?
7403 JZ BRACE ; * If so, jump to 'BRACE'
PUSHSTH: ; Otherwise...
50 PUSH AX ; * Push AX onto stack
EB0A JMP END ; * Jump to 'END'
BRACE: ; If AX == ')'?
5A POP DX ; * pop TOS to DX
; * (So DX is now the rightmost angle brace)
58 POP AX ; * pop TOS to AX
; * (So AX is now the middle angle brace)
3C3E CMP AL,'>' ; * Compare current AL with '>' (result stored in PSW)
58 POP AX ; * AX = left argument
7401 JZ RAB ; * If prev. value of AL == '>', jump to 'RAB'
LAB: ; * Handle prev. value of AL == '<':
92 XCHG DX,AX ; * DX = left argument instead
RAB: ; Now, DX is the chosen value.
58 POP AX ; * Discard TOS (which is an excess '(')
52 PUSH DX ; * Push DX onto stack
END: ; Finally,
E2EC LOOP LOOP ; * Loop the above CX times
58 POP AX ; Pop TOS to AX
C3 RET ; Return to caller
PCRE, 52 bytes
(((<|>|\((?3){3}\))(?=(?>(?4))?>)(?3))?(\((?1))?)(.)
Try it online! Link includes Perl 5 test harness. Does not take outer parentheses (admittedly a version that takes outer parentheses would probably be shorter.) The desired result is captured in group 5. Explanation: Group 3 matches an operator. Group 2 matches two operators, but only if the second operator evaluates to >; a recursive atomic match is used to determine whether that is true. Group 4 then recurses if the current operator is an expression.
( Group 1 is:
( Group 2, which is:
( Group 3, which is either:
<|>| ... a literal `<` or `>` or...
\((?3){3}\) ... three recursive matches of group 3 inside parentheses;
)
(?= Followed by a lookahead to:
(?>(?4))? An optional atomic recursive match of group 4...
> ... which must be followed by a `>`;
)
(?3) Followed by another recursive match of group 3.
)? Group 2 is optional.
( Group 4, which is...
\( ... a literal `(`...
(?1) ... followed by a recursive match of group 1.
)? Group 4 is optional.
) End of group 1.
(.) Group 5 then captures the desired result.
Perl 5 -p, 32 bytes
s/\((.>(.)|(.)<.)\)/$2$3/g&&redo
Takes advantage of the spec allowing outside parentheses to be required.
APL (Dyalog Unicode), 27 bytes
'\((.>)?(.)(<.)?\)'⎕R'\2'⍣≡
This is longer than rak1507's answer, but I just wanted to use a different approach. Uses the same regex as everyone else.
JavaScript (ES6), 69 67 bytes
Saved 2 bytes thanks to @Neil
f=s=>s<(s=s.replace(/.?([<>]{3}).?/,(_,s)=>s[s[1]>'<'?2:0]))?f(s):s
Java (JDK), 76 bytes
s->{while(s.length()>1)s=s.replaceAll("\\((.>)?(.)(<.)?\\)","$2");return s;}
Credits
- -16 bytes thanks to Kevin Cruijssen by porting tsh's JavaScript answer's regex
Charcoal, 27 bytes
F⁻S(≡ι)«≔⊟υθ≡⊟υ>§≔υ±¹θ»⊞υιυ
Try it online! Link is to verbose version of code. Takes input wrapped in ()s. Explanation: Port of @2x-1's answer.
F⁻S(
Remove (s from the input and loop over the remaining characters.
≡ι)«
If the current character is a ) then...
≔⊟υθ
... pop the last character from the stack; and ...
≡⊟υ>
... if the (second) last character was a > then...
§≔υ±¹θ
... overwrite the (third) last character with the originally popped character.
»⊞υι
Otherwise push the current character to the stack.
υ
Print the final remaining character.
05AB1E, 20 bytes
Δ„<>3々(ÿ)¬¦¨ºĆ'>ª:
Takes the input wrapped in parenthesis in both programs, as is allowed.
Try it online or verify all test cases.
05AB1E (legacy), 20 bytes
'<∞©3ãε…(ÿ)}¬®Ã∞®«S:
Should have been 19 bytes by also using €…(ÿ), but apparently there is a bug in the legacy version, so we'll have to use ε…(ÿ)} (or '(ì')«) instead.
Try it online or verify all test cases.
Explanation:
Δ # Continue until it no longer changes, using the (implicit) input:
„<> # Push string "<>"
3ã # Create all possible triplets of these two characters:
# ["<<<","<<>","<><","<>>","><<","><>",">><",">>>"]
€ # Map over each string in the list
…(ÿ) # And wrap it in parenthesis
¬ # Get the first item (without popping the list): "(<<<)"
¦¨ # Remove its first/last characters: "<<<"
º # Mirror it: "<<<>>>"
Ć # Enclose; appending its own head: "<<<>>><"
'>ª '# Convert it to a list of characters, and append ">":
# ["<","<","<",">",">",">","<",">"]
: # Replace all ["(<<<)",...,"(>>>)"] with ["<",...,">"]
# (after the loop, the result is output implicitly)
'<∞ '# Push "<" and mirror it to "<>"
© # Store this string in variable `®` (without popping)
3ãε…(ÿ)}¬ # Same as above
®Ã # Only keep the characters that are also in `®`, removing the "()"
∞ # Mirror it: "<<<>>>"
®« # Append `®`: "<<<>>><>"
S # Convert it to a list of characters:
# ["<","<","<",">",">",">","<",">"]
: # Keep replacing all ["(<<<)",...,"(>>>)"] with ["<",...,">"]
# until there is nothing more to replace
# (after which the result is output implicitly)
Python 3, 98 74 bytes
Saved a whopping 24 bytes thanks to ovs!!!
import re
f=lambda p:p[1:]and f(re.sub('\(((.)<.|.>(.))\)',r'\2\3',p))or p
Takes an input string with enclosing in parentheses and returns whether it's left (<) or right (>).
Wolfram Language (Mathematica), 54 bytes
#//._[a___,"(",b_,c_,d_,")",e___]->a.If[c=="<",b,d].e&
Input a list of characters.
JavaScript (Node.js), 50 bytes
f=a=>a[1]?f(a.replace(/\((.>)?(.)(<.)?\)/,'$2')):a
Repeat apply regex replace until only 1 char left. The regex /\((.>)?(.)(<.)?\)/ get the calculate result as 2nd capturing group.
Save 1 byte, thanks to Arnauld
Pyth, 25 bytes
u:G."(\K%<åkí2""\\2
Uses the regex from tsh's Javascript answer. Replaces each match with its second matching group until a fixed point is found and printed.
J, 30 bytes
')/''<>'''".@,~'(',rplc&'<[>]'
Very similar to rak1507's APL answer, though I had the idea independently -- it's natural for J, though loses some elegance because of the quote escaping.
rplc&'<[>]'replace<>with[], which in J are the "left" and "right" identity operators, meaning they return the left or right argument.(Prepend a left paren to that result.')/''<>'''...,~Append)/'<>'to the previous result.- Now we have
( ~~input with [] instead of <>~~ )/'<>'. - Which is the same as:
'<' ( ~~input with [] instead of <>~~ ) '>' ".@Evaluate that string. From here, J trains and the definition of[and]do exactly what we want.
Stax, 23 bytes
ü▼2δ`▀ÆH╞íq`º╪ ≈♀ô☺ßX→ú
Uses the same regex as tsh's Javascript solution, and replaces till a fixed point is reached.
Explanation
"\((.>)?(.)(<.)?\)".$2RgiH
g generator:
i apply the following till invariant:
"\((.>)?(.)(<.)?\)".$2 regex replace with second capture group
H take last generated value
Jelly, 17 bytes
“)ɗ<ḷ>ṛ( ”y;”/vØ<
Same essential approach as rak1507's APL answer. Requires the input fully parenthesized.
“ ”y Replace
) ) with
ɗ last-three-links-as-dyad,
< < with
ḷ return-left-argument-and-ignore-right,
> > with
ṛ return-right-argument-and-ignore-left,
( and ( with a space which is essentially ignored.
;”/ Append the reduce quick,
v and evaluate the result as a monad with argument
Ø< "<>".
Retina 0.8.2, 22 bytes
{`\((.>)?(.)(<.)?\)
$2
Basically the port of my JavaScript answer in Retina. I just learnt how to write loop in past 10 minutes and got this.
{` loops the replace until nothing changed. The replacement calculate one step each time.
APL (Dyalog Extended), 30 23 bytes
(⍎'(⊣⊢)'['(<>'⍳⍞])/'<>'
'(<>'⍳⍞ take the input ⍞ and get the indices of '(<>'
this fills with the last index + 1 if not found, saving 1 char
'(⊣⊢)'[ stuff ] index into '(⊣⊢)', replacing <> with ⊣⊢, the left and right tack functions
⍎ evaluate this as a train
APL trains of the form (f g h) when applied to left and right arguments x and y produce (x f y) g (x h y)
This translates directly to this language
Replacing <> with ⊣ and ⊢ which do the same thing, the input becomes a valid function in APL
( train )/'<>' Reduce over '<>', which uses '<' as a left argument and '>' as a right one