Golfscript - 56 50 49 48 41 40 38 37 caratteri
n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/
Nota: gestisce più righe di input, è veloce (1/8 di secondo per eseguire i casi di test) e non si interrompe per alcun input legale.
(La prima versione è stata anche il mio primo programma Golfscript in assoluto; grazie a eBusiness per aver messo in evidenza diversi trucchi che mi mancavano).
Per rendere anche questo utile post educativo, ecco una spiegazione di come funziona. Iniziamo con la ricorrenza f(n, k) = k * (f(n-1, k) + f(n-1, k-1))
. Questo può essere inteso in modo combinatorio dicendo che per posizionare n
sfere k
distinguibili in secchi distinguibili in modo tale che ogni secchio contenga almeno una pallina, scegli uno dei k
secchi per la prima pallina ( k *
) e quindi conterrà almeno un'altra pallina ( f(n-1, k)
) o non lo farà ( f(n-1, k-1)
).
I valori risultanti da questo formano una griglia; prendendo n
come indice di riga e k
come indice di colonna e indicizzando entrambi da 0 inizia
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 ...
. . . . . . . .
. . . . . . . .
. . . . . . . .
Quindi, rivolgendosi al programma,
n%{~ <<STUFF>> }/
divide l'input in righe e quindi per ogni riga lo valuta, mettendo n
e k
in pila, e quindi chiama <<STUFF>>
, che è il seguente:
),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;
Questo calcola le prime k+1
voci della n+1
riga di quella griglia. Inizialmente lo stack è n k
.
),
dà stack di n [0 1 2 ... k]
{!}%
dà stack di n [1 0 0 ... 0]
dove ci sono k
0.
\{ <<MORE STUFF>> }*
porta n
in cima e lo rende il numero di volte che eseguiamo <<MORE STUFF>>
.
Il nostro stack attualmente è una riga della tabella: [f(i,0) f(i,1) ... f(i,k)]
0.@
mette un paio di 0 prima di quell'array. Il primo sarà j
e il secondo sarà f(i,j-1)
.
{ <<FINAL LOOP>> }/
scorre attraverso gli elementi dell'array; per ognuno lo mette in cima allo stack e quindi esegue il corpo del loop.
.@+2$*@)@
è noiosa manipolazione dello stack per ottenere ... j f(i,j-1) f(i,j)
e cedere ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]
pop-over del rimanentek+1 f(i,k)
e raccoglie tutto in un array, pronto per il prossimo giro del ciclo.
Alla fine, quando abbiamo generato la n
riga della tabella,
)p;
prende l'ultimo elemento, lo stampa e scarta il resto della riga.
Per i posteri, tre soluzioni a 38 caratteri su questo principio:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/