Created
July 14, 2017 16:51
-
-
Save petemcfarlane/ef977d504b1c301c2390c2bcf07ad800 to your computer and use it in GitHub Desktop.
Exercise from part 2.25 of https://www.futurelearn.com/courses/functional-programming-erlang/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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