Execute HQ9+

From Rosetta Code
Revision as of 01:29, 1 February 2011 by Thundergnat (talk | contribs) (→‎{{header|Perl 6}}: minor tweak)
Task
Execute HQ9+
You are encouraged to solve this task according to the task description, using any language you may know.

Implement a HQ9+ interpreter or compiler for Rosetta Code.

Ada

see Execute HQ9+/Ada

AutoHotkey

<lang AutoHotkey>; http://www.autohotkey.com/forum/viewtopic.php?p=356268#356268

testCode := "hq9+HqQ+Qq"

MsgBox % RunHQ9Plus(testCode)

---------------------------------

RunHQ9Plus(input) {

 Loop, Parse, input
   If ( A_LoopField = "+" )
     acc++
   Else If ( A_LoopField = "H" )
     output .= "Hello, world!`n"
   Else If ( A_LoopField = "Q" )
     output .= input "`n"
   Else If ( A_LoopField = "9" )
     Loop, 99
     {
       ; following 4 lines could be only 1 long line
       output .= (99+1-A_Index) " bottles of beer on the wall`n"
       output .= (99+1-A_Index) " bottles of beer`n"
       output .= "Take one down, pass it around`n"
       output .= (99-A_Index) " bottles of beer on the wall`n`n"
     }
 Return output

}</lang>

C

<lang c>void runCode(char *code) {

   int c_len = strlen(code);
   int i, accumulator, bottles;
   for(i=0;i<c_len;i++)
   {
       switch(code[i])
       {
           case 'Q':
               printf("%s\n", code);
               break;
           case 'H':
               printf("Hello, world!\n");
               break;
           case '9':
               //Nice bottles song alg. from RC :)
               bottles = 99;
               do {
                   printf("%d bottles of beer on the wall\n", bottles);
                   printf("%d bottles of beer\n", bottles);
                   printf("Take one down, pass it around\n");
                   printf("%d bottles of beer on the wall\n\n", --bottles);
               } while( bottles > 0 );
               break;
           case '+':
               //Am I the only one finding this one weird? :o
               accumulator++;
               break;
       }
   }

};</lang>

C++

Basically the same as the C example, although this has been C++'ified with strings and streams. <lang cpp>void runCode(string code) {

   int c_len = code.length();
   int accumulator, bottles;
   for(int i=0;i<c_len;i++)
   {
       switch(code[i])
       {
           case 'Q':
               cout << code << endl;
               break;
           case 'H':
               cout << "Hello, world!" << endl;
               break;
           case '9':
               //Nice bottles song alg. from RC :)
               bottles = 99;
               do {
                   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" << endl << endl;
               } while( bottles > 0 );
               break;
           case '+':
               //Am I the only one finding this one weird? :o
               accumulator++;
               break;
       }
   }

};</lang>

C#

<lang csharp> using System; using System.Collections.Generic; using System.Linq;

class Program {

   static void RunCode(string code)
   {
       int accumulator = 0;
       var opcodes = new Dictionary<char, Action>
       {
           {'H', () => Console.WriteLine("Hello, World!"))},
           {'Q', () => Console.WriteLine(code) },
           {'9', () => Console.WriteLine(Enumerable.Range(1,100).Reverse().Select(n => string.Format("{0} bottles of beer on the wall\n{0} bottles of beer\nTake one down, pass it around\n{1} bottles of beer on the wall\n", n, n-1)).Aggregate((a,b) => a + "\n" + b))},
           {'+', () => accumulator++ }
       }
       foreach(var c in code)
           opcodes[c]();
   }

} </lang>

Common Lisp

See RCHQ9+/Common Lisp.

E

See RCHQ9+/E.

Forth

<lang forth>variable accumulator

H cr ." Hello, world!" ;
Q cr 2dup type ;
9 99 verses ; \ http://rosettacode.org/wiki/99_Bottles_of_Beer#Forth
+ 1 accumulator +! ;
hq9+ ( "code" -- )
 parse-word 2dup bounds ?do
   i 1 [ get-current literal ] search-wordlist
   if execute else true abort" invalid HQ9+ instruction"
 then loop 2drop ;</lang>

Haskell

See RCHQ9+/Haskell.

Inform 7

<lang inform7>HQ9+ is a room.

