1 .. #!/usr/bin/env python
3 # :Copyright: 2007 Riccardo Murri, Guenter Milde.
4 # Released under the terms of the GNU General Public License
9 Introductory Example to Literate Programming
10 ++++++++++++++++++++++++++++++++++++++++++++
12 Print the famous `99 bottles of beer` song lyrics
15 This was used as an introductory example to literate programming
16 in the (no longer available) `LiteratePrograms.org Wiki`.
21 We take the lyrics from the Wikipedia, which says in the
22 `99 bottles of beer`_ entry:
24 The verse format is very formulaic, and can be expressed as follows:
29 <number> bottles of beer on the wall
30 <number> bottles of beer!
31 Take one down, pass it around
32 <number - 1> bottles of beer on the wall!"""
34 There is much variation in the final verse. One common final verse (which
35 could potentially cause an infinite-loop motif) is::
38 No bottles of beer on the wall!
40 Go to the store and buy some more
41 99 bottles of beer on the wall!"""
46 There are a countless number of ways to implement a program that prints the
47 whole song in Python. The following examples uses a `for` loop and the
48 `replace` method of string objects.
52 Count down from 99 to 1 and print the verses::
54 def print_verses_1(start_number=99):
55 for number in xrange(start_number, 0, -1):
56 verse = verse_template.replace("<number>", str(number))
57 print verse.replace("<number - 1>", str(number-1 or "No"))
59 Consider the singular case
61 There is one problem left, we should check whether to print 'bottles' or
64 An improved version will replace the "bottles" with a construct that
65 takes into account the actual number of bottles::
67 def print_verses_2(start_number=99):
68 for number in xrange(start_number, 0, -1):
69 verse = verse_template.replace("<number>", str(number))
70 verse = verse.replace("bottles", "bottle" + plural_suffix(number))
71 print verse.replace("<number - 1>", str(number-1 or "No"))
73 where an auxiliary function returns the matching suffix (or not)::
75 def plural_suffix(number):
81 Still, the last line come out wrong, as here we have <number-1> bottles. To
82 treat this case we either could split the last line and treat it differently,
83 or use a modified template as e.g. ::
85 verse_template_2 = """
86 <number> bottle<s> of beer on the wall
87 <number> bottle<s> of beer!
88 Take one down, pass it around
89 <number - 1> bottle<s> of beer on the wall!"""
93 def print_verses_3(start_number=99):
94 for number in xrange(start_number, 0, -1):
95 verse = verse_template_2.replace("<number>", str(number))
96 verse = verse.replace("<s>", plural_suffix(number), 2)
97 verse = verse.replace("<s>", plural_suffix(number-1), 1)
98 print verse.replace("<number - 1>", str(number-1 or "No"))
104 Print the lyrics if this script is called from the command line::
106 if __name__ == "__main__":
111 .. _99 bottles of beer: http://en.wikipedia.org/wiki/99_Bottles_of_Beer
112 .. .. _LiteratePrograms.org Wiki:
113 http://en.literateprograms.org/LiteratePrograms:Welcome