Golfscript - 56 50 49 48 41 40 38 37 caracteres
n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/
Nota: ele lida com várias linhas de entrada, é rápido (1/8 segundos para executar os casos de teste) e não quebra para nenhuma entrada legal.
(A primeira versão também foi o meu primeiro programa Golfscript; agradeço ao eBusiness por apontar vários truques que perdi).
Para tornar este post educacional útil também, aqui está uma explicação de como ele funciona. Começamos com a recorrência f(n, k) = k * (f(n-1, k) + f(n-1, k-1))
. Isso pode ser entendido combinatoricamente como dizer que, para colocar n
bolas distinguíveis em k
baldes distinguíveis, de modo que cada balde contenha pelo menos uma bola, você escolhe um dos k
baldes para a primeira bola ( k *
) e, em seguida, conterá pelo menos mais uma bola ( f(n-1, k)
) ou não vai ( f(n-1, k-1)
).
Os valores resultantes disso formam uma grade; tomando n
como o índice de linha e k
como o índice da coluna e indexando ambos a partir de 0 começa
1 0 0 0 0 0 0 ...
0 1 0 0 0 0 0 ...
0 1 2 0 0 0 0 ...
0 1 6 6 0 0 0 ...
0 1 14 36 24 0 0 ...
0 1 30 150 240 120 0 ...
0 1 62 540 1560 1800 720 ...
. . . . . . . .
. . . . . . . .
. . . . . . . .
Então, voltando-se para o programa,
n%{~ <<STUFF>> }/
divide a entrada em linhas e, em seguida, para cada linha a avalia, colocando n
e k
na pilha e, em seguida <<STUFF>>
, chama , da seguinte maneira:
),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;
Este calcula as primeiras k+1
entradas do n+1
th linha dessa grade. Inicialmente, a pilha é n k
.
),
dá pilha de n [0 1 2 ... k]
{!}%
dá pilha de n [1 0 0 ... 0]
onde há k
0s.
\{ <<MORE STUFF>> }*
traz a n
ao topo e faz com que seja o número de vezes que executamos <<MORE STUFF>>
.
Nossa pilha atualmente é uma linha da tabela: [f(i,0) f(i,1) ... f(i,k)]
0.@
coloca um par de 0s antes dessa matriz. A primeira será j
e a segunda será f(i,j-1)
.
{ <<FINAL LOOP>> }/
percorre os elementos da matriz; para cada um, coloca-o no topo da pilha e depois executa o corpo do loop.
.@+2$*@)@
é chato manipulação pilha para tomar ... j f(i,j-1) f(i,j)
e rendimento ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]
aparece fora a esquerda ao longok+1 f(i,k)
e reúne tudo em uma matriz, pronta para a próxima rodada.
Finalmente, quando geramos a n
quinta linha da tabela,
)p;
pega o último elemento, o imprime e descarta o restante da linha.
Para a posteridade, três soluções de 38 caracteres sobre esse princípio:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/