Prepare for Github,
[pylit.git] / doc / examples / 99bottles.py.txt
blobc301f5cbb48119c63a5d17fdbab136f4e529ec1f
1 ..  #!/usr/bin/env python
2   #
3   # :Copyright: 2007 Riccardo Murri, Guenter Milde.
4   #             Released under the terms of the GNU General Public License 
5   #             (v. 2 or later)
6   
7 99bottles.py
8 ============
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`.
18 The lyrics
19 ----------
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:
26 From 99 down to 1::
28   verse_template = """ 
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!"""
33   
34 There is much variation in the final verse. One common final verse (which
35 could potentially cause an infinite-loop motif) is::
37   final_verse = """
38   No bottles of beer on the wall!
39   No bottles of beer!
40   Go to the store and buy some more
41   99 bottles of beer on the wall!"""
42   
43 The Python program
44 ------------------
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.
50 Basic version
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"))
58   
59 Consider the singular case
61 There is one problem left, we should check whether to print 'bottles' or
62 'bottle'.
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"))
72   
73 where an auxiliary function returns the matching suffix (or not)::
75   def plural_suffix(number):
76       if number != 1:
77           return "s"
78       else:
79           return ""
80   
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!"""
90   
91 together with::
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"))
99   
100   
101 Command line use
102 ----------------
104 Print the lyrics if this script is called from the command line::
106   if __name__ == "__main__":
107       print_verses_3()
108       print final_verse
109   
110   
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