Can I string all my cords and adapters together? Suppose one day you are digging through your big box of unused computer cords and adapters (USB to USB mini, VGA to DVI, etc.). There are tangled cords everywhere making quite a mess, and you wonder if you could simplify things by attaching all the cords together in one long strand, and then just rolling it up.
The question is, is it possible to connect all of your cords and adapters in one long line like this? It's obviously not always possible, e.g. if you only had two cords with completely different plugs, they could not be connected together. But if you had a third cord that can connect to both of them, then you could string all your cords together.
You don't care about what type of plugs are on the ends of the all-cord strand. They don't need to plug into one another to form a loop. You only want to know if making the all-cord strand is possible, and if it is, how to do it.
Challenge
Write a program or function that takes in a multiline string where every line depicts one of the cords you own. A cord is made up of one or more dashes (-), with a plug on either end. A plug is always one of the 8 characters ()[]{}&lt;&gt;.
So these are some valid cords:
&gt;-&gt;
(--[
}-{
&lt;-----]
(---)

But these are not:
--&gt;
(--
)--
[{
---

When connecting cords, only plugs with the exact same bracket type can be connected together.
So these are some valid cord connections:
...---((---...
...---))---...
...---]]---...
...---{{---...
...---&lt;&lt;---...

And these are invalid:
...---()---...
...---)(---...
...---{]---...
...---{[---...
...---&gt;&lt;---...
...---&gt;)---...

If all the cords in the input can be rearranged and attached together in one long strand, then output that strand to stdout on one line (with an optional trailing newline). When there are multiple solutions you can choose any one of them to output. If making a single strand is not possible, then output nothing (or output an empty string with an optional trailing newline).

For example, if the input is
[--&gt;
{---]
&gt;----{

the output could be
[--&gt;&gt;----{{---]

where all the cords are strung together.
However if the input were
[--&gt;
{---]

the cords cannot be connected so there would be no output.

Note that cords can be flipped around as much necessary to make connections. e.g. [--&gt; and &lt;--] are effectively the same cord because they can make the same type of connections. Some outputs may depend on flipping the input cords.

For example
(-[
}--]

could have output
(-[[--{

where the second cord is flipped, or
}--]]-)

where the first cord is flipped.
(Note that in general flipping the entire output is valid because it's the same as initially flipping every cord individually.)

The lengths of the cords in the output should of course match the lengths of the corresponding input cords. But the cords may be reordered and flipped  around as much as you want in order to make the all-cord strand. The input will always contain at least one cord.
The shortest code in bytes wins.
Test Cases
Cases with output:
[--&gt;
{---]
&gt;----{
gives
[--&gt;&gt;----{{---]
or
[---}}----&lt;&lt;--]

(-[
}--]
gives
(-[[--{
or
}--]]-)

(-)
gives
(-)

[--{
gives
[--{
or
}--]

[-]
]-[
gives
[-]]-[
or
]-[[-]

[-----&gt;
)------------[
{--&lt;
}---)
could give
[-----&gt;&gt;--}}---))------------[
or
&gt;--}}---))------------[[-----&gt;
or
}---))------------[[-----&gt;&gt;--}
or
{--&lt;&lt;-----]]------------((---{
etc.

&gt;--&gt;
&gt;-&gt;
&gt;---&gt;
could give
&gt;--&gt;&gt;-&gt;&gt;---&gt;
or
&gt;---&gt;&gt;--&gt;&gt;-&gt;
or
&gt;-&gt;&gt;--&gt;&gt;---&gt;
or
&lt;--&lt;&lt;---&lt;&lt;-&lt;
etc.

(-]
]-&gt;
&gt;-}
}-)
)-[
[-&lt;
&lt;-{
{-(
could give
(-]]-&gt;&gt;-}}-))-[[-&lt;&lt;-{{-(
or
{-((-]]-&gt;&gt;-}}-))-[[-&lt;&lt;-{
or
&lt;-{{-((-]]-&gt;&gt;-}}-))-[[-&gt;
etc.

Cases without output:
[--&gt;
{---]

[-]
[-]

(-]
]-&gt;
}-)

&gt;-&gt;
&gt;--&gt;
]---]

[-------------------]
]-------------------[
[-----------------]
[-----------------]

{--[
]--}
Unreadable, 3924 bytes

This is the first time I implemented somewhat of a call-stack-like structure in Unreadable.

(The first version of this was over 5300 bytes, just to give an idea of how much I golfed this.)


  '"""""'""'""""""'""""""'"""'""'""'""'""'""'""'"""""""'"""'""""""'""'"""'""""""""""'""""'""""'""""'""""""'""'""'""'""'""'""'"""""""'"""'"""""'"""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""'""'""'"""""""'"""'""""""""""'""""""""'"""'"""'""""'""""""'""'""'""'""'"""'"""""""'""'""'"""""""'"""'""""""'""'"""""""'"""'""'"""""""'""'"""""""'"""'"""""'""""""'""'"""'"""""""'"""""""'"""'""""'""""""'""'""'""'"""""""'"""'"""""""""'""""""'""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'""'"""'"""""""""'""""""'""'"""'""""""""'"""""""'""'"""'"""""""""'""""""'""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'""'"""'"""""""""'""""""'""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'""'"""'"""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'""'"""'""""""""'""""""""'"""""""'"""""""'"""'""'""'"""""""'"""""""'"""'""'""'"""""""'"""""""'"""'""'""'"""""""'"""""""'"""'""""""""'"""""""'"""""""'"""'""'"""""""'"""""""'"""'""""""'"""'""'""'"""""""'"""'""""""'""'""'""'"""""""'"""'"""""""'""""""""'"""""""'"""'""""""""""'""""""'"""""""'"""'""""""""'""""""'""'""'""'"""'""""""'""""""'""'"""'""'"""""""'"""'"""'"""""'"""""""'""'""'""'"""'""""'""""'""""""'""'""'"""'""""""'"""'"""'"""""'"""""""'""""""'"""'""'""'""'""'""'"""""""'"""'"""""""""'"""""""'""'""'""'""'"""""""'"""'"""'""""""'""'""'"""'""""""""'"""'"""""""""'"""""""'""'""'"""'""""""'""'""'""'"""'""""""""'"""'""""'""""'""""""'"""'"""""""'"""""""'""'"""'"""""'"""""""'""""""'"""'""'""'""'""'""'"""""""'"""'"""""""""'"""""""'""'""'""'""'"""""""'"""'"""'"""""""""'"""""""""'"""""""'""""""""'"""""""'""'"""'""""'""""'""""""'""""""""'"""'"""""""'""'""'"""""""'""""""""'"""""""'""'"""'""""""'""'""'"""'""'"""""""'"""""""'"""'"""""""""'"""""'""""""'""'""'"""'""""""""'"""""""'""'""'"""'""""""'""""""""'"""'""""""""'"""""""'""""""""'"""'""""""""'"""'"""'"""'""""""'"""'""""""""'""""""'""'""'"""'""""""'"""""""'""'"""'"""""""'"""'"""'"""""""""'"""""""'""'""'"""'""""""'""""""'""'"""'""'"""""""'""'"""'""""""'"""""""'"""'""""""'"""""""""'"""""""'""""""""'"""""""'"""'""'""'""'""'""'"""""""'"""'""""""""'""""""""'""""""""'""""""""'""""""""'"""""""'"""'"""'"""""""""'""""""'"""'"""""""'""""""'""'"""'""""""""'"""""""'""'"""'""""""'""'""'""'""'"""""""'"""'""""""'"""""""""'"""""""'""'""'""'"""""""'"""'""'""'""'""'""'""'""'""'""'"""""""'"""'""""""""'"""""""'"""'""""""""'"""'""""""'""'""'""'"""'""""""""'"""'"""""""""'"""""""'"""'"""""'""""""""'"""""""'""""""'"""'""'"""""""'"""'""""'""""'"'"""""""'"""""""'"""""""'"""'"""""'""'""""""'""'"""""""'"""""""'"""'""""""""'"""""""'""'"""""""'"""""""'"""'"'"""""""'""'""'""'""'"""'"'"""""""'""'""'"""""""'"""""""'"""'"""


Explanation

Consider this example input:

&gt;--{
[---}


Throughout most of the execution, the tape is laid out as follows:


Cells 0 to 5 are locations for various variables.
Cell 6 onwards contain all information about the set of cables in your box:


The remaining cells after the “zero terminator” contain the stack. Each “stackframe” is a single cell that points to the first cell of a cable (the “start plug” cell). In the above example, when the program decides it has found a solution, the stack will contain 6 (referring to &gt;--{, the first cable) and 21 (referring to {---], the mirror of the second cable).


The program proceeds in three main stages:


Read the entire input and generate the above structure, including all the mirrored cables.
Try out all combinations (but stop if a solution is found).
If a solution was found, output it.


The first stage (read input and generate cables structure) only uses cells #1 (which I’ll call p) and #2 (which I’ll call ch) and operates in a while loop as follows:


While condition: increment p by 6, read the next character (start plug) into cell *p, and check that it isn’t -1 (EOF).
Read subsequent characters into *(p+2), and count them in *(p+1), until we encounter anything other than - (hyphen). At that point, *(p+1) will contain the number of hyphens (cable length) and *(p+2) the last non-hyphen character (the end plug). (We also copy the hyphen characters to cell #5 so we can access this ASCII code later in the output stage.)
In a while loop, find the mirror plug and store it at *(p+3), then increment p by 2, until *p is zero. The loop looks like this in pseudocode:

while (ch = *p) {
    *(p+3) = (ch -= 40) ? (ch -= 1) ? (ch -= 19) ? (ch -= 31) ? ch-32 ? *p-2 : *p+2 : *p+2 : *p+2 : *p-1 : *p+1
    p += 2
}

This loop will always perform two iterations (the start plug and end plug) and store the results in the fourth and sixth cell of this cable. Now, if you paid attention, you realize that the sixth cell is indeed the correct location for the mirrored end plug, but the mirrored start plug is in the cell labeled “boolean indicating original cable”. This is OK because we only need this cell to be a non-zero value.
Since p has just been incremented a total of 4, it’s now pointing at the cell labeled “boolean indicating cable is in use”. Set *(p+3) to the value of *(p-1). This puts the mirrored start plug in the right place.
Read (and discard) one more character (which we expect to be a newline, but the program doesn’t check for that).


p initially starts out at 0 but is incremented by 6 inside the while condition, thus the cable data starts at cell #6. p is incremented by 4 inside the loop body, and thus a total of 10 for each cable, which is exactly what we need.

During the second stage, cells #0–4 are occupied by variables that I’ll call a, p, q, m, and notdone. (Cell #5 still remembers the ASCII code of the hyphen.)

To get ready for stage 2, we need to set *p back to 0 (the cell labeled “zero terminator”) so that it can act as the terminator for the list of cables; we also set q (which is our stack pointer) to p+1 (i.e. the cell after the “zero terminator”; this is where the stack starts); *q to 1 (the first item on the stack; why 1 will become apparent later); and notdone to 1. All this is done in a single statement:

*p = (notdone = *(q = p+1) = 1)-1


The second stage is also a while loop. Its condition is simply notdone. In each iteration of that while loop, any one of the following four things could happen:


We find that all cables are marked “in use”. This means we’ve found a solution (which is represented by the current stack contents).
We can advance *q to another eligible cable (which we promptly mark as “in use” along with its twin) and then recurse (i.e. create a new stackframe).
We cannot advance *q because no further eligible cable exists, so we need to backtrack (remove a stackframe and mark the previous cable and its twin as no longer “in use”).
We cannot advance *q because no further eligible cable exists and we cannot backtrack because we have reached the bottom of the stack. This means there is no solution.


The loop body checks for each of these four conditions in this order. Here are the details:


Set m and p to 1 and in a while loop, increment p by 5 (thus iterating through the cables) and check if *(p+4) (“in use”) is set. If it isn’t, set m to 0. At the end of that loop, m tells us if all the cables are in use. If so, set notdone to 0 to terminate the main loop. Otherwise, continue at step 2 below.
Set p to *q (the cable at the top of the stack) and in a while loop similar to the above, increment p by 5 to iterate through the cables. Starting at *q ensures we only consider those that we haven’t already considered before; however, remember that the initial value for a new stackframe is 1, so the first cable looked at is the one at cell 6, which is indeed the first cable.

For each cable, we need to check *(p+4) to ensure that it’s not already in use, and also that either *(q-1) is zero (meaning we’re at the bottom of the stack, so there’s no constraint on the start plug), or *p (the cable’s start plug) is equal to *(*(q-1)+2) (the end plug of the cable just below on the stack). We check for equality by setting a to *(*(q-1)+2) and m to *p+1 and then decrementing both in a while loop. The +1 is because m is decremented inside the while condition, so it is decremented once more than a. If a is zero at the end of this, the two plugs are equal.

Thus, if either *(q-1) was zero or the equality comparison succeeded, the cable is eligible. Set *q to p to replace the cable at the top of the stack with the new one; set m to the same to indicate that we found a matching cable; and then decrement p. That decrement is a little trick to cause the while loop (iterating through the cables) to terminate early; it will increment p by 5 again, thus taking it to the cell containing this cable’s “in use” flag, and we know that’s zero because we just checked that.
Finally, after the cable-iterating while loop, we check if m is non-zero. If so, we found a matching cable and p is pointing at the “in-use” flag for that matching cable. Set it to 1 to mark it as in use. Also set *(*(p-1) ? p+5 : p-5) to 1 to mark its twin as in use. Finally, increment q and set the new *q to 1 to create a new stackframe.
If, after the cable-iterating while loop, we find m to be zero, there are no more matching cables, so we need to backtrack. Decrement q to move down the stack and check if it’s still pointing at a cable (a non-zero value). If so, mark that cable and its twin as no longer in use. (We store the value of *q in p to make this expression shorter in code.)
If, after decrementing q, we find that it points at a zero value, then that is the “zero terminator”, which means we’ve underrun the stack. We conclude that there is no solution. We set notdone to 0 to terminate the main loop.


The third stage is the output stage. There are two things that can happen:


the main loop found a solution that we need to output, or
the main loop concluded there is no solution and we output nothing.


Conveniently, if there was no solution, p is zero because we set it to the value of *q before checking that for zero; and if there was a solution, p is pointing at the “zero terminator” because it just iterated through the cables, so we can now use p to iterate through the stack. So just iterate through the stack, outputting for each cable the start plug (*(*p)), the hyphens (by decrementing *(*p+1) in a while loop; and using the hyphen ASCII code stored in cell #5), and the end plug (*(*p+2)). Never mind that this destroys the cable-length information; we don’t need that anymore.