Tạo trình thông dịch HQ9 +


31

Mục tiêu của mã golf này là tạo ra một trình thông dịch cho ngôn ngữ lập trình HQ9 +
Có 4 lệnh trong ngôn ngữ lập trình này:

  • H - in "Xin chào, thế giới!"
  • Q - in mã nguồn của chương trình
  • 9 - in lời bài hát "99 chai bia"
  • + - tăng bộ tích lũy

Những quy định:

  1. Vì bộ tích lũy không được xác định, bạn có thể bỏ qua lệnh +
  2. Chương trình của bạn sẽ nhắc nhập (đầu vào này sẽ là mã nguồn) hoặc mã nguồn được đọc từ một tệp
  3. Bạn không được phép đặt lời bài hát "99 chai bia" vào một tệp và đọc văn bản từ tệp
  4. Bạn không được phép sử dụng thuật toán nén như GZip hoặc BZip để nén văn bản bài hát: bạn phải tạo thuật toán nén của riêng mình. Đây không phải là một thuật toán phức tạp, nhưng hãy cố gắng nén văn bản càng nhiều càng tốt (hãy nhớ: đây là một môn đánh gôn, mã có ít byte nhất sẽ thắng)
  5. Nếu mã nguồn chứa char không phải là H , Q , 9 hoặc + , thì hãy xuất "Mã nguồn chứa các ký tự không hợp lệ" trước khi chạy bất kỳ lệnh nào! Điều này có nghĩa là, nếu mã nguồn là H1ví dụ, thì không xuất ra Hello, world!trước khi bạn xuất Source code contains invalid characters. Không, đầu ra ngay lập tứcSource code contains invalid characters
  6. Nếu trình thông dịch của bạn chấp nhận cả ký tự viết hoa và viết thường, thì bạn nhận được -8 cho số ký tự của bạn

Chúc may mắn!


3
Quy tắc 4 không có ý nghĩa gì tại "tại sao anh ta lại cấm điều đó?!" cấp độ; quy tắc 5 không có ý nghĩa gì với "ý anh ta là gì?!" cấp độ.
Peter Taylor

4
Làm thế nào để quy tắc 5 không có ý nghĩa?
Mike C

Tôi nghĩ sẽ tốt hơn nếu chỉ yêu cầu nó chỉ sử dụng chữ hoa, thay vì tự ý nói rằng bạn nhận được 8 ký tự miễn phí nếu nó chấp nhận. 8 có thể hoặc không thể bao gồm nó tùy thuộc vào ngôn ngữ.
Mike C

10
Quy tắc 5 không có ý nghĩa vì nó phá vỡ thông số HQ9 +.
gian hàng

2
Một thông dịch viên trong HQ9 + sẽ tự động giành chiến thắng.
TheNumberOne

Câu trả lời:


16

APL (Dyalog) (326 - 8 = 318)

Dán nó trong một cửa sổ soạn thảo và gọi H. Đầu vào được lấy từ bàn phím.

H
⎕←'Source code contains invalid characters'/⍨~∧/'HhQq9+'∊⍨V←⍞
B←' of beer'
W←' on the wall'
L←⎕TC[2]
Z←{k←' bottle','s'/⍨⍵≠1⋄⍵<0:'99',k⋄⍵=0:'No',k⋄k,⍨⍕⍵}
{⍵∊'Hh':⎕←'Hello, world!'
⍵∊'Qq':⎕←V
⍵∊'9':{⎕←G,K,(G←Z⍵),B,L,(⊃'Go to the store and buy some more' 'Take one down and pass it around'[1+×⍵]),L,(Z⍵-1),K←B,W,L}¨1-⍨⌽⍳100}¨V

6

Toán học, 349 346 341 ký tự

