open Format
let n = int_of_string Sys.argv.(1)
let lines = ref []
let () =
try
while true do
let s = read_line () in
if s = "" then raise End_of_file;
if String.length s = n then
let l = Array.init n (fun i -> s.[i] <> '|') in
lines := l :: !lines
done
with End_of_file ->
()
let lines = List.rev !lines
let compatible l1 l2 =
try
for i = 0 to n-1 do if l1.(i) && l2.(i) then raise Exit done; true
with Exit ->
false
let merge l1 l2 = Array.init n (fun i -> l1.(i) || l2.(i))
let rec compact = function
| [] | [_] as l ->
l
| l1 :: l2 :: lines ->
if compatible l1 l2 then
compact (merge l1 l2 :: lines)
else
l1 :: compact (l2 :: lines)
let included l1 l2 =
let sup1 = ref true in
let sup2 = ref true in
try
for i = 0 to n-1 do
if l1.(i) then sup1 := not !sup1;
if l2.(i) then sup2 := not !sup2;
if l1.(i) && not l2.(i) then raise Exit;
if l1.(i) && l2.(i) && !sup1 <> !sup2 then raise Exit
done;
true
with Exit ->
false
let swapable l1 l2 = included l1 l2 || included l2 l1
let rec swap = function
| [] | [_] as l ->
l
| [l1; l2] as l ->
if swapable l1 l2 then [l2; l1] else l
| l1 :: l2 :: l3 :: lines ->
if swapable l1 l2 then
l2 :: (if compatible l1 l3
then l1 :: l3 :: swap lines
else swap (l1 :: l3 :: lines))
else
l1 :: swap (l2 :: l3 :: lines)
let display_one_line l =
let sup = ref true in
Array.iteri
(fun i b ->
if b then begin
if !sup then printf ">" else printf "<";
sup := not !sup
end else
printf "|")
l;
printf "@."
let display = List.iter display_one_line
let () =
let rec loop lines =
let size = List.length lines in
eprintf "%d lines@." size;
let lines = compact lines in
let lines = swap lines in
if List.length lines < size then loop lines else display lines
in
loop lines