fix leading comment
[pylit.git] / rstdocs / examples / 99bottles.py
blob2355bcc839d6bdb75b09a8453bd010aed6a1c698
1 #!/usr/bin/env python
3 # :Copyright: 2007 Riccardo Murri, Guenter Milde.
4 # Released under the terms of the GNU General Public License
5 # (v. 2 or later)
7 # 99bottles.py
8 # ============
9 #
10 # Print the famous `99 bottles of beer` song lyrics
12 # This is used as an introductory example to literate programming
13 # in the `LiteratePrograms.org Wiki`_.
15 # The lyrics
16 # ----------
18 # We take the lyrics from the Wikipedia_, which says in the
19 # `99 bottles of beer`_ entry:
21 # The verse format is very formulaic, and can be expressed as follows:
23 # From 99 down to 1::
25 verse_template = """
26 <number> bottles of beer on the wall
27 <number> bottles of beer!
28 Take one down, pass it around
29 <number - 1> bottles of beer on the wall!"""
31 # There is much variation in the final verse. One common final verse (which
32 # could potentially cause an infinite-loop motif) is::
34 final_verse = """
35 No bottles of beer on the wall!
36 No bottles of beer!
37 Go to the store and buy some more
38 99 bottles of beer on the wall!"""
40 # The Python program
41 # ------------------
43 # There are a countless number of ways to implement a program that prints the
44 # whole song in Python. The following examples uses a `for` loop and the
45 # `replace` method of string objects.
47 # Basic version
49 # Count down from 99 to 1 and print the verses::
51 def print_verses_1(start_number=99):
52 for number in xrange(start_number, 0, -1):
53 verse = verse_template.replace("<number>", str(number))
54 print verse.replace("<number - 1>", str(number-1 or "No"))
56 # Consider the singular case
58 # There is one problem left, we should check whether to print 'bottles' or
59 # 'bottle'.
61 # An improved version will replace the "bottles" with a construct that
62 # takes into account the actual number of bottles::
64 def print_verses_2(start_number=99):
65 for number in xrange(start_number, 0, -1):
66 verse = verse_template.replace("<number>", str(number))
67 verse = verse.replace("bottles", "bottle" + plural_suffix(number))
68 print verse.replace("<number - 1>", str(number-1 or "No"))
70 # where an auxiliary function returns the matching suffix (or not)::
72 def plural_suffix(number):
73 if number != 1:
74 return "s"
75 else:
76 return ""
78 # Still, the last line come out wrong, as here we have <number-1> bottles. To
79 # treat this case we eiter could split the last line and treat it differently,
80 # or use a modified template as e.g. ::
82 verse_template_2 = """
83 <number> bottle<s> of beer on the wall
84 <number> bottle<s> of beer!
85 Take one down, pass it around
86 <number - 1> bottle<s> of beer on the wall!"""
88 # together with::
90 def print_verses_3(start_number=99):
91 for number in xrange(start_number, 0, -1):
92 verse = verse_template_2.replace("<number>", str(number))
93 verse = verse.replace("<s>", plural_suffix(number), 2)
94 verse = verse.replace("<s>", plural_suffix(number-1), 1)
95 print verse.replace("<number - 1>", str(number-1 or "No"))
98 # Command line use
99 # ----------------
101 # Print the lyrics if this script is called from the command line::
103 if __name__ == "__main__":
104 print_verses_3()
105 print final_verse
108 # .. _Wikipedia: http://en.wikipedia.org
109 # .. _99 bottles of beer: http://en.wikipedia.org/wiki/99_Bottles_of_Beer
110 # .. _LiteratePrograms.org Wiki:
111 # http://en.literateprograms.org/LiteratePrograms:Welcome