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