watersheds
% watersheds.pi (in Picat)
% by Neng-Fa Zhou, June 2, 2015
% https://code.google.com/codejam/contest/90101/dashboard#s=p1
% Qualification Round 2009
% Problem B. Watersheds
%
% to use: picat watersheds < input_file > output_file
%
% Thanks to Mike Bionchik for bring this problem to my attention.
%
% This program well demonstrates the features of Picat, including
% logic variables, loops, list comprehensions, and assignments.
%
main =>
T = read_int(stdin), %% number of test cases.
foreach (I in 1..T)
do_case(I)
end.
do_case(Case) =>
H = read_int(stdin), %% height
W = read_int(stdin), %% width
% read matrix
InMatrix = new_array(H,W),
foreach(Row in 1..H, Col in 1..W)
InMatrix[Row,Col] = read_int(stdin)
end,
%% decide flows
BasinMatrix = new_array(H,W),
foreach(Row in 1..H, Col in 1..W)
flow(Row,Col,H,W,InMatrix,BasinMatrix)
end,
%% label cells
Label = ord(a),
foreach(Row in 1..H, Col in 1..W)
if var(BasinMatrix[Row,Col]) then
BasinMatrix[Row,Col] = Label,
Label := Label+1
end
end,
%% output
printf("Case #%w:%n", Case),
foreach(Row in 1..H)
foreach(Col in 1..W)
printf("%w ", chr(BasinMatrix[Row,Col]))
end,
nl
end.
%% find the neighbor with the lowest altitude
flow(Row,Col,1,1,_InMatrix,_BasinMatrix) => true.
flow(Row,Col,H,W,InMatrix,BasinMatrix) =>
{LAlt,LRow,LCol} = min([{InMatrix[Row1,Col1],Row1,Col1} :
(Row1,Col1) in [(Row-1,Col), % north
(Row,Col-1), % west
(Row,Col+1), % east
(Row+1,Col)], % south
Row1 >= 1, Row1 =< H, Col1 >= 1, Col1 =< W]),
if LAlt < InMatrix[Row,Col] then
BasinMatrix[LRow,LCol] = BasinMatrix[Row,Col]
end.