shopping_plan
``` ```
% shopping_plan.pi (in Picat)
% by N.F. Zhou, Jan. 27, 2016
% Practice Problems
% Problem D. Shopping Plan
%
% to use: picat shopping_plan < input_file > output_file
%
import util.

main =>
foreach (TC in 1..T)
initialize_table,
[_NItems,NStores,GasPrice] = [to_int(Token) : Token in read_line().split()],
ShoppingList = [change_name(Name) : Name in read_line().split()].sort(),
Stores = [make_store(read_line().split(), ShoppingList) : _ in 1..NStores],
sp((0,0),ShoppingList,(Stores,GasPrice),Cost),
printf("Case #%w: %.7f\n", TC, Cost)
end.

change_name(Name) = NewName, append(Pre, "!", Name) =>
NewName = ['!'|Pre].
change_name(Name) = Name.

make_store([XStr,YStr|Rest], ShoppingList) = \$store(X,Y,StoreItems) =>
X = to_int(XStr), Y = to_int(YStr),
StoreItems = [(Item,Price) : Token in Rest, parse_item_price(Token, Item, Price, ShoppingList)].sort().

parse_item_price(Token, Item, Price, ShoppingList) =>
once append(ItemStr, [':'|PriceStr], Token),
Price = to_int(PriceStr),
if member(ItemStr,ShoppingList) then
Item = ItemStr
else
Item = ['!'|ItemStr]    % perishable
end.

table (+,+,+,min)
sp((X,Y), [], (_,GasPrice), Cost) => Cost = sqrt(X*X+Y*Y)*GasPrice.
sp((X,Y), Items, SG@(Stores,GasPrice), Cost) =>
Store = \$store(X1,Y1,StoreItems),
member(Store,Stores),
shop_at_store(StoreItems, Items, ItemsR, 0, Price, HasPerishable),
if HasPerishable == true then
sp((0,0), ItemsR, SG, Cost1),
Dist  = sqrt((X-X1)**2+(Y-Y1)**2) + sqrt(X1*X1+Y1*Y1)
else
sp((X1,Y1), ItemsR, SG, Cost1),
Dist  = sqrt((X-X1)**2+(Y-Y1)**2)
end,
Cost = Dist*GasPrice+Price+Cost1.

% buy items at the selected store
shop_at_store(_StoreItems, [], ItemsR, TotalPrice0, TotalPrice, _HasPerishable) =>
TotalPrice = TotalPrice0, ItemsR = [].
shop_at_store(StoreItems, [Item|Items], ItemsR, TotalPrice0, TotalPrice, HasPerishable) ?=>
member((Item,Price),StoreItems),
if Item = ['!'|_] then HasPerishable = true end,
shop_at_store(StoreItems, Items, ItemsR, TotalPrice0+Price, TotalPrice, HasPerishable).
shop_at_store(StoreItems, [Item|Items], ItemsR, TotalPrice0, TotalPrice, HasPerishable) =>
ItemsR = [Item|ItemsRR],
shop_at_store(StoreItems, Items, ItemsRR, TotalPrice0, TotalPrice, HasPerishable).

``````