After reading a command: interpret the player's command; reject the player's command.

To interpret (code - indexed text): let accumulator be 0; repeat with N running from 1 to the number of characters in code: let C be character number N in code in upper case; if C is "H": say "Hello, world!"; otherwise if C is "Q": say "[code][line break]"; otherwise if C is "9": repeat with iteration running from 1 to 99: let N be 100 - iteration; say "[N] bottle[s] of beer on the wall[line break]"; say "[N] bottle[s] of beer[line break]"; say "Take one down, pass it around[line break]"; say "[N - 1] bottle[s] of beer on the wall[paragraph break]"; otherwise if C is "+": increase accumulator by 1.</lang>

J

From 99 Bottles of Beer <lang J>bob =: ": , ' bottle' , (1 = ]) }. 's of beer'"_ bobw=: bob , ' on the wall'"_ beer=: bobw , ', ' , bob , '; take one down and pass it around, ' , bobw@<:</lang>

The rest of the interpreter: <lang J>H=: smoutput bind 'Hello, world!' Q=: smoutput @ [ hq9=: smoutput @: (beer"0) bind (1+i.-99) hqp=: (A=:1)1 :'0 0$A=:A+m[y'@]

hq9p=: H`H`Q`Q`hq9`hqp@.('HhQq9+' i. ])"_ 0~</lang>

Example use:

<lang J> hq9p 'hqQQq' Hello, world! hqQQq hqQQq hqQQq hqQQq</lang>

Java

See RCHQ9+/Java.

JavaScript

The function below executes a HQ9+ program and returns the program output as a string. <lang javascript>function hq9plus(code) {

 var out = ;
 var acc = 0;
 
 for (var i=0; i<code.length; i++) {
   switch (code.charAt(i)) {
     case 'H': out += "hello, world\n"; break;
     case 'Q': out += code + "\n"; break;
     case '9':
       for (var j=99; j>1; j--) {
         out += j + " bottles of beer on the wall, " + j + " bottles of beer.\n";
         out += "Take one down and pass it around, " + (j-1) + " bottles of beer.\n\n";
       }
       out += "1 bottle of beer on the wall, 1 bottle of beer.\n" +
           "Take one down and pass it around, no more bottles of beer on the wall.\n\n" +
           "No more bottles of beer on the wall, no more bottles of beer.\n" +
           "Go to the store and buy some more, 99 bottles of beer on the wall.\n";
       break;
     case '+': acc++; break;
   }
 }
 return out;

}</lang>

Liberty BASIC

<lang lb>'Try this hq9+ program - "hq9+HqQ+Qq" Prompt "Please input your hq9+ program."; code$ Print hq9plus$(code$) End

Function hq9plus$(code$)

   For i = 1 to Len(code$)
       Select Case
           Case Upper$(Mid$(code$, i, 1)) = "H"
               hq9plus$ = hq9plus$ + "Hello, world!"
           Case Upper$(Mid$(code$, i, 1)) = "Q"
               hq9plus$ = hq9plus$ + code$
           Case Mid$(code$, i, 1) = "9"
               For bottles = 99 To 1 Step -1
                    hq9plus$ = hq9plus$ + str$(bottles) + " bottle"
                    If (bottles > 1) Then hq9plus$ = hq9plus$ + "s"
                    hq9plus$ = hq9plus$ + " of beer on the wall, " + str$(bottles) + " bottle"
                    If (bottles > 1) Then hq9plus$ = hq9plus$ + "s"
                    hq9plus$ = hq9plus$ + " of beer,"  + chr$(13) + chr$(10) + "Take one down, pass it around, " + str$(bottles - 1) + " bottle"
                    If (bottles > 2) Or (bottles = 1) Then hq9plus$ = hq9plus$ + "s"
                    hq9plus$ = hq9plus$ + " of beer on the wall." + chr$(13) + chr$(10)
               Next bottles
               hq9plus$ = hq9plus$ + "No more bottles of beer on the wall, no more bottles of beer." _
                                   + chr$(13) + chr$(10) + "Go to the store and buy some more, 99 bottles of beer on the wall."
           Case Mid$(code$, i, 1) = "+"
               accumulator = (accumulator + 1)
       End Select
       If Mid$(code$, i, 1) <> "+" Then
           hq9plus$ = hq9plus$ + chr$(13) + chr$(10)
       End If
   Next i
   hq9plus$ = Left$(hq9plus$, (Len(hq9plus$) - 2))

End Function</lang>

Perl 6

99 bottles code adapted from here. [1]

<lang perl6>class HQ9Interpreter {

   has @!code;
   has $!pointer;
   has $!accumulator;

   method new (Str $code) {
       HQ9Interpreter.bless(*,code => $code.comb);
   }

   method run {
       $!accumulator = 0;
       $!pointer = 0;
       while $!pointer < @!code {
           given @!code[$!pointer].lc {
               when 'h' { say "Hello world!" }
               when 'q' { say @!code }
               when '9' { 
                          my $b = 99;
                          sub r { "$b bottle{$b-1??"s"!!""} of beer" };
                          my $w = "on the wall";
                          while $b {  
                              .say for "&r() $w,","&r()!"; 
                              --$b; 
                              .say for "Take one down, pass it around,","&r() $w!",; 
                          }
               }
               when '+' { $!accumulator++ }
               default { say "Syntax error: Unknown command \"{@!code[$!pointer]}\"" and exit }
           }

$!pointer++;

       }
   }

}

my $code = "hHq+++QqJ"; my $hq9 = HQ9Interpreter.new($code); $hq9.run;</lang>

Output:

Hello world!
Hello world!
hHq+++QqJ
hHq+++QqJ
hHq+++QqJ
Syntax error: Unknown command "J"

PicoLisp

<lang PicoLisp>(de hq9+ (Code)

  (let Accu 0
     (for C (chop Code)
        (case C
           ("H" (prinl "Hello, world"))
           ("Q" (prinl Code))
           ("9"
              (for (N 99 (gt0 N))
                 (prinl N " bottles of beer on the wall")
                 (prinl N " bottles of beer")
                 (prinl "Take one down, pass it around")
                 (prinl (dec 'N) " bottles of beer on the wall")
                 (prinl) ) )
           ("+" (inc 'Accu)) ) )
     Accu ) )</lang>

PureBasic

<lang PureBasic>Procedure hq9plus(code.s)

 Protected accumulator, i, bottles
 For i = 1 To Len(code)
   Select Mid(code, i, 1)
     Case "h", "H"
       PrintN("Hello, world!")
     Case "q", "Q"
       PrintN(code)
     Case "9"
       bottles = 99
       While bottles
         PrintN(Str(bottles) + " bottles of beer on the wall, " + Str(bottles) + " bottles of beer,")
         bottles - 1
         PrintN("Take one down, pass it around, " + Str(bottles) + " bottles of beer on the wall.")
       Wend
     Case "+"
       accumulator + 1
   EndSelect
 Next i

EndProcedure

If OpenConsole()

 Define testCode.s = "hq9+HqQ+Qq"
 hq9plus(testCode)
 
 Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
 CloseConsole()

EndIf</lang>

Python

See RCHQ9+/Python.

Ruby

See RCHQ9+/Ruby.

Scala

<lang Scala>def hq9plus(code: String) : String = {

   var out = ""
   var acc = 0
   def bottle(num: Int) : Unit = {
       if (num > 1) {
           out += num + " bottles of beer on the wall, " + num + " bottles of beer.\n"
           out += "Take one down and pass it around, " + (num - 1) + " bottle"
           if (num > 2) out += "s"
           out += " of beer.\n\n"
           bottle(num - 1)
       }
       else {
           out += "1 bottle of beer on the wall, 1 bottle of beer.\n" +
               "Take one down and pass it around, no more bottles of beer on the wall.\n\n" +
               "No more bottles of beer on the wall, no more bottles of beer.\n" +
               "Go to the store and buy some more, 99 bottles of beer on the wall.\n"
       }
   }
   def handle(char: Char) = char match {
       case 'H' => out += "Hello world!\n"
       case 'Q' => out += code + "\n"
       case '+' => acc += 1
       case '9' => bottle(99)
   }
   code.toList foreach handle
   out

}

println(hq9plus("HQ9+")) </lang>

Tcl

See RCHQ9+/Tcl.

Ursala

See RCHQ9+/Ursala.