/* 99 bottles of beer in Picat. From http://rosettacode.org/wiki/99_Bottles_of_Beer """ 99 Bottles of Beer In this puzzle, write code to print out the entire "99 bottles of beer on the wall" song. For those who do not know the song, the lyrics follow this form: X bottles of beer on the wall X bottles of beer Take one down, pass it around X-1 bottles of beer on the wall X-1 bottles of beer on the wall ... Take one down, pass it around 0 bottles of beer on the wall Where X and X-1 are replaced by numbers of course. Grammatical support for "1 bottle of beer" is optional. As with any puzzle, try to do it in as creative/concise/comical a way as possible (simple, obvious solutions allowed, too). See also: http://99-bottles-of-beer.net/ Model created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import util. main => go. go => beer1(99). go2 => println([beer2(Beer) : Beer in 99..-1..1].join('')). go3 => beer3(99). go4 => beer_dcg(99..-1..1,Y,[]), % Note the flatten (and .to_string for the digits in the DCG) println(Y.flatten), nl. beer1(N) => Beer = N, while (Beer > 0) printf("%d bottles of beer on the wall,\n", Beer), printf("%d bottles of beer.\n", Beer), printf("Take one down, pass it around.\n"), printf("%d bottles of beer.\n", Beer-1), Beer := Beer -1 end, print("0 more bottles of beer on the wall.\n"), nl. beer2(B) = S => BS = B.to_string(), BB = " bottles", BT = BB, if B > 1 then BB := BB ++ "s" end, OB = " of beer", NL = "\n", BW = OB ++ " on the wall." ++ NL, T = NL ++ "Take one down, pass it around." ++ NL, S1 = BS ++ BT ++ BW ++ BS ++ BT ++ OB ++ T ++ cond(B > 0, (B-1).to_string() ++ BT ++ BW ++ NL, ""), S = S1. print_beer(Beer) :- Ss = cond(Beer != 1, "s",""), Ss1 = cond(Beer-1 != 1, "s",""), printf("%d bottle%s of beer on the wall,\n", Beer,Ss), printf("%d bottle%s of beer.\n", Beer,Ss), printf("Take one down, pass it around.\n"), printf("%d bottle%s of beer.\n", Beer-1,Ss1), nl. beer3(Beer) :- Beer > 0, print_beer(Beer), beer3(Beer-1). % Note that we have to convert the numbers (Beer) to strings % and then also flatten the result. beer_dcg([Beer|Beers]) --> [Beer.to_string], " bootles of beer on the wall.\n", [Beer.to_string] , " bottles of beer.\n", "Take one down, pass it around.\n", [(Beer-1).to_string], " bottles of beer.\n", beer_dcg(Beers). beer_dcg([]) --> [].