g | x | w | all
Bytes Lang Time Link
417Python3241019T145637ZAjax1234
173Befunge161206T231342ZJames Ho
178JavaScript ES6161204T190920ZNeil
241Python 2161205T105825ZTFeld
025Pyth161204T054309ZMaltysen

Python3, 417 bytes

from itertools import*
E=enumerate
def f(w):
 C=0
 D={i:(C:=C+1)if'|'==a else 0 for i,a in E(w[0])}
 B=[[*i]for i in zip(*w[::-1])]
 for I,j in E(B):
  for a,b in groupby(E(j),key=lambda x:x[1].lower()):
   if'x'==a:
    u=[*b];v=sum([-1,1][t=='X']for _,t in u)
    for A,_ in u:B[I][A]=' '
    if v:B[I][u[-1][0]]=v
 return'\n'.join(f'{D[i-1]} {D[i+1]} '+['L','R'][a==1]for j in zip(*B) for i,a in E(j)if a in[1,-1])

Try it online!

Befunge, 173 bytes

Input is read from stdin in the exact format given in the challenge description, although it's crucial that every line be the correct length and the final line must include a newline (i.e. not just EOF at the end of that line).

$1>>05p~$~:55+-#v_
$_^#`"N":+1g50$<>:2+3%1-05g6g+0v>!#:v#
vg50-1*2p51:-1_^#:<*2!!-*84p6g5<
 +#,.#$"R"\#\-#+5<^g51$_:0`6*\25g\v@_:#!.#:1#,
>+::25p6g\48*\6p48 *-:!^!:--1*2`0:<

Try it online!

The basic idea for this solution is that we have an "array" keeping track of the twist counts for each wire. So every time we encounter a twist in one direction we increment the count for the associated wire, while a twist in the other direction will decrement the count.

At the same time as we process the twist for a particular wire, we also look at the twist count for the wires to the left and right of it. If either of them are non-zero, we need to "flush" those twists onto the stack, since it will no longer be possible for them to be unravelled by later twists in the opposite direction.

After the last line of input, the input stream returns EOF repeatedly, and these EOF characters are interpreted as twists in every wire, at least for the purposes of flushing. This forces the program to flush any outstanding counts in the array, but it will not generate any new twist counts.

Once we've finished processing the input, all the commands for untangling the wires will now be on the stack. This means we can simply pop them off in reverse order to output the instructions needed to untangle the wires from the bottom up.

JavaScript (ES6), 178 bytes

f=([t,...a],r=[])=>a[0]?t.replace(/x/gi,(c,i)=>(c=c<'x'?'R':'L',i=++i/2,r.reduce((f,[j,,d],n)=>f||i<j+2&&j<i+2&&(j-i|c==d||r.splice(n,1)&&2),0)<2?r=[[i,i+1,c],...r]:r))&&f(a,r):r

Takes input as an array of strings representing lines and returns an array of arrays of values e.g. [[2, 3, "R"], [3, 4, "L"], [1, 2, "R"]]. The reverse ordering helps with the eliminations.

Python 2, 244 241 bytes

m=[]
for l in input():
 for i in range(len(l)):
  c=l[i];a=i/2+1;L,R=[a,a+1,'LR'[c>'v']],[a,a+1,'RL'[c>'v']];x=m.index(L)if L in m else-1;M=zip(*m[:x+1])
  if c in'xX':
   if x>=0and(a in M[1]or a+1in M[0])<1:del m[x]
   else:m=[R]+m
print m

Takes input as list of strings

Example:

Input: ['| | | |', ' X | |', '| | x ', '| X |', ' x | |']

Output: [[1, 2, 'L'], [2, 3, 'R'], [3, 4, 'L'], [1, 2, 'R']]

Edit: Fixed for case:

Input: ['| | |', ' X |', ' X |', ' x |', '| X', ' X |', ' x |', ' x |', '| | |']

Output: [[1, 2, 'L'], [2, 3, 'R'], [1, 2, 'R']]

Pyth - 26 25 bytes

Very straightforward, maybe I can golf the filtering.

fhhT_m+hB/xrdZ\x2@"RL"}\x

Try it online here.