[Question]
  [
A "triplet bracket" (that I made up for this challenge) is one of the following:
```
(...+...)
[...:...]
{...|...}
<...-...>
```
A balanced triplet bracket string (BTBS for short) is either an empty string, two BTBSes concatenated, or one of the above triplet brackets with each `...` replaced with a BTBS.
Your task is to write a program or function that checks whether a string that consists of only `(+)[:]{|}<->` is balanced. Shortest code wins.
## Examples
Your program should return truthy for the following strings:
```
(+)(+)(+)
[[[:]:]:(+(+))]{<->|<(+)->[:]}(+)
<<<<<<<<<<<<->->->->->->->->->->->->
{|(+[:<-{|(+[:<->])}>])}
[[[:]:[:]]:[[:]:[:]]]
{[:](+)|<->{|}}[(+)<->:{|}(+)]
```
Your program should return falsy for the following strings:
```
:[
<|>
(+(+)
[:][:](+[[:]):]
{|{|{|(+{|{|{|}}}}}+)}[:]{|}
{{||}}
<<->-<->-<->>
[(+):((+)+)+(+(+))]
<<<<<->->->->->->
```
  
[Answer]
## JavaScript (ES6), ~~77~~ ~~58~~ ~~57~~ 56 bytes
```
f=s=>s==(s=s.replace(/\(\+\)|\[:]|{\|}|<->/,''))?!s:f(s)
```
### Test cases
```
f=s=>s==(s=s.replace(/\(\+\)|\[:]|{\|}|<->/,''))?!s:f(s)
console.log("Testing truthy values");
console.log(f("(+)(+)(+)"));
console.log(f("[[[:]:]:(+(+))]{<->|<(+)->[:]}(+)"));
console.log(f("<<<<<<<<<<<<->->->->->->->->->->->->"));
console.log(f("{|(+[:<-{|(+[:<->])}>])}"));
console.log(f("[[[:]:[:]]:[[:]:[:]]]"));
console.log(f("{[:](+)|<->{|}}[(+)<->:{|}(+)]"));
console.log("Testing falsy values");
console.log(f(":["));
console.log(f("<|>"));
console.log(f("(+(+)"));
console.log(f("[:][:](+[[:]):]"));
console.log(f("{|{|{|(+{|{|{|}}}}}+)}[:]{|}"));
console.log(f("{{||}}"));
console.log(f("<<->-<->-<->>"));
console.log(f("[(+):((+)+)+(+(+))]"));
console.log(f("<<<<<->->->->->->"));
```
[Answer]
# sed, ~~28~~ 27 bytes
```
:
s#(+)\|\[:]\|{|}\|<->##
t
```
*sed* doesn't have a concept of truthy/falsy, so I'm considering an empty string truthy and a non-empty string falsy. This checks out if we consider the conditional `/^$/`.
*Thanks to @Neil for golfing off 1 byte!*
[Try it online!](http://sed.tryitonline.net/#code=OgpzIygrKVx8XFs6XVx8e3x9XHw8LT4jIwp0&input=KCspKCspKCspCltbWzpdOl06KCsoKykpXXs8LT58PCgrKS0-WzpdfSgrKQo8PDw8PDw8PDw8PDwtPi0-LT4tPi0-LT4tPi0-LT4tPi0-LT4Ke3woK1s6PC17fCgrWzo8LT5dKX0-XSl9CltbWzpdOls6XV06W1s6XTpbOl1dXQp7WzpdKCspfDwtPnt8fX1bKCspPC0-Ont8fSgrKV0KOlsKPHw-CigrKCspCls6XVs6XSgrW1s6XSk6XQp7fHt8e3woK3t8e3x7fH19fX19Kyl9Wzpde3x9Cnt7fHx9fQo8PC0-LTwtPi08LT4-ClsoKyk6KCgrKSspKygrKCspKV0KPDw8PDwtPi0-LT4tPi0-LT4)
[Answer]
## Python, 77 bytes
```
lambda s:eval("s"+".replace('%s','')"*4%('(+)','[:]','{|}','<->')*len(s))==''
```
Uses [Arnauld's replacement idea](https://codegolf.stackexchange.com/a/97071/20260). Generates and evaluates a long string like
```
s.replace('(+)','').replace('[:]','').replace('{|}','').replace('<->','').replace('(+)','').replace('[:]','').replace('{|}','').replace('<->','')
```
to cycle between replacing all the bracket types. Then, checks if the result is the empty string. 
[Answer]
# Mathematica, 55 bytes
```
StringDelete["(+)"|"[:]"|"{|}"|"<->"]~FixedPoint~#==""&
```
Anonymous function. Takes a string as input and returns `True` or `False` as output. Uses the standard method for doing this.
[Answer]
## [Grime](https://github.com/iatorm/grime), 39 bytes
```
e`\(_\+_\)|\[_\:_\]|\{_\|_\}|\<_\-_\>v*
```
[Try it online!](http://grime.tryitonline.net/#code=ZWBcKF9cK19cKXxcW19cOl9cXXxce19cfF9cfXxcPF9cLV9cPnYq&input=WygrKTwtPjpde3x9) Sadly, the TIO version runs out of memory on most of the test cases.
## Explanation
Nothing too fancy here.
`_` is shorthand for the entire pattern, and `v*` is the same as `*`, but with lower precedence.
```
e`                                       Match entire input against this pattern:
  \(_\+_\)                               '(', match of _, '+', match of _, ')'
          |                              or
           \[_\:_\]|\{_\|_\}|\<_\-_\>    same for the other bracket types
                                     v*  repeated 0-∞ times
```
[Answer]
# J, 48 bytes
```
a:=([:delstring&.>/'(+)';'[:]';'{|}';'<->';])^:_
```
Similar to the others, this is also based on Arnauld's [method](https://codegolf.stackexchange.com/a/97071/6710).
## Usage
```
   f =: a:=([:delstring&.>/'(+)';'[:]';'{|}';'<->';])^:_
   f '(+)(+)(+)'
1
   f '[[[:]:]:(+(+))]{<->|<(+)->[:]}(+)'
1
   f '<<<<<<<<<<<<->->->->->->->->->->->->'
1
   f '<|>'
0
   f '[:][:](+[[:]):]'
0
   f '{|{|{|(+{|{|{|}}}}}+)}[:]{|}'
0
```
## Explanation
```
a:=([:delstring&.>/'(+)';'[:]';'{|}';'<->';])^:_  Input: string S
   (                                        )^:_  Repeat until convergence
                                         ]          Get S
                 '(+)';'[:]';'{|}';'<->';           Append to ['(+)', '[:]', '{|}', '<->']
    [:delstring&.>/                                 Reduce right-to-left by deleting
                                                    occurrences of each string on the
                                                    left from the right
                                                    Return the final string as the new S
a:=                                               Test if the final value of S is empty
```
[Answer]
# Japt, 25 bytes
```
!Ue"%(%+%)|%[:]|\{%|}|<->
```
[**Test it online!**](http://ethproductions.github.io/japt/?v=master&code=IVVlIiUoJSslKXwlWzpdfFx7JXx9fDwtPg==&input=IntbOl0oKyl8PC0+e3x9fVsoKyk8LT46e3x9KCspXSI=)
`e` on strings is a recursive-replace function. The second parameter defaults to the empty string, which means this recursively removes matches of the Japt regex `"%(%+%)|%[:]|\{%|}|<->"` (in regular terms, `/\(\+\)|\[:]|{\|}|<->/`). This returns an empty string for balanced triplet strings and a non-empty string for non-balanced, so the correct return value is the logical NOT of this.
[Answer]
## [Pip](http://github.com/dloscutoff/pip), 26 bytes
```
L#aaR:"(+)[:]{|}<->"<>3x!a
```
[Try it online!](http://pip.tryitonline.net/#code=TCNhYVI6IigrKVs6XXt8fTwtPiI8PjN4IWE&input=&args=e3x7fHt8KCt7fHt8e3x9fX19fSspfVs6XXt8fQ)
Loops len(a) times, replacing all occurrences of empty triplet brackets (`"(+)[:]{|}<->"<>3`, where `<>` is the "group" operator, => `["(+)"; "[:]"; "{|}"; "<->"]`) with empty string (`x`). This many iterations is overkill, but it will always be more than enough to completely reduce all properly formed triplet brackets to nothing. After the loop completes, outputs `!a`: `0` if `a` is truthy (still has some characters), `1` if `a` is falsey (empty).
[Answer]
# Scala, 96 bytes
```
def&(s:String):Any={val t=s.replaceAll(raw"\(\+\)|\[:]|\{\|}|<->","")
if(t==s)t.size<1 else&(t)}
```
This is basically the same idea as the other answers, but with some scala boilerplate.
### without stealing ideas from others (188 bytes):
```
import scala.util.parsing.combinator._
val a = new RegexParsers{def r:Parser[_]="("~r~"+"~r~")"|"["~r~":"~r~"]"|"{"~r~"|"~r~"}"|"<"~r~"-"~r~">"|""
def!(s:String)= !parseAll(r,s).isEmpty}!_
```
]