h = If[StringMatchQ[#, ("H" | "Q" | "9" | "+") ...], 
   b = If[# > 0, ToString@#, "No"] <> " bottle" <> 
      If[# == 1, "", "s"] <> " of beer" &; 
   w = b@# <> " on the wall" &; 
   Print /@ 
    StringCases[#, {"H" -> "Hello, world!", "Q" -> #, 
      "9" -> "" <> 
        Table[w@n <> ",\n" <> b@n <> 
          ".\ntake one down, pass it around,\n" <> w[n - 1] <> 
          If[n == 1, ".", ".\n\n"], {n, 99, 1, -1}]}];, 
   "Source code contains invalid characters"] &

Rất ấn tượng nhưng dường như có một số lỗi nhỏ.'h ["Q"] xuất ra "Q". h ["9"] hoạt động, nhưng h [9] xuất toàn bộ chương trình (tôi không hiểu làm thế nào.)
DavidC

@DavidCarraher Nó xuất mã do cách StringMatchQ và Nếu thất bại:If[StringMatchQ[3, "a"], x, y]
ssch

6

C, 599 587 487 481 467 ký tự

Tôi chắc chắn điều này có thể bị đánh bại. Tôi đang sử dụng C sau tất cả. Có một lý do mà bạn không thấy nhiều mục golf chiến thắng được viết bằng C. Đây hiện là 467 ký tự nhờ lạm dụng hình sự #define.

Chỉ định tệp nguồn HQ9 + làm đối số dòng lệnh.

EDIT: Bây giờ chấp nhận nguồn từ stdin, không phải là một tập tin. Bắt đầu chương trình, bắt đầu nhập mã, CTRL-C khi hoàn tất để chạy nó.

Nó biên dịch ít nhất trong MinGW / GCC với: gcc -o hq9+.exe hq9+.c

Nên hoạt động trong MSVC, nhưng tôi không muốn tạo ra một giải pháp hoàn chỉnh chỉ cho việc này. :)

#define B "bottles of beer"
#define C case
#define P printf
#define R break
a,i,j,s;
main(){
char p[9999],c;
for(;;) {
    switch(c=getch()){
    C 'H':C 'Q':C '9':C '+': C 3: R;
    default:P("Source code contains invalid characters\n");
    }
    if (c==3) R;
    p[s++]=c;
}
for(i=0;i<s;i++){
    c = p[i];
    switch(c){
    C 'H':
        P("Hello world!");
        R;
    C 'Q':
        for(j=0;j<s;j++)putchar(p[j]);
        R;
    C '9':
        j=99;
        while(j){
            P("%d "B" on the wall,\n%d "B".\nTake one down, pass it around,\n%d "B".\n",j,j,j-1);
            j--;
        }
        R;
    C '+':
        a++;
    }
}
}

Hoặc là:

#define B "bottles of beer"
#define C case
#define P printf
#define R break
a,i,j,s;main(){char p[9999],c;for(;;){switch(c=getch()){C 'H':C 'Q':C '9':C '+': C 3: R;default:P("Source code contains invalid characters\n");}if (c==3) R;p[s++]=c;}for(i=0;i<s;i++){c = p[i];switch(c){C 'H':P("Hello world!");R;C 'Q':for(j=0;j<s;j++)putchar(p[j]);R;C '9':j=99;while(j){P("%d "B" on the wall,\n%d "B".\nTake one down, pass it around,\n%d "B".\n",j,j,j-1);j--;}R;C '+':a++;}}}

Giảm xuống 487 ký tự bằng cách sử dụng stdin thay vì tệp để nhập.
Mike C

Kiếm 464 bằng cách lạm dụng #define.
Mike C

Bạn có thể thoát khỏi không gian, như những người sau Cvà một vài người trước đó R;. Cũng có thể cạo 8 ký tự p[s++]=0;sau vòng lặp đầu vào để đơn giản hóa việc in p.
Daniel Lubarov

3

Python 2 - 452 453 443 byte

q=raw_input()
if set(q)-set('HQ9+'):print'Source code contains invalid characters'
b=' bottles of beer'
b=[b,b.replace('s','')]
w=[a+' on the wall'for a in b]
t='Take one down, pass it around,\n'
c={'H':'Hello, world!','Q':q,'9':''.join(`i`+w[i<2]+',\n'+`i`+b[i<2]+'.\n'+t+(`i`if i>1 else'No')+w[0]+'.\n'for i in range(1,100)[::-1])+'No'+w[0]+',\nNo'+b[0]+'.\n'+'Go to the store, buy some more,\n99'+w[0]+'.'}
for d in q:
 if d in c:print c[d]

Thôi nào. Nó đã bị hỏng, nhưng sau đó tôi phát hiện ra một lỗi khiến tôi phải trả một byte để sửa. Thôi nào.

(Tôi đã từng không bao gồm +trong đầu ra cho Q. Chẳng hạn, một đầu vào Q+++đã cho đầu ra Q.)

Đã lưu một số ký tự bằng cách không thoát khỏi đầu vào không hợp lệ như tôi nghĩ bạn phải có.

Phiên bản giải thích sắp ra mắt.Tôi từ bỏ. Tôi thậm chí còn không hiểu làm thế nào sự quái dị này hoạt động nữa. Nếu có nhu cầu tôi sẽ cho nó đi tiếp nhưng đến lúc đó nó không xảy ra.


Bạn không exitnhập ký tự không hợp lệ, chỉ hiển thị thông báo, vì vậy bạn có thể lưu 7 ký tự ở đó.
Kyle Kanos

@KyleKanos ơi, tôi hiểu nhầm rồi. Cảm ơn!
undergroundmonorail

Lời bài hát của bạn không đúng - hiện tại nó nói: 99 bottles of beer on the wall, 99 bottles of beer. Take one down, pass it around, *99* bottles of beer on the wall. Đáng lẽ phải nói: 99 bottles of beer on the wall, 99 bottles of beer. Take one down, pass it around, *98* bottles of beer on the wall.
Oliver Ni

Nó cũng báo lỗi khi tôi nhập +. Bạn nên bỏ qua + , không đưa ra lỗi
Oliver Ni

Also there's not supposed to be anything between outputs. Like if I enter HQHH it should say Hello World!HQHHHelloWorld!Hello World!
Oliver Ni

3

Perl, 325 - 8 = 317

sub p{print@_}$_=<>;$a=' on the wall';$b=' bottle';$e=' of beer';$c='Take one down, pass it around';if(!/^[hqHQ9+]+$/){p"Source code contains invalid characters";exit}$k=$_;for(/./g){/H|h/&&p"Hello, World!";if(/9/){$i=99;$d=$b."s$e";while($i>0){p"$i$d$a
$i$d
$c
";$q=--$i==1?'':'s';$d="$b$q$e";$i||=No;p"$i$d$a
"}}/Q|q/&&p$k}

Expanded:

sub p{print@_}
$_=<>;
$a=' on the wall';
$b=' bottle';
$e=' of beer';
$c='Take one down, pass it around';
if(!/^[hqHQ9+]+$/){
    p"Source code contains invalid characters";
    exit
}
$k=$_;
for(/./g){
    /H|h/&&p"Hello, World!";
    if(/9/){
        $i=99;
        $d=$b."s$e";
        while($i>0){
            p"$i$d$a
$i$d
$c
";
            $q=--$i==1?'':'s';
            $d="$b$q$e";
            $i||=No;
            p"$i$d$a
"
        }
    }
    /Q|q/&&p$k
}

2

Ruby, 364 360 - 8 = 352

Still has lots of room for improvement. 99 bottles code stolen from here.

p=gets.upcase
if p=~/[^HQ9+
]/
puts"Source code contains invalid characters"else
p.each_char{|x|case x
when ?H
puts"Hello, world!"
when ?Q
puts p
when ?9
def c;"#{$n} bottle#{'s'if$n>1} of beer on the wall"end
($n=99).times{puts"#{c}, #{c[0..-13]}.
#{$n<2?"Go to the store and buy some more":"Take one down and pass it around"}, #{$n=($n-2)%99+1;c}.

"}end}end

There's supposed to be No more bottles of beer on the wall after the 1 bottle section. then it's Go to the store...
Oliver Ni

1 bottle of beer on the wall, 1 bottle of beer on the wall, take one down, 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, buy some more, 99 bottles of beer on the wall.
Oliver Ni

@Oliver The question does not specify the exact lyrics of the song. In no place does it require the "no more" section to be included.
Doorknob

Ok, but also, there's not supposed to be a newline between outputs.
Oliver Ni

@Oliver Where does the challenge say that?
Doorknob

2

Haskell, 298

main=interact g
g s|all(`elem`"HQ9+")s=s>>=(%s)|0<1="Source code contains invalid characters"
'H'%_="hello World!"
'Q'%s=s
'9'%_=drop 32$d 99
_%_=""
k=" bottles of beer on the wall"
d 0="No more"++k++"."
d n|a<-shows n k=[a,".\n\n",a,",\n",take 18a,".\ntake one down, pass it around\n",d$n-1]>>=id

this is quite straightforward. % returns a command's output (given the source cod for use on Q). d returns the 99 bottles song with a junk line at the start for golfing reasons. everything is wrapped in an interact (you might want to use g instead of main when testing)


How should I run it? I tried pasting it in WinGHCi, but I get <interactive>:8:5: parse error on input ‘=’.
ProgramFOX

@ProgramFOX i have no idea... Ill check when i can
proud haskeller

@ProgramFOX sorry it took long :-). you're not using GHCi properly. in GHCi you can't irectly input definitions as it expects expressions. you can either use a let to insert definitions (this breaks when inserting multiple definitions not separated by ;) or run the code from a file.
proud haskeller

I see. I still fail at trying to run it though; when I load the file and call main, it says that the source code contains invalid characters when I try to execute H. When I try to run g instead of main, it immediately gives an error.
ProgramFOX

@ProgramFOX main doesn't work because the newline appended is not a legal command. That's why i recommended using g instead. As for g, does putStrLn $ g "H" not work properly?
proud haskeller

2

J - 444 bytes

I liked the number, so stopped golfing. Here 'ya go, single expression function!

f=:'Source code contains invalid characters'"_`('Hello, world!'"_`[`((((s=:(<:@[s],L,(v,LF,'Take one down and pass it around, '"_,b@<:,' of beer on the wall.'"_)@[,''"_)`(],(L=:LF,LF),(v=:1&b,' of beer on the wall, '"_,b,' of beer.'"_)@[)@.([<1:))''"_),LF,'Go to the store and buy some more, '"_,(b=:({&'Nn'@([=0:),'o more'"_)`(":@])@.(]>0:),{.&' bottles'@(8:-=&1@])),' of beer on the wall.'"_)@(99"_))`]@.('HQ9+'&i.@])"0 1 0])@.(*./@e.&'HQ9+')

Examples:

   hq9 '9QHHQ+'
99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.

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

...

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

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.
9QHHQ+
Hello, world!
Hello, world!
9QHHQ+
+
   hq9 '9QHHaQ'
Source code contains invalid characters

And no, I won't write an explanation for this. Too long.
seequ

Wait, why is this downvoted?
seequ

2

Fortran 528 470 481

It requires compiling with -fpp flag (+3 to score)1 to use preprocessing directives (which saves way more than 3 chars, so I'm totally okay with that). It is also case insensitive, so there's -8 :D. Saved 5 chars by not preprocessing the endif as that is used once anyway.

Requires the file to have a .F90 extension (makes sense to call it hq9+.F90) so that the compiler forces preprocessing. The code is case-sensitive; making it case-insensitive adds something like 16 characters, so it's not really worth it to save 8 characters. My previous answer did not account for the changing plurals in bottles for 9; this version corrects it (and sadly adds a lot more characters).

#define P print*,
#define W " of beer on the wall"
#define N print'(x,i0,a,a)',
#define e enddo
#define S case
#define J len(trim(c))
character(len=99)::c,b=" bottles";read*,c;do i=1,J;if(all(c(i:i)/=["H","Q",'9',"+"])) then;P"Source code contains invalid characters";exit;endif;e;do i=1,J;select S(c(i:i));S("H");P"Hello, world!";S("Q");P c;S("9");l=8;do k=99,1,-1;N k,b(1:l),W;N k,b(1:l)," of beer";P "Take one down, pass it around";if(k==2)l=l-1;if(k==1)exit;N k-1,b(1:l),W;P"";e;P"No more",trim(b),W;S default;endselect;e;end

Looks a lot better ungolfed & non-preprocessed (probably because you can see what's going on):

program hq9
   character(len=99)::c,b=" bottles"
   read*,c
   do i=1,len(trim(c))
! change the below to ["H","h","Q","q","9","+"] to be case-insensitive
      if(all(c(i:i)/=["H","Q","9","+"]))then
         print*,"Source code contains invalid characters"
         exit
      endif
   enddo
   do i=1,len(trim(c))
      select case(c(i:i))
        case("H")                ! change to case("H","h") for case-insensitive
           print*,"Hello, world!"
        case("Q")                ! change to case("Q","q") for case-insensitive
           print*, c
        case("9")
           l=8
           do k=99,1,-1
              print'(x,i0,a,a)', k,b(1:l)," of beer on the wall"
              print'(x,i0,a)', k,b(1:l)," of beer"
              print*,"Take one down, pass it around"
              if(k==2) l=l-1
              if(k==1) exit
              print'(x,i0,a)', k-1,b(1:l)," of beer on the wall"
              print*,""
           enddo
           print*,"No more",trim(b)," of beer on the wall"
        case default
           ! do nothing
      endselect
   enddo
end program hq9

I think it's acceptable to require a specific extension to let the compiler know what it's compiling. An analog might be requiring a C++ file to be named .cc to avoid needing the -lstdc++ flag.
primo

2

Python 2, 340 - 8 = 332

s,o=raw_input(),''
for z in s:
 if z in'Hh':o+='Hello World!'
 elif z in'Qq':o+=s
 elif'9'==z:
  i=298
  while~-i:print i/3or 99,'bottle'+'s of beer on the wall.\n'[2<i<6:9+i%3*12]+'..\nGToa kteo  otnhee  dsotwonr,e ,p absusy  isto maer omuonrde,,'[(i>3)+i%3*68::2];i-=1
 elif'+'!=z:o='Source code contains invalid characters';break
print o

1

Lua 443 - 8 = 435 464 - 8 = 456

I managed to save 21 characters by using multiple if-ends instead of if-elseif-end. I also had some extra white spaces floating around after a few ).

p=print o=" of beer"t=" on the wall"B=" bottle"b=" bottles"l=io.read("*l");g=l:lower()if g:match"[^hq9+]"then p("Source code contains invalid characters")end for i=1,#g do s=g:sub(i,i)if s=='h'then p("Hello, world")end if s=='q'then p(l)end if s=='9'then n=99 repeat p(n..b..o..t..", "..n..b..o)n=n-1 p("Take one down, pass it around, "..n..b..o..t..".")p()until n==1 p("1"..B..o..t..", 1"..B..o)p("No more"..b..o..t..", no more"..b..o)end end

I'm fairly happy with this one, even though it's not much shorter than my Fortran answer. The 99 bottles of beer code has been modified from this answer by Alessandro. Ungolfed, we have

-- reuse stuff
p=print
o=" of beer"
t=" on the wall"
B=" bottle"
b=" bottles"
-- read the line & then lowercase it for case insensitivity
l=io.read("*l");g=l:lower()
if g:match"[^hq9+]" then -- horray for basic regex
   p("Source code contains invalid characters")
end
for i=1,#g do
   s=g:sub(i,i)               -- take substring
   if s=='h' then p("Hello, world") end
   if s=='q' then p(l) end
   if s=='9' then
      n=99
      repeat
         p(n..b..o..t..", "..n..b..o)
         n=n-1
         p("Take one down, pass it around, "..n..b..o..t..".")
         p()
      until n==1
      p("1"..B..o..t..", 1"..B..o)
      p("No more"..b..o..t..", no more"..b..o)
   end
end

The code to lowercase the input costs 12 characters, so the bonus is not worth it.
nyuszika7h

You don't need to lowercase the input, you can just do something like if s in'Hh'
Oliver Ni

It saves 8 chars
Oliver Ni

@MCParadox: Er, that's Python you're thinking of, Lua's in is for for-loop iterators and not comparisons; you'll get an error if you stick that in there. There are three choices here: (1) use match at each line, (2) user s=='h'or s=='H' at each line, (3) do it the way I did it. Clearly (3) is shorter than (1) and (2).
Kyle Kanos

1

Julia, 362

s = chomp(readline(STDIN))
l=""
z=" of beer"
q,r,w,t=" bottles$z"," bottle$z"," on the wall.\n","take one down, pass it around,\n"
for j=99:-1:2
b="$j$q"
l*="$b$w$b.\n$t"
end
l*="1$r$(w)1$r.\n$(t)No$q$w"
p=println
all(c->c in "HQ9+", s)||p("Source code contains invalid characters")
for c in s
    c=='Q'&&p(s)
    c=='H'&&p("Hello, world!")
    c=='9'&&p(l)
end

1

Tcl, 515

set d [read stdin]
if {![regexp {^[hq9\+HQ]*$} $d]} {puts "Source code contains invalid characters"}
lmap c [split $d {}] {set b { bottles of beer}
switch -- $c H {puts "Hello, world"} Q {puts $d} 9 {for {set i 99} {$i>2} {incr i -1} {puts "$i$b on the wall,
$i$b.
Take one down, pass it around,
[expr $i-1]$b on the wall.
"}
puts "2$b on the wall,
2$b.
Take one down, pass it around,
1 bottle of beer on the wall.

1 bottle of beer on the wall,
1 bottle of beer.
Take one down, pass it around,
No$b on the wall."}}

Just a bit golfed, still smaller than C and the correct 99 Bottles of beer end verse.


Okay, now that one's legit. Good job, you beat me. I should stop using C for golf.
Mike C

You can remove the first line and embed it at the last parameter of regexp. You can get my golfing of 99 beers on codegolf.stackexchange.com/a/109818/29325
sergiol

1

JavaScript (ES6), 385

s=>{n=99,b=' bottle',j=' of beer',d=' on the wall',e='Take one down, pass it around',k='Go to the store, buy some more',l='No',o='s',f=', ';for(i=s.split(m=v='');~n;)v+=[n||l,b,n-1?o:m,j,d,f,n||l,b,n-1?o:m,j,f,n?e:k,f,--n<1?99:n,b,n-1?o:m,j,d,'! '].join(m);return s.match(/[^HQ9\+]/,r='')?'Source code contains invalid characters':[...s].map(c=>({H:'Hello World!',9:v,Q:s})[c]).join``}

Didn't opt for the case-insensitive, would have cost too many characters. Not even close to some of the other entries, but was fun nonetheless!

JavaScript, 344

I made a version with a less complete version of the song:

(function(i){if(s.match(/[^HQ9\+]/)){m='Source code contains invalid characters'}else{n=99,b=' bottles of beer ',d='on the wall',e='take one down, pass it around',f=', ';for(;n;)v+=[n,b,d,f,n,b,f,e,f,--n||'no more',b,d,'! '].join(m);h={H:'Hello World!',Q:arguments.callee+m,9:v};for(;c=i[n++];)m+=h[c]||''}alert(m)})((s=prompt()).split(m=v=''))

but after seeing the other entries (and looking at the actual lyrics, who knew!), I thought it was a bit of a cop out!


It should be Go to the store, buy some more, *99* bottles of beer on the wall, not *No more* bottles of beer on the wall
Oliver Ni

If you buy some more, how can there still be no more?
Oliver Ni

And also, Q doesn't work for me.
Oliver Ni

@Oliver didn't notice you comment on this back then... I totally misunderstood when the Q was supposed to do that the time and provided the source code of the function instead of the input... That was originally my reason for doing it in JS, that part would be easy, however I now know that isn't what's required at all!
Dom Hastings

@Oliver updated the lyrics!
Dom Hastings

1

C, 562 bytes

char*c="%1d %3$s of %4$s on the %5$s, %1d %3$s of %4$s.\n\0Take one down and pass it around, %2d %3$s of %4$s on the %5$s.\n\0Go to the store and buy some more, %1d %3$s of %4$s on the %5$s.\n";main(int a,char**b){int x=0;for(int i=0;i<strlen(b[1]);i++){if(b[1][i]=='+')x++;else if(b[1][i]=='9'){int k=99;while(1){printf(&c[0],k,k,k==1?"bottle":"bottles","beer","wall");if(k!=1){printf(&c[49],k,k,"bottles","beer","wall");k--;}else{k=99;printf(&c[114],k,k,"bottles","beer","wall");break;}}}else printf("%s",b[1][i]=='H'?"Hello, world!":(b[1][i]=='Q'?b[1]:""));}}

As a full program. First argument is the HQ9+ program. With an actual accumulator. I challanged myself not to use define statements.

Ungolfed version:

char* c = "%1d %3$s of %4$s on the %5$s, %1d %3$s of %4$s.\n\0Take one down and pass it around, %2d %3$s of %4$s on the %5$s.\n\0Go to the store and buy some more, %1d %3$s of %4$s on the %5$s.\n";
main (int a, char** b) {
    int x = 0;
    for (int i = 0; i < strlen(b[1]); i++) {
        if (b[1][i] == '+')
            x++;
        else if (b[1][i] == '9') {
            int k = 99;
            while (1) {
                printf(&c[0], k, k, k == 1 ? "bottle" : "bottles", "beer", "wall");
                if (k != 1) {
                    printf(&c[49], k, k, "bottles", "beer", "wall");
                    k--;
                } else {
                    k=99;
                    printf(&c[114], k, k, "bottles", "beer", "wall");
                    break;
                }
            }
        } else
            printf("%s",b[1][i] == 'H' ? "Hello, world!" : (b[1][i] == 'Q' ? b[1] : ""));
    }
}

0

Java, 546 bytes

This is my first code golf submission. I am sure we could do more with it. It reads the input as the command line argument. Beer code "borrowed" from "99 Bottles of Beer" java answer (creative commons)

class a{public static void main(String[] a){if(a[0].matches("^[HQ9\\Q+\\E]+$")){for(char c:a[0].toCharArray()){if(c=='H')p("Hello, world!");if(c=='Q')p(a[0]);if(c=='9')b();}}else{System.out.println("Source code contains invalid characters");}}static void p(String s){System.out.println(s);}static void b(){String b=" of beer",c=" on the wall",n=".\n",s;for(int i=100;i-->1;){s=" bottle"+(i>1?"s":"");p(i+s+b+c+", "+i+s+b+n+(i<2?"Go to the store and buy some more, 99":"Take one down and pass it around, "+(i-1))+" bottle"+(i!=2?"s":"")+b+c+n);}}}

Let me know if command line args is not acceptable. This was a lot of fun!


CLA are fine. Nice answer.
Rɪᴋᴇʀ

0

Excel VBA, 489 Bytes

Unindented:

Sub h(s)
For c=1 To Len(s)
Select Case Mid(s,c,1)
Case "H"
Debug.? "Hello,World!"
Case "Q"
Set v=ActiveWorkbook.VBProject.VBComponents("M").CodeModule:For n=1 To v.countoflines:Debug.? v.Lines(n,1):Next
Case "+"
a=a+1
Case "9"
s=" Bottles of Beer":o=" Bottle of Beer":w=" on the wall":t=". Take 1 down pass it around,":p=",":d=".":For n=99 To 3 Step -1:Debug.? n;s;w;p;n;s;t;n-1;s;w;d:Next:Debug.? 2;s;w;p;2;s;t;1;o;w;d:Debug.? 1;o;w;p;1;o;t;"No";s;w;d
End Select
Next
End Sub

(indented for readability)

Sub h(s)
For c=1 To Len(s)
Select Case Mid(s,c,1)
    Case "H"
        Debug.? "Hello,World!"
    Case "Q"
        Set v=ActiveWorkbook.VBProject.VBComponents("M").CodeModule
        For n=1 To v.countoflines
            Debug.? v.Lines(n,1)
        Next
    Case "+"
        a=a+1
    Case "9"
        s=" Bottles of Beer"
        o=" Bottle of Beer"
        w=" on the wall"
        t=". Take 1 down pass it around,"
        p=","
        d="."
        For n=99 To 3 Step -1
            Debug.? n;s;w;p;n;s;t;n-1;s;w;d
        Next
        Debug.? 2;s;w;p;2;s;t;1;o;w;d
        Debug.? 1;o;w;p;1;o;t;"No";s;w;d
End Select
Next
End Sub

Rename default Module1 to M
call with h "+++++++++Your Code"
This will also work on other office applications, changing ActiveWorkbook to the appropriate document type


note that excel will add spaces, and expand abbreviations, so within excel, the code is 531 chars
SeanC

Thats 636 Characters
Oliver Ni

Remove all the whitespace from my indentation, @oliver
SeanC

You can loose 3 Bytes by converting all instances of For n=1 To to For n=1To (removing whitespace before To) and 4 bytes by converting all instances of Debug.? 2; to Debug.?2; (removing whitespace after ? keyword)
Taylor Scott
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.