Criando um intérprete HQ9 +

31

O objetivo deste código golf é criar um intérprete para a linguagem de programação HQ9 +.
Existem 4 comandos nessa linguagem de programação:

  • H - imprime "Olá, mundo!"
  • Q - imprime o código fonte do programa
  • 9 - imprime a letra da música "99 garrafas de cerveja"
  • + - incrementa o acumulador

As regras:

  1. Porque o acumulador não está definido, você pode ignorar o comando +
  2. Seu programa deve solicitar entrada (essa entrada será o código-fonte) ou o código-fonte é lido de um arquivo
  3. Você não tem permissão para colocar a letra de "99 garrafas de cerveja" em um arquivo e ler o texto do arquivo
  4. Você não tem permissão para usar um algoritmo de compactação, como GZip ou BZip, para compactar o texto da música: você deve criar seu próprio algoritmo de compactação. Isso não precisa ser um algoritmo complexo, mas tente compactar o texto o máximo possível (lembre-se: este é um código de golfe, o código com o menor número de bytes ganha)
  5. Se o código-fonte contiver um caractere que não seja H , Q , 9 ou + , emita a saída "O código-fonte contém caracteres inválidos" antes de executar qualquer comando! Isso significa que, se o código-fonte for, H1por exemplo, não saia Hello, world!antes de sair Source code contains invalid characters. Não, saída imediataSource code contains invalid characters
  6. Se o seu intérprete aceita caracteres maiúsculos e minúsculos, você recebe -8 na contagem de caracteres

Boa sorte!

ProgramFOX
fonte
3
A regra 4 não faz sentido no "por que ele proibiria isso ?!" nível; a regra 5 não faz sentido com "o que ele quer dizer ?!" nível.
Peter Taylor
4
Como a regra 5 não faz sentido?
Mike C
Eu acho que seria melhor exigir apenas que ele use maiúsculas, em vez de dizer arbitrariamente que você recebe 8 caracteres gratuitos se ele aceitar. 8 pode ou não cobrir, dependendo do idioma.
Mike C
10
A regra 5 não faz sentido porque quebra as especificações do HQ9 +.
Boothby
2
Um intérprete no HQ9 + deve vencer automaticamente.
TheNumberOne

Respostas:

16

APL (Diálogo) (326 - 8 = 318)

Cole-o em uma janela do editor e ligue H. A entrada é retirada do teclado.

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
marinus
fonte
6

Mathematica, 349 346 341 caracteres

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"] &
alefalpha
fonte
Muito impressionante, mas parece haver alguns aspectos menores. 'H ["Q"] gera "Q". h ["9"] funciona, mas h [9] gera todo o programa (não entendo como.) #
9157
@DavidCarraher Ele gera código devido a como StringMatchQ e If falham:If[StringMatchQ[3, "a"], x, y]
ssch
6

C, 599 587 487 481 467 caracteres

Tenho certeza que isso pode ser derrotado. Eu estou usando C depois de tudo. Há uma razão pela qual você não vê muitas entradas vencedoras de golfe escritas em C. Agora, são 467 caracteres graças ao abuso criminal de #define.

Especifique o arquivo de origem HQ9 + como um argumento da linha de comandos.

EDIT: Agora aceita a fonte de stdin, não um arquivo. Inicie o programa, comece a digitar o código, CTRL- Cquando terminar de executá-lo.

Compila pelo menos em MinGW / GCC com: gcc -o hq9+.exe hq9+.c

Deveria funcionar no MSVC, mas não queria criar uma solução completa apenas para isso. :)

#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++;
    }
}
}

Ou:

#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++;}}}
Mike C
fonte
Reduzimos para 487 caracteres usando stdin em vez de um arquivo para entrada.
Mike C
Faça isso 464 abusando de #define.
Mike C
Você pode se livrar de espaços, como os seguintes Ce alguns antes R;. Também pode cortar 8 caracteres com p[s++]=0;o loop de entrada para simplificar a impressão p.
Daniel Lubarov 23/10
3

Python 2 - 452 453 443 bytes

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]

Bleh. Já estava sangrando, mas descobri um bug que me custou um byte para corrigir. Bleh.

(Eu não costumava incluir +na saída para Q. Uma entrada de Q+++deu a saída Q, por exemplo.)

Salvei alguns caracteres por não sair com entrada inválida, como eu pensava.

Versão explicada em breve.Eu desisto. Eu mal entendo como essa monstruosidade funciona mais. Se houver demanda, darei outra chance, mas até então não está acontecendo.

undergroundmonorail
fonte
Você não exitusa o caractere inválido, apenas exibe a mensagem, para que você possa salvar 7 caracteres.
precisa
@KyleKanos Oh, eu não entendi isso. Obrigado!
Undergroundmonorail
Suas letras não estão corretas - atualmente diz: 99 bottles of beer on the wall, 99 bottles of beer. Take one down, pass it around, *99* bottles of beer on the wall. Deve-se dizer: 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
Também dá um erro quando entro +. Você deveria ignorar + , não para cometer um erro #
Oliver Ni
Também não deve haver nada entre as saídas. Como se eu digitasse HQHH, deveria dizerHello 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}

Expandido:

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
}
faubi
fonte
2

Ruby, 364 360 - 8 = 352

Ainda tem muito espaço para melhorias. Código de 99 garrafas roubado daqui .

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
Maçaneta da porta
fonte
Deveria haver No more bottles of beer on the walldepois da 1 bottleseção. então é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 A pergunta não especifica a letra exata da música. Em nenhum lugar é necessário que a seção "no more" seja incluída.
Maçaneta
Ok, mas também, não deveria haver uma nova linha entre as saídas.
Oliver Ni
@ Oliver Onde o desafio diz isso?
Maçaneta
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

isso é bem direto. %retorna a saída de um comando (dado o código-fonte para uso Q). dretorna a música de 99 garrafas com uma linha de sucata no início por razões de golfe. tudo está envolvido em uma interação (você pode usar em gvez de maintestar)

orgulhoso haskeller
fonte
Como devo executá-lo? Tentei colar no WinGHCi, mas entendi <interactive>:8:5: parse error on input ‘=’.
ProgramFOX
@ProgramFOX eu não tenho idéia ... Vou verificar quando posso
proud haskeller
@ProgramFOX desculpe, demorou muito :-). você não está usando o GHCi corretamente. no GHCi, você não pode inserir definições de forma incorreta, pois espera expressões. você pode usar a letpara inserir definições (isso é interrompido ao inserir várias definições não separadas por ;) ou executar o código de um arquivo.
haskeller orgulhoso
Entendo. Eu ainda falho ao tentar executá-lo; quando carrego o arquivo e ligo main, ele diz que o código fonte contém caracteres inválidos quando tento executar H. Quando tento executar em gvez de main, ele imediatamente dá um erro.
ProgramFOX
O @ProgramFOX mainnão funciona porque a nova linha anexada não é um comando legal. É por isso que eu recomendo usar g. Quanto a g, putStrLn $ g "H" não funciona corretamente?
haskeller orgulhoso
2

J - 444 bytes

Eu gostei do número, então parei de jogar golfe. Aqui está, função de expressão única!

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+')

Exemplos:

   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
seequ
fonte
E não, não vou escrever uma explicação para isso. Demasiado longo.
seequ
Espere, por que isso é prejudicado?
seequ
2

Fortran 528 470 481

Requer a compilação com o -fppsinalizador (+3 para pontuar) 1 para usar diretivas de pré-processamento (que economizam muito mais do que 3 caracteres, por isso estou totalmente de acordo com isso). Também não diferencia maiúsculas de minúsculas, então há -8: D. Salvou 5 caracteres ao não pré-processar o endifque é usado uma vez de qualquer maneira .

Requer que o arquivo tenha uma .F90extensão (faz sentido chamá-lo hq9+.F90) para que o compilador force o pré-processamento. O código faz distinção entre maiúsculas e minúsculas; torná-lo sem distinção entre maiúsculas e minúsculas adiciona algo como 16 caracteres; portanto, não vale a pena salvar 8 caracteres. A minha resposta anterior não conta para a mudança plurais em bottlespara 9; esta versão corrige (e infelizmente adiciona muito mais caracteres).

#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

Parece muito melhor não-processado e não-processado (provavelmente porque você pode ver o que está acontecendo):

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
Kyle Kanos
fonte
Eu acho que é aceitável exigir uma extensão específica para que o compilador saiba o que está compilando. Um analógico pode estar exigindo que um arquivo C ++ seja nomeado .ccpara evitar a necessidade do -lstdc++sinalizador.
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
Oliver Ni
fonte
1

Lua 443 - 8 = 435 464 - 8 = 456

Consegui salvar 21 caracteres usando vários if-ends em vez de if-elseif-end. Eu também tinha alguns espaços em branco extras flutuando depois de alguns ).

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

Estou bastante feliz com este, mesmo que não seja muito menor do que minha resposta do Fortran . O código das 99 garrafas de cerveja foi modificado a partir desta resposta por Alessandro . Ungolfed, temos

-- 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
Kyle Kanos
fonte
O código para minúscula a entrada custa 12 caracteres, portanto o bônus não vale a pena.
usar o seguinte código
Você não precisa minúscula a entrada, você pode apenas fazer algo parecido comif s in'Hh'
Oliver Ni
Ele salva 8 caracteres
Oliver Ni
@MCParadox: Er, é em Python que você está pensando, o Lua iné para iteradores de loop for e não para comparações; você receberá um erro se colocar isso lá. Existem três opções aqui: (1) use matchem cada linha, (2) usuário s=='h'or s=='H'em cada linha, (3) faça da maneira que eu fiz. Claramente (3) é menor que (1) e (2).
Kry 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
gggg
fonte
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."}}

Apenas um pouco de golfe, ainda menor que C e as 99 garrafas de cerveja corretas no verso.

Johannes Kuhn
fonte
Ok, agora esse é legítimo. Bom trabalho, você me venceu. Eu deveria parar de usar C para jogar golfe.
Mike C
Você pode remover a primeira linha e incorporá-la no último parâmetro de regexp. Você pode obter meu golfe de 99 cervejas em 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``}

Não optar por não diferenciar maiúsculas de minúsculas, teria custado muitos caracteres. Nem mesmo perto de algumas das outras entradas, mas foi divertido!

JavaScript, 344

Eu fiz uma versão com uma versão menos completa da música:

(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=''))

mas depois de ver as outras entradas (e olhando as letras reais, quem sabia!), pensei que era um pouco de polícia!

Dom Hastings
fonte
Deveria ser Go to the store, buy some more, *99* bottles of beer on the wall, não*No more* bottles of beer on the wall
Oliver Ni
Se você compra um pouco mais, como ainda não pode haver mais?
Oliver Ni
E também, Qnão funciona para mim.
Oliver Ni
@ Oliver não percebeu que você comentava sobre isso naquela época ... eu entendi totalmente errado quando Qera para fazer isso da vez e forneci o código fonte da função em vez da entrada ... Essa foi originalmente a minha razão para fazê-lo em JS, essa parte seria fácil, mas agora eu sei que não é isso que é necessário!
Dom Hastings
@Oliver atualizou a letra!
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]:""));}}

Como um programa completo. O primeiro argumento é o programa HQ9 +. Com um acumulador real. Eu me desafiei a não usar declarações de definição.

Versão não destruída:

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] : ""));
    }
}
biscoito
fonte
0

Java, 546 bytes

Este é o meu primeiro envio de código de golfe. Estou certo de que poderíamos fazer mais com isso. Ele lê a entrada como o argumento da linha de comandos. Código da cerveja "emprestado" da resposta java "99 garrafas de cerveja" (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);}}}

Deixe-me saber se os argumentos da linha de comando não são aceitáveis. Isso foi muito divertido!

Rohan Jhunjhunwala
fonte
CLA estão bem. Boa resposta.
Rɪᴋᴇʀ
0

Excel VBA, 489 bytes

Sem indentação:

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

(recuado para facilitar a leitura)

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

Renomear a chamada padrão do Módulo1 para M
com h "+++++++++Your Code"
Isso também funcionará em outros aplicativos de escritório, alterando o ActiveWorkbook para o tipo de documento apropriado

SeanC
fonte
Observe que o Excel irá adicionar espaços, e expandir abreviaturas, por isso dentro do Excel, o código é 531 caracteres
SeanC
Isso é 636 caracteres
Oliver Ni
Remova todos os espaços do meu recuo, @oliver
SeanC
Você pode perder 3 bytes através da conversão de todas as instâncias de For n=1 Toa For n=1To(removendo espaços em branco antes To) e 4 bytes através da conversão de todas as instâncias de Debug.? 2;a Debug.?2;(removendo espaços em branco após a ?palavra-chave)
Taylor Scott