Skip to content

Instantly share code, notes, and snippets.

@ingydotnet
Created November 5, 2024 07:14
Show Gist options
  • Select an option

  • Save ingydotnet/93753b50508670b22a309322b7236046 to your computer and use it in GitHub Desktop.

Select an option

Save ingydotnet/93753b50508670b22a309322b7236046 to your computer and use it in GitHub Desktop.

YAMLScript Comparison for '99-bottles-of-beer'

This page compares the YAMLScript code for the Rosetta Code task '99-bottles-of-beer' with code from other Rosetta Code Languages.

Click on the arrow for a language below to expand its code.

This Markdown page was generated by this YAMLScript program.


About Task '99-bottles-of-beer'

;Task: Display the complete lyrics for the song:     '''99 Bottles of Beer on the Wall'''.

;The beer song: The lyrics follow this form:

::: 99 bottles of beer on the wall
::: 99 bottles of beer
::: Take one down, pass it around
::: 98 bottles of beer on the wall

::: 98 bottles of beer on the wall
::: 98 bottles of beer
::: Take one down, pass it around
::: 97 bottles of beer on the wall

... and so on, until reaching   '''0'''     (zero).

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).

{{Template:Strings}}

;See also:


YAMLScript (15 lines)

!yamlscript/v0

defn main(number=99):
  each num (number .. 1):
    say: |
      $bottles(num) of beer on the wall,
      $bottles(num) of beer.
      Take one down, pass it around.
      $bottles(num.--) of beer on the wall.

defn bottles(n):
  condp eq n:
    0    :: No more bottles
    1    :: 1 bottle
    else :  "$n bottles"

The Exercism Languages

8th (12 lines)
[
  ( "Just one more bottle of beer on the wall, one bottle of beer.\n" . ) ,
  ( I dup "%d bottles of beer on the wall, %d bottles of beer.\n" s:strfmt . )
] constant lyrics

: app:main
  (
    dup lyrics [2,99] rot ' n:cmp a:pigeon w:exec
    n:1- "Take one down, pass it around, %d bottles of beer on the wall.\n\n" s:strfmt .
  ) 1 99 loop-

  "No more bottles of beer on the wall, no more bottles of beer.\n" . ;
ABAP (18 lines)
REPORT YCL_99_BOTTLES.

DATA it_99_bottles TYPE TABLE OF string WITH EMPTY KEY.
DATA(cr_lf) = cl_abap_char_utilities=>cr_lf.
it_99_bottles = VALUE #(
    FOR i = 99 THEN i - 1 UNTIL i = 0 ( COND string( LET  lv = ( i - 1 )
                                                          lr = i && | bottles of beer on the wall|
                                                                 && cr_lf
                                                                 && i && | bottles of beer|
                                                                 && cr_lf
                                                                 && |Take one down, pass it around|
                                                                 && cr_lf
                                                                 && lv && | bottles of beer on the wall|
                                                                 && cr_lf IN WHEN 1 = 1 THEN lr )
                                      )
                         ).
cl_demo_output=>write( it_99_bottles ).
cl_demo_output=>display( ).
AWK (21 lines)
# usage:  gawk  -v i=6  -f beersong.awk

function bb(n) {
	b = " bottles of beer"
	if( n==1 ) { sub("s","",b) }
	if( n==0 ) { n="No more" }
	return n b
}

BEGIN {
	if( !i ) { i = 99 }
	ow = "on the wall"
	td = "Take one down, pass it around."
	print "The beersong:\n"
	while (i > 0) {
		printf( "%s %s,\n%s.\n%s\n%s %s.\n\n",
			bb(i), ow, bb(i), td, bb(--i), ow )
		if( i==1 ) sub( "one","it", td )
	}
	print "Go to the store and buy some more!"
}
C (17 lines)
#include <stdio.h>

int main(int argc, char *argv[])
{
        if(argc == 99)
                return 99;
        if(argv[0] != NULL){
                argv[0] = NULL;
                argc = 0;
        }
        argc = main(argc + 1, argv);
        printf("%d bottle%c of beer on the wall\n", argc, argc == 1?'\0': 's');
        printf("%d bottle%c of beer\n", argc, argc == 1?'\0': 's');
        printf("Take one down, pass it around\n");
        printf("%d bottle%c of beer on the wall\n\n", argc - 1, (argc - 1) == 1?'\0': 's');
        return argc - 1;
}
C++ (20 lines)
#include <iostream>
using namespace std;
void rec(int bottles)
{
if ( bottles!=0)
 {
     cout << bottles << " bottles of beer on the wall" << endl;
        cout << bottles << " bottles of beer" << endl;
        cout << "Take one down, pass it around" << endl;
        cout << --bottles << " bottles of beer on the wall\n" << endl;
    rec(bottles);
 }
}

int main()
 {
rec(99);
system("pause");
return 0;
}
ColdFusion (9 lines)
<cfoutput>
  <cfloop index="x" from="99" to="0" step="-1">
    <cfset plur = iif(x is 1,"",DE("s"))>
    #x# bottle#plur# of beer on the wall<br>
    #x# bottle#plur# of beer<br>
    Take one down, pass it around<br>
    #iif(x is 1,DE("No more"),"x-1")# bottle#iif(x is 2,"",DE("s"))# of beer on the wall<br><br>
  </cfloop>
</cfoutput>
Clojure (13 lines)
(defn paragraph [num]
  (str num " bottles of beer on the wall\n"
       num " bottles of beer\n"
       "Take one down, pass it around\n"
       (dec num) " bottles of beer on the wall.\n"))

(defn lyrics []
  (let [numbers (range 99 0 -1)
        paragraphs (map paragraph numbers)]
    (clojure.string/join "\n" paragraphs)))


(print (lyrics))
COBOL (16 lines)
program-id. ninety-nine.
data division.
working-storage section.
01  cnt       pic 99.

procedure division.

  perform varying cnt from 99 by -1 until cnt < 1
    display cnt " bottles of beer on the wall"
    display cnt " bottles of beer"
    display "Take one down, pass it around"
    subtract 1 from cnt
    display cnt " bottles of beer on the wall"
    add 1 to cnt
    display space
  end-perform.
CoffeeScript (4 lines)
for j in [99..1]
    x=''
    x += [j,j-1,'\nTake one down, pass it around\n'," bottles of beer",' on the wall\n'][i] for i in [0,3,4,0,3,2,1,3,4]
    console.log x.replace /(1.+)s/g, '$1'
C-sharp (12 lines)
public static void BottlesSong(int numberOfBottles)
{
    if (numberOfBottles > 0)
    {
        Console.WriteLine("{0} bottles of beer on the wall", numberOfBottles);
        Console.WriteLine("{0} bottles of beer ", numberOfBottles);
        Console.WriteLine("Take one down, pass it around");
        Console.WriteLine("{0} bottles of beer ", numberOfBottles - 1);
        Console.WriteLine();
        BottlesSong(--numberOfBottles);
    }
}
Crystal (7 lines)
99.downto(1) do |n|
  puts "#{n} bottle#{n > 1 ? "s" : ""} of beer on the wall"
  puts "#{n} bottle#{n > 1 ? "s" : ""} of beer"
  puts "Take one down, pass it around"
  puts "#{n-1} bottle#{n > 2 ? "s" : ""} of beer on the wall\n\n" if n > 1
end
puts "No more bottles of beer on the wall"
D (21 lines)
module bottles;

template BeerSong(int Bottles)
{
	static if (Bottles == 1)
	{
		enum BeerSong = "1 bottle of beer on the wall\n" ~
		"1 bottle of beer\ntake it down, pass it around\n" ~ "
		no more bottles of beer on the wall\n";
	}
	else
	{
		enum BeerSong = Bottles.stringof ~ " bottles of beer on the wall\n" ~
		Bottles.stringof ~ " bottles of beer\ntake it down, pass it around\n" ~
		BeerSong!(Bottles-1);
	}
}

pragma(msg,BeerSong!99);

void main(){}
Dart (61 lines)
main() {
  BeerSong beerSong = BeerSong();
  //pass a 'starting point' and 'end point' as parameters respectively
  String printTheLyrics = beerSong.recite(99, 1).join('\n');
  print(printTheLyrics);
  }

class Song {
  String bottleOnTheWall(int index) {
    String bottleOnTheWallText =
        '$index bottles of beer on the wall, $index bottles of beer,';
    return bottleOnTheWallText;
  }

  String bottleTakenDown(int index) {
    String englishGrammar = (index >= 2) ? 'bottle' : 'bottles';
    String bottleTakenDownText =
        'Take one down and pass it around, ${index - 1} $englishGrammar of beer on the wall.';
    return bottleTakenDownText;
  }
}

class BeerSong extends Song {
  @override
  String bottleOnTheWall(int index) {
    String originalText = super.bottleOnTheWall(index);
    if (index < 2) {
      String bottleOnTheWallText =
          '$index bottle of beer on the wall, $index bottle of beer,';
      return bottleOnTheWallText;
    }
    return originalText;
  }

  @override
  String bottleTakenDown(int index) {
    if (index < 2) {
      String bottleTakenDownText =
          'Take it down and pass it around, no more bottles of beer on the wall.';
      return bottleTakenDownText;
    }
    String originalText = super.bottleTakenDown(index);
    return originalText;
  }

  List<String> recite(int actualBottleOnTheWall, int remainingBottleOnTheWall) {
    List<String> theLyrics = [];
    for (int index = actualBottleOnTheWall;
        index >= remainingBottleOnTheWall;
        index--) {
      String onTheWall = bottleOnTheWall(index);
      String takenDown = bottleTakenDown(index);
      theLyrics.add(onTheWall);
      theLyrics.add(takenDown);
      theLyrics.add('');
    }
    return theLyrics;
  }
}

}
Elixir (16 lines)
defmodule Bottles do
  def run do
    Enum.each 99..1, fn idx ->
      IO.puts "#{idx} bottle#{plural(idx)} of beer on the wall"
      IO.puts "#{idx} bottle#{plural(idx)} of beer"
      IO.puts "Take one down, pass it around"
      IO.puts "#{idx - 1} bottle#{plural(idx-1)} of beer on the wall"
      IO.puts ""
    end
  end

  def plural(1), do: ""
  def plural(num), do: "s"
end

Bottles.run
Elm (27 lines)
module Main exposing (main)

import Html


main =
    List.range 1 100
        |> List.reverse
        |> List.map
            (\n ->
                let
                    nString =
                        String.fromInt n

                    n1String =
                        String.fromInt (n - 1)
                in
                [ nString ++ " bottles of beer on the wall"
                , nString ++ " bottles of beer"
                , "Take one down, pass it around"
                , n1String ++ " bottles of beer on the wall"
                ]
                    |> List.map Html.text
                    |> List.intersperse (Html.br [] [])
                    |> Html.p []
            )
        |> Html.div []
Emacs-Lisp (7 lines)
(let ((i 99))
  (while (> i 0)
    (message "%d bottles of beer on the wall" i)
    (message "%d bottles of beer" i)
    (message "Take one down, pass it around")
    (message "%d bottles of beer on the wall" (1- i))
    (setq i (1- i))))
Erlang (39 lines)
-module(beersong).
-export([sing/0]).
-define(TEMPLATE_0, "~s of beer on the wall, ~s of beer.~nGo to the store and buy some more, 99
bottles of beer on the wall.~n").
-define(TEMPLATE_N, "~s of beer on the wall, ~s of beer.~nTake one down and pass it around, ~s of
beer on the wall.~n~n").

create_verse(0)      -> {0, io_lib:format(?TEMPLATE_0, phrase(0))};
create_verse(Bottle) -> {Bottle, io_lib:format(?TEMPLATE_N, phrase(Bottle))}.

phrase(0)      -> ["No more bottles", "no more bottles"];
phrase(1)      -> ["1 bottle", "1 bottle", "no more bottles"];
phrase(2)      -> ["2 bottles", "2 bottles", "1 bottle"];
phrase(Bottle) -> lists:duplicate(2, integer_to_list(Bottle) ++ " bottles") ++
[integer_to_list(Bottle-1) ++ " bottles"].

bottles() -> lists:reverse(lists:seq(0,99)).

sing() ->
    lists:foreach(fun spawn_singer/1, bottles()),
    sing_verse(99).

spawn_singer(Bottle) ->
    Pid = self(),
    spawn(fun() -> Pid ! create_verse(Bottle) end).

sing_verse(Bottle) ->
    receive
        {_, Verse} when Bottle == 0 ->
            io:format(Verse);
        {N, Verse} when Bottle == N ->
            io:format(Verse),
            sing_verse(Bottle-1)
    after
        3000 ->
            io:format("Verse not received - re-starting singer~n"),
            spawn_singer(Bottle),
            sing_verse(Bottle)
    end.
Euphoria (20 lines)
-- yet another version:

include std/console.e

object stanza = {
"[] bottles of beer on the wall,",
"[] bottles of beer,",
"take one down, and pass it around,"
}

object bottles = 99

loop do
    display(stanza[1],bottles)
    display(stanza[2],bottles)
    display(stanza[3])
    bottles -= 1
    display(stanza[1]&"\n",{bottles})
until bottles = 0
end loop
Fortran (132 lines)
module song_typedefs
   implicit none

   private ! all
   public :: TBottles

   type, abstract :: TContainer
      integer :: quantity
   contains
      ! deferred method i.e. abstract method =  must be overridden in extended type
      procedure(take_one), deferred, pass :: take_one
      procedure(show_quantity), deferred, pass :: show_quantity
   end type TContainer


   abstract interface
      subroutine  take_one(this)
         import TContainer
         implicit none
         class(TContainer) :: this
      end subroutine take_one
      subroutine  show_quantity(this)
         import TContainer
         implicit none
         class(TContainer) :: this
      end subroutine show_quantity
   end interface

   ! extended derived type
   type, extends(TContainer) :: TBottles
   contains
      procedure, pass :: take_one => take_one_bottle
      procedure, pass :: show_quantity => show_bottles
      final :: finalize_bottles
   end type TBottles

 contains

   subroutine  show_bottles(this)
      implicit none
      class(TBottles) :: this
      ! integer :: show_bottles
      character(len=*), parameter :: bw0 = "No more bottles of beer on the wall,"
      character(len=*), parameter :: bwx = "bottles of beer on the wall,"
      character(len=*), parameter :: bw1 = "bottle of beer on the wall,"
      character(len=*), parameter :: bb0 = "no more bottles of beer."
      character(len=*), parameter :: bbx = "bottles of beer."
      character(len=*), parameter :: bb1 = "bottle of beer."
      character(len=*), parameter :: fmtxdd = "(I2,1X,A28,1X,I2,1X,A16)"
      character(len=*), parameter :: fmtxd = "(I1,1X,A28,1X,I1,1X,A16)"
      character(len=*), parameter :: fmt1 = "(I1,1X,A27,1X,I1,1X,A15)"
      character(len=*), parameter :: fmt0 = "(A36,1X,A24)"

      select case (this % quantity)
       case (10:)
         write(*,fmtxdd) this % quantity, bwx, this % quantity, bbx
       case (2:9)
         write(*,fmtxd) this % quantity, bwx, this % quantity, bbx
       case (1)
         write(*,fmt1) this % quantity, bw1, this % quantity, bb1
       case (0)
         write(*,*)
         write(*,fmt0) bw0, bb0
       case default
         write(*,*)"Warning!  Number of bottles exception, error 42. STOP"
         stop
      end select
      !    show_bottles = this % quantity
   end subroutine show_bottles

   subroutine  take_one_bottle(this) ! bind(c, name='take_one_bottle')
      implicit none
      class(TBottles) :: this
      ! integer :: take_one_bottle
      character(len=*), parameter :: t1 = "Take one down and pass it around,"
      character(len=*), parameter :: remx = "bottles of beer on the wall."
      character(len=*), parameter :: rem1 = "bottle of beer on the wall."
      character(len=*), parameter :: rem0 = "no more bottles of beer on the wall."
      character(len=*), parameter :: fmtx = "(A33,1X,I2,1X,A28)"
      character(len=*), parameter :: fmt1 = "(A33,1X,I2,1X,A27)"
      character(len=*), parameter :: fmt0 = "(A33,1X,A36)"

      this % quantity = this % quantity -1

      select case (this%quantity)
       case (2:)
         write(*,fmtx) t1, this%quantity, remx
       case (1)
         write(*,fmt1) t1, this%quantity, rem1
       case (0)
         write(*,fmt0) t1, rem0
       case (-1)
         write(*,'(A66)') "Go to the store and buy some more, 99 bottles of beer on the wall."
       case default
         write(*,*)"Warning!  Number of bottles exception, error 42. STOP"
         stop
      end select

   end subroutine take_one_bottle

   subroutine  finalize_bottles(bottles)
      implicit none
      type(TBottles) :: bottles
   ! here can be more code
   end subroutine finalize_bottles

end module song_typedefs

!-----------------------------------------------------------------------
!Main program
!-----------------------------------------------------------------------
program    bottles_song
   use song_typedefs
   implicit none
   integer, parameter :: MAGIC_NUMBER = 99
   type(TBottles), target :: BTLS

   BTLS = TBottles(MAGIC_NUMBER)

   call make_song(BTLS)

 contains

   subroutine make_song(bottles)
      type(TBottles) :: bottles
      do while(bottles%quantity >= 0)
         call bottles%show_quantity()
         call bottles%take_one()
      enddo
   end subroutine make_song

end program bottles_song
F-Sharp (12 lines)
#light
let rec bottles n =
    let (before, after) = match n with
                          | 1 -> ("bottle", "bottles")
                          | 2 -> ("bottles", "bottle")
                          | n -> ("bottles", "bottles")
    printfn "%d %s of beer on the wall" n before
    printfn "%d %s of beer" n before
    printfn "Take one down, pass it around"
    printfn "%d %s of beer on the wall\n" (n - 1) after
    if n > 1 then
        bottles (n - 1)
Go (80 lines)
package main

import (
    "fmt"
    "math/rand"
    "strings"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())
    for i := 99; i > 0; i-- {
        fmt.Printf("%s %s %s\n",
            slur(numberName(i), i),
            pluralizeFirst(slur("bottle of", i), i),
            slur("beer on the wall", i))
        fmt.Printf("%s %s %s\n",
            slur(numberName(i), i),
            pluralizeFirst(slur("bottle of", i), i),
            slur("beer", i))
        fmt.Printf("%s %s %s\n",
            slur("take one", i),
            slur("down", i),
            slur("pass it around", i))
        fmt.Printf("%s %s %s\n",
            slur(numberName(i-1), i),
            pluralizeFirst(slur("bottle of", i), i-1),
            slur("beer on the wall", i))
    }
}

// adapted from Number names task
func numberName(n int) string {
    switch {
    case n < 0:
    case n < 20:
        return small[n]
    case n < 100:
        t := tens[n/10]
        s := n % 10
        if s > 0 {
            t += " " + small[s]
        }
        return t
    }
    return ""
}

var small = []string{"no", "one", "two", "three", "four", "five", "six",
    "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen",
    "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}
var tens = []string{"ones", "ten", "twenty", "thirty", "forty",
    "fifty", "sixty", "seventy", "eighty", "ninety"}

// pluralize first word of s by adding an s, but only if n is not 1.
func pluralizeFirst(s string, n int) string {
    if n == 1 {
        return s
    }
    w := strings.Fields(s)
    w[0] += "s"
    return strings.Join(w, " ")
}

// p is string to slur, d is drunkenness, from 0 to 99
func slur(p string, d int) string {
    // shuffle only interior letters
    a := []byte(p[1 : len(p)-1])
    // adapted from Knuth shuffle task.
    // shuffle letters with probability d/100.
    for i := len(a) - 1; i >= 1; i-- {
        if rand.Intn(100) >= d {
            j := rand.Intn(i + 1)
            a[i], a[j] = a[j], a[i]
        }
    }
    // condense spaces
    w := strings.Fields(p[:1] + string(a) + p[len(p)-1:])
    return strings.Join(w, " ")
}
Groovy (10 lines)
def bottles = { "${it==0 ? 'No more' : it} bottle${it==1 ? '' : 's' }" }

99.downto(1) { i ->
    print """
${bottles(i)} of beer on the wall
${bottles(i)} of beer
Take one down, pass it around
${bottles(i-1)} of beer on the wall
"""
}
Haskell (28 lines)
{-# LANGUAGE TemplateHaskell #-}
-- build with "ghc --make beer.hs"
module Main where
import Language.Haskell.TH
import Control.Monad.Writer

-- This is calculated at compile time, and is equivalent to
-- songString = "99 bottles of beer on the wall\n99 bottles..."
songString =
    $(let
         sing = tell -- we can't sing very well...

         someBottles 1 = "1 bottle of beer "
         someBottles n = show n ++ " bottles of beer "

         bottlesOfBeer n = (someBottles n ++)

         verse n = do
           sing $ n `bottlesOfBeer` "on the wall\n"
           sing $ n `bottlesOfBeer` "\n"
           sing $ "Take one down, pass it around\n"
           sing $ (n - 1) `bottlesOfBeer` "on the wall\n\n"

         song = execWriter $ mapM_ verse [99,98..1]

      in return $ LitE $ StringL $ song)

main = putStr songString
Java (41 lines)
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;

public class Beer extends JFrame {
    private int x;
    private JTextArea text;

    public static void main(String[] args) {
        new Beer().setVisible(true);
    }

    public Beer() {
        x = 99;

        JButton take = new JButton("Take one down, pass it around");
        take.addActionListener(this::onTakeClick);

        text = new JTextArea(4, 30);
        text.setText(x + " bottles of beer on the wall\n" + x + " bottles of beer");
        text.setEditable(false);

        setLayout(new BorderLayout());
        add(text, BorderLayout.CENTER);
        add(take, BorderLayout.PAGE_END);
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    }

    private void onTakeClick(ActionEvent event) {
        JOptionPane.showMessageDialog(null, --x + " bottles of beer on the wall");
        text.setText(x + " bottles of beer on the wall\n" + x + " bottles of beer");
        if (x == 0) {
            dispose();
        }
    }
}
JavaScript (25 lines)
function Bottles(count) {
  this.count = count || 99;
}

Bottles.prototype.take = function() {
  var verse = [
    this.count + " bottles of beer on the wall,",
    this.count + " bottles of beer!",
    "Take one down, pass it around",
    (this.count - 1) + " bottles of beer on the wall!"
  ].join("\n");

  console.log(verse);

  this.count--;
};

Bottles.prototype.sing = function() {
  while (this.count) {
    this.take();
  }
};

var bar = new Bottles(99);
bar.sing();
Jq (17 lines)
$ jq -n -r -f 99_bottles.jq
...

2 bottles of beer on the wall
2 bottles of beer
Take one down, pass it around
2 bottles of beer on the wall

1 bottles of beer on the wall
1 bottles of beer
Take one down, pass it around
1 bottles of beer on the wall

0 bottles of beer on the wall
0 bottles of beer
Take one down, pass it around
0 bottles of beer on the wall
Julia (12 lines)
bottles(n) = n==0 ? "No more bottles" :
             n==1 ? "1 bottle" :
             "$n bottles"

for n = 99:-1:1
    println("""
        $(bottles(n)) of beer on the wall
        $(bottles(n)) of beer
        Take one down, pass it around
        $(bottles(n-1)) of beer on the wall
    """)
end
Kotlin (8 lines)
fun main(args: Array<String>) {
    for (i in 99.downTo(1)) {
        println("$i bottles of beer on the wall")
        println("$i bottles of beer")
        println("Take one down, pass it around")
    }
    println("No more bottles of beer on the wall!")
}
Lua (10 lines)
verse = [[%i bottle%s of beer on the wall
%i bottle%s of beer
Take one down, pass it around
%i bottle%s of beer on the wall
]]
function suffix(i) return i ~= 1 and 's' or '' end

for i = 99, 1, -1 do
    print(verse:format(i, suffix(i), i, suffix(i), i-1, suffix(i-1)))
end
MIPS-Assembly (77 lines)
##################################
# 99 bottles of beer on the wall #
# MIPS Assembly targeting MARS   #
# By Keith Stellyes              #
# August 24, 2016                #
##################################

#It is simple, a loop that goes as follows:

#if accumulator is not 1:
#PRINT INTEGER: accumulator
#PRINT lyrica
#PRINT INTEGER: accumulator
#PRINT lyricb
#PRINT INTEGER: accumulator
#PRINT lyricc
#DECREMENT accumulator

#else:
#PRINT FINAL LYRICS

.data
	lyrica: .asciiz " bottles of beer on the wall, "
	lyricb: " bottles of beer.\nTake one down and pass it around, "
	lyricc: " bottles of beer on the wall. \n\n"
	
	#normally, I don't like going past 80 columns, but that was done here.
	# there's an argument to be had for breaking this up. I chose not to
	# for simpler instructions.
	final_lyrics: "1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall."

.text	
	#lw $a0,accumulator #load address of accumulator into $a0 (or is it getting val?)
	li $a1,99 #set the inital value of the counter to 99
	
loop:	
	###99
	li $v0, 1 #specify print integer system service
	move $a0,$a1
	syscall #print that integer
	
	### bottles of beer on the wall,
	la $a0,lyrica
	li $v0,4
	syscall
	
	###99
	li $v0, 1 #specify print integer system service
	move $a0,$a1
	syscall #print that integer	
	
	### bottles of beer.\n Take one down and pass it around,
	la $a0,lyricb
	li $v0,4
	syscall
	
	###99
	li $v0, 1 #specify print integer system service
	move $a0,$a1
	syscall #print that integer
	
	### "bottles of beer on the wall. \n\n"
	la $a0,lyricc
	li $v0,4
	syscall
	
	#decrement counter, if at 1, print the final and exit.
	subi $a1,$a1,1
	bne $a1,1,loop

### PRINT FINAL LYRIC, THEN TERMINATE.
final:  la $a0,final_lyrics
	li $v0,4
	syscall

	li $v0,10
	syscall
Nim (21 lines)
from strutils import format

for i in countdown(99, 1):
  case i
  of 3..99:
    echo format("""$1 bottles of beer on the wall
$1 bottles of beer
Take one down, pass it around
$2 bottles of beer on the wall""", i, i-1)
  of 2:
    echo format("""$1 bottles of beer on the wall
$1 bottles of beer
Take one down, pass it around
$2 bottle of beer on the wall""", i, i-1)
  of 1:
    echo format("""$1 bottle of beer on the wall
$1 bottle of beer
Take one down, pass it around
No more bottles of beer on the wall""", i)
  else:
    discard
Objective-C (17 lines)
#import <Foundation/Foundation.h>

int main()
{
    @autoreleasepool {
        int bottles = 99;
        do
        {
            NSLog(@"%i bottles of beer on the wall\n", bottles);
            NSLog(@"%i bottles of beer\n", bottles);
            NSLog(@"Take one down, pass it around\n");
            NSLog(@"%i bottles of beer on the wall\n\n", --bottles);
        } while (bottles > 0);
	
    }
    return 0;
}
OCaml (6 lines)
for n = 99 downto 1 do
  Printf.printf "%d bottles of beer on the wall\n" n;
  Printf.printf "%d bottles of beer\n" n;
  Printf.printf "Take one down, pass it around\n";
  Printf.printf "%d bottles of beer on the wall\n\n" (pred n);
done
Perl (18 lines)
#!/usr/bin/perl -w

my $verse = <<"VERSE";
100 bottles of beer on the wall,
100 bottles of beer!
Take one down, pass it around!
99 bottles of beer on the wall!

VERSE

{
    $verse =~ s/(\d+)/$1-1/ge;
    $verse =~ s/\b1 bottles/1 bottle/g;
    my $done = $verse =~ s/\b0 bottle/No bottles/g; # if we make this replacement, we're also done.

    print $verse;
    redo unless $done;
}
Smalltalk (15 lines)
Smalltalk at: #sr put: 0 ; at: #s put: 0 !
sr := Dictionary new.
sr at: 0 put: ' bottle' ;
   at: 1 put: ' bottles' ;
   at: 2 put: ' of beer' ;
   at: 3 put: ' on the wall' ;
   at: 4 put: 'Take one down, pass it around' !
99 to: 0 by: -1 do: [:v | v print.
         ( v == 1 ) ifTrue: [ s := 0. ]
	            ifFalse: [ s := 1. ].
	 Transcript show: (sr at:s) ; show: (sr at:2) ; show: (sr at:3) ; cr.
	            v print.
	 Transcript show: (sr at:s) ; show: (sr at:2) ; cr.
		    (v ~~ 0) ifTrue: [ Transcript show: (sr at:4) ; cr. ].
   ].
PHP (16 lines)
<?php

$bottles = 99;

while ($bottles > 0) {
	printf(ngettext('%d bottle', '%d bottles', $bottles) . " of beer on the wall\n", $bottles);		//X bottles of beer on the wall
	printf(ngettext('%d bottle', '%d bottles', $bottles) . " of beer\n", $bottles);				//X bottles of beer
	printf("Take one down, pass it around\n");										//Take one down, pass it around

	$bottles--;

	if ($bottles > 0) {
		printf(ngettext('%d bottle', '%d bottles', $bottles) . " of beer on the wall\n\n", $bottles);	//X bottles of beer on the wall
	}
}
printf('No more bottles of beer on the wall');											//No more bottles of beer on the wall
Python (25 lines)
VERSE = '''\
{n} bottle{s} of beer on the wall
{n} bottle{s} of beer
Take one down, pass it around
{n_minus_1} bottle{s2} of beer on the wall

'''


for n in range(99, 0, -1):
    if n == 1:
        n_minus_1 = 'No more'
        s = ''
        s2 = 's'
    elif n == 2:
        n_minus_1 = n - 1;
        s = 's'
        s2 = ''
    else:
        n_minus_1 = n - 1;
        s = 's'
        s2 = 's'


    print(VERSE.format(n=n, s=s, s2=s2, n_minus_1=n_minus_1))
R (16 lines)
#a naive function to sing for N bottles of beer...

song = function(bottles){

  for(i in bottles:1){ #for every integer bottles, bottles-1 ... 1

    cat(bottles," bottles of beer on the wall \n",bottles," bottles of beer \nTake one down, pass it around \n",
        bottles-1, " bottles of beer on the wall \n"," \n" ,sep="")       #join and print the text (\n means new line)

        bottles = bottles - 1 #take one down...

  }

}

song(99)#play the song by calling the function
Racket (8 lines)
#lang racket
(define (sing bottles)
  (define (plural n) (~a n " bottle" (if (= n 1) "" "s")))
  (printf "~a of beer on the wall\n~a of beer\n~
           Take one down, pass it around\n~a of beer on the wall\n\n"
          (plural bottles) (plural bottles) (plural (sub1 bottles)))
  (unless (= 1 bottles) (sing (sub1 bottles))))
(sing 99)
Raku (18 lines)
for 99...1 -> $bottles {
    sing $bottles, :wall;
    sing $bottles;
    say  "Take one down, pass it around";
    sing $bottles - 1, :wall;
    say  "";
}

#| Prints a verse about a certain number of beers, possibly on a wall.
sub sing(
    Int $number, #= Number of bottles of beer.
    Bool :$wall, #= Mention that the beers are on a wall?
) {
    my $quantity = $number == 0 ?? "No more"      !! $number;
    my $plural   = $number == 1 ?? ""             !! "s";
    my $location = $wall        ?? " on the wall" !! "";
    say "$quantity bottle$plural of beer$location"
}
Red (21 lines)
w: 99
while [w][
	print [
		reform [
			w x: either 1 < w ["bottles"] ["bottle"] y: "of beer" z: "on the wall" ","
			w x y
		]
	]
	w: w - 1
	if w = 1 [remove at x length? x]
	print [
		"take one down pass it around, "
		either 0 < w [
			reform [w x y z]
		][
			w: false reform [
				"no more bottles " y rejoin [z "."]
			]
		]
	]
]
Ruby (14 lines)
def bottles(beer, wall = false)
  "#{beer>0 ? beer : "no more"} bottle#{"s" if beer!=1} of beer#{" on the wall" if wall}"
end

99.downto(0) do |remaining|
  puts "#{bottles(remaining,true).capitalize}, #{bottles(remaining)}."
  if remaining==0
    print "Go to the store and buy some more"
    remaining=100
  else
    print "Take one down, pass it around"
  end
  puts ", #{bottles(remaining-1,true)}.\n\n"
end
Rust (18 lines)
fn main() {
	for n in (0..100).rev() {
		match n {
			0 => {
				println!("No more bottles of beer on the wall, no more bottles of beer.");
				println!("Go to the store and buy some more, 99 bottles of beer on the wall.");
			},
			1 => {
				println!("1 bottle of beer on the wall, 1 bottle of beer.");
				println!("Take one down and pass it around, no more bottles of beer on the wall.\n");
			},
			_ => {
				println!("{0:?} bottles of beer on the wall, {0:?} bottles of beer.", n);
				println!("Take one down and pass it around, {} bottles of beer on the wall.\n", n-1);
			},
		}
	}
}
Scheme (12 lines)
(define (sing)
 (define (sing-to-x n)
  (if (> n -1)
    (begin
        (display n)
        (display "bottles of beer on the wall")
        (newline)
        (display "Take one down, pass it around")
        (newline)
        (sing-to-x (- n 1)))
    (display "would you wanna me to sing it again?")))
 (sing-to-x 99))
Standard-ML (7 lines)
fun bottles 0 = ()
  | bottles x = ( print (Int.toString x ^ " bottles of beer on the wall\n");
                  print (Int.toString x ^ " bottles of beer\n");
                  print "Take one down, pass it around\n";
                  print (Int.toString (x-1) ^ " bottles of beer on the wall\n");
                  bottles (x-1)
                )
Swift (5 lines)
for i in (1...99).reversed() {
	print("\(i) bottles of beer on the wall, \(i) bottles of beer.")
	let next = i == 1 ? "no" : (i-1).description
	print("Take one down and pass it around, \(next) bottles of beer on the wall.")
}
TypeScript (18 lines)
function beerSong(){
    function nbottles(howMany:number){
        return `${howMany?howMany:'no'} bottle${howMany!=1?'s':''}`;
    }
    let song=[];
    let beer = 99;
    while (beer > 0) {
        song.push(`
            ${nbottles(beer)} of beer on the wall,
            ${nbottles(beer)} of beer!
            Take one down, pass it around
            ${nbottles(--beer)} of beer on the wall
        `);
    }
    return song.join('');
}

console.log(beerSong());
Wren (6 lines)
for (i in 99...0) {
    System.print("%(i) bottles of beer on the wall,")
    System.print("%(i) bottles of beer,")
    System.print("Take one down, pass it around,")
    System.print("%(i - 1) bottles of beer on the wall.\n")
}
Zig (22 lines)
const print = @import("std").debug.print;
pub fn main() void {
  var i: u8 = 99;
  while (i > 2) : (i-= 1) {
  print(
    \\{} bottles of beer on the wall, {} bottles of beer.
    \\Take one down and pass it around, {} bottles of beer on the wall.
    \\
    \\
   , .{i, i, i-1});
  }
  print(
    \\2 bottles of beer on the wall, 2 bottles of beer.
    \\Take one down and pass it around, 1 bottle of beer on the wall.
    \\
    \\1 bottle of beer on the wall, 1 bottle of beer.
    \\Take one down and pass it around, no more bottles of beer on the wall.
    \\
    \\No more bottles of beer on the wall, no more bottles of beer.
    \\Go to the store and buy some more, 99 bottles of beer on the wall.
  , .{});
}

About

About the ys-vs-rc Project

YAMLScript is a relatively new programming language and this project is intended to show how things are done with it compared to some other programming languages.

When comparing these programs, keep in mind that they were all written by different people and they are not necessarily exactly equivalent.

For example, most of the YAMLScript programs are written to be runnable with:

$ ys task-name.ys

which prints the intended results.

This is not necessarily the case for the solutions in other languages. Many solutions just show the functions necessary to complete the task.

Also the line counts are not meant ot imply any superiority of a solution.

Contributing

A great way to contribute to YAMLScript is to add more YAMLScript task solutions to Rosetta Code.

You can use this program to compare your solutions with others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment