beam
 
% 2017 Round 2, Problem C, in Picat, by Afa Zhou
% https://code.google.com/codejam/contest/5314486/dashboard#s=p2&a=2
% Beaming With Joy

import util, sat.

main =>
    T = read_line().to_int(),
    foreach (TC in 1..T)
        [R,C] = [to_int(Token) : Token in read_line().split()],
        M = new_array(R),
        foreach (I in 1..R)
            M[I] = read_line().to_array()
        end,
        dc(TC,R,C,M)
    end.

dc(TC,R,C,M) ?=>
    G = new_array(R,C),
    foreach (I in 1..R, J in 1..C)
        G[I,J] = {B,DirL,DirR,DirU,DirD}
    end,
    foreach (I in 1..R, J in 1..C, (M[I,J] == '-' ; M[I,J] == '|'))
        G[I,J] = {0,DirH,DirH,DirV,DirV},  % B=0, a shooter receives no beam
        [DirH,DirV] :: 0..1,
        DirH + DirV #= 1,
        reach(up,I-1,J,DirV,R,C,M,G),
        reach(down,I+1,J,DirV,R,C,M,G),
        reach(left,I,J-1,DirH,R,C,M,G),
        reach(right,I,J+1,DirH,R,C,M,G)
    end,
    foreach (I in 1..R, J in 1..C)
        G[I,J] = {B,DirL,DirR,DirU,DirD},
        (dvar(DirL) -> true; DirL = 0),
        (dvar(DirR) -> true; DirR = 0),
        (dvar(DirU) -> true; DirU = 0),
        (dvar(DirD) -> true; DirD = 0),
        (M[I,J] == '.' -> B = 1; true),
        (#~DirL #/\ #~DirR #/\ #~DirU #/\ #~DirD) #=> #~B
    end,
    solve(G),
    printf("Case #%w: POSSIBLE\n", TC),
    foreach (I in 1..R, J in 1..C)
        ((M[I,J] == '-' || M[I,J] == '|') ->
            G[I,J] = {_B,DirL,_,_,_},
            (DirL == 1 -> Cell = '-'; Cell ='|')
        ;
            Cell = M[I,J]
        ),
        printf("%c",Cell),
        (J == C -> nl; true)
    end.
dc(TC,_R,_C,_M) =>
    printf("Case #%w: IMPOSSIBLE\n", TC).

reach(D,I,J,Dir,R,C,M,G), I >= 1, I =< R, J >= 1, J =< C =>
    next(M[I,J],D,I,J,Dir,R,C,M,G).
reach(D,I,J,Dir,R,C,M,G) => true.

next('#',D,I,J,Dir,R,C,M,G) => true.
next('/',D,I,J,Dir,R,C,M,G) => 
    change_d('/',D,NextD),
    next('.',NextD,I,J,Dir,R,C,M,G).
next('\\',D,I,J,Dir,R,C,M,G) =>
    change_d('\\',D,NextD),
    next('.',NextD,I,J,Dir,R,C,M,G).
next('-',D,I,J,Dir,R,C,M,G) =>
    Dir = 0.    % can't choot a chooter
next('|',D,I,J,Dir,R,C,M,G) =>
    Dir = 0.    % can't choot a chooter
next('.',D,I,J,Dir,R,C,M,G) =>
    next_dir(D,G[I,J],NextDir),
    (dvar(NextDir) ->                        % dvar(NextDir) means this cell has been visited
        true
    ;
        Dir = NextDir,
        next_pos(D,I,J,I1,J1),
        reach(D,I1,J1,Dir,R,C,M,G)
    ).

next_pos(up,I,J,I1,J1) => I1 = I-1, J1 = J.
next_pos(down,I,J,I1,J1) => I1 = I+1, J1 = J.
next_pos(left,I,J,I1,J1) => I1 = I, J1 = J-1.
next_pos(right,I,J,I1,J1) => I1 = I, J1 = J+1.

index (+,+,-)
change_d('/',left,down).
change_d('/',right,up).
change_d('/',up,right).
change_d('/',down,left).
change_d('\\',left,up).
change_d('\\',right,down).
change_d('\\',up,left).
change_d('\\',down,right).

next_dir(left,{_,DirL,DirR,DirU,DirD},NextDir) => NextDir = DirL.
next_dir(right,{_,DirL,DirR,DirU,DirD},NextDir) => NextDir = DirR.
next_dir(up,{_,DirL,DirR,DirU,DirD},NextDir) => NextDir = DirU.
next_dir(down,{_,DirL,DirR,DirU,DirD},NextDir) => NextDir = DirD.