Skip to content

Instantly share code, notes, and snippets.

@petemcfarlane
Created July 14, 2017 16:51
Show Gist options
  • Save petemcfarlane/ef977d504b1c301c2390c2bcf07ad800 to your computer and use it in GitHub Desktop.
Save petemcfarlane/ef977d504b1c301c2390c2bcf07ad800 to your computer and use it in GitHub Desktop.
-module (till).
-compile(export_all).
% A supermarket billing system will take a sequence of barcodes such as
%
% [1234,4719,3814,1112,1113,1234]
%
% into a printed bill of the form
%
% Erlang Stores
%
% Dry Sherry, 1lt...........5.40
% Fish Fingers..............1.21
% Orange Jelly..............0.56
% Hula Hoops (Giant)........1.33
% Unknown Item..............0.00
% Dry Sherry, 1lt...........5.40
%
% Total....................13.90
% using the data in a simple database such as
%
% [ (4719, "Fish Fingers" , 121),
% (5643, "Nappies" , 1010),
% (3814, "Orange Jelly", 56),
% (1111, "Hula Hoops", 21),
% (1112, "Hula Hoops (Giant)", 133),
% (1234, "Dry Sherry, 1lt", 540)]
% The aim of this exercise is to define the function that
% will produce the bill from a list of barcodes and the database.
% You’ll need to think about how to structure the solution by
% defining the right set of auxiliary functions to help you to
% divide and conquer the problem.
%
% To take the problem further you might like to add these features:
%
% You are asked to add a discount for multiple buys of sherry: for every
% two bottles bought, there is a £1.00 discount.
%
% Design functions which update the database of bar codes. You will need
% a function to add new information while removing any entry for the same
% bar code.
%
% Re-design your system so that bar codes which do not appear in the
% database (e.g. 1113 in the example) give no entry in the final bill.
db() ->
[
{4719, "Fish Fingers" , 121},
{5643, "Nappies" , 1010},
{3814, "Orange Jelly", 56},
{1111, "Hula Hoops", 21},
{1112, "Hula Hoops (Giant)", 133},
{1234, "Dry Sherry, 1lt", 540}
].
getItem(Barcode, [{Barcode,_,_}=Item|_Items]) ->
Item;
getItem(Barcode, [_Item|Items]) ->
getItem(Barcode, Items);
getItem(_Barcode, []) ->
{_Barcode, "Unknown Item", 0}.
printBill(Barcodes, Db) ->
Items = lists:filtermap(fun(Barcode) ->
Item = getItem(Barcode, Db),
case Item of
{_,"Unknown Item",_} -> false;
_ -> {true, Item}
end
end, Barcodes),
LineItems = lists:map(fun(Item) -> lineItem(Item) end, Items),
Spacer = string:copies(" ", 30),
NetTotal = sumItems(Items),
NetTotalPrice = formatPrice(NetTotal),
NetTotalLine = string:pad("Net", 30 - length(NetTotalPrice), trailing, ".") ++ [NetTotalPrice],
Discount = multibuyDiscount(Items),
DiscountPrice = formatPrice(Discount),
DiscountLine = string:pad("Discount", 30 - length(DiscountPrice), trailing, ".") ++ [DiscountPrice],
TotalPrice = formatPrice(NetTotal - Discount),
TotalLine = string:pad("Total", 30 - length(TotalPrice), trailing, ".") ++ [TotalPrice],
Header = string:pad("Erlang Stores", 30, both),
Lines = [
Header,
Spacer
]
++ LineItems
++ [
Spacer,
NetTotalLine,
DiscountLine,
TotalLine
],
Out = string:join(Lines, "\n"),
io:format("~s~n", [Out]).
lineItem({_,Desc,Cents}) ->
Price = formatPrice(Cents),
string:pad(Desc, 30 - length(Price), trailing, ".") ++ [Price].
formatPrice(Cents) ->
erlang:float_to_list(Cents / 100, [{decimals,2}]).
sumItems([]) ->
0;
sumItems([{_,_,Cents}|Items]) ->
Cents + sumItems(Items).
multibuyDiscount(Items) ->
SherryDiscount = countSherrys(Items) div 2 * 100,
SherryDiscount.
countSherrys([]) ->
0;
countSherrys([{1234,_,_}|Items]) ->
1 + countSherrys(Items);
countSherrys([_Item|Items]) ->
countSherrys(Items).
% Design functions which update the database of bar codes.
% You will need a function to add new information while
% removing any entry for the same bar code.
addItem({Id,_,_}=Item, [{Id,_,_}|Items]) ->
[Item|Items]; % update
addItem(Item, [NotItem|Items]) ->
[NotItem | addItem(Item, Items)]; % insert
addItem(Item, []) ->
[Item]. % insert
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment