Golfscript - 56 50 49 48 41 40 38 37 znaków
n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/
Uwaga: obsługuje wiele linii danych wejściowych, jest szybki (1/8 sek., Aby wykonać przypadki testowe) i nie psuje się w przypadku legalnych danych wejściowych.
(Pierwsza wersja była również moim pierwszym programem do gry w golfa; dzięki eBiznesowi za wskazanie kilku sztuczek, które przegapiłem).
Aby uczynić go również użytecznym postem edukacyjnym, oto wyjaśnienie, jak to działa. Zaczynamy od nawrotu f(n, k) = k * (f(n-1, k) + f(n-1, k-1))
. Można to zrozumieć kombinatorycznie, mówiąc, że aby umieścić n
wyróżniające się kule w k
wyróżniających się wiadrach, tak aby każde wiadro zawierało co najmniej jedną piłkę, wybierasz jedno z k
wiader dla pierwszej piłki ( k *
), a następnie albo będzie ona zawierać co najmniej jeszcze jedną piłkę ( f(n-1, k)
) albo nie będzie ( f(n-1, k-1)
).
Wynikające z tego wartości tworzą siatkę; przyjmując n
jako indeks wiersza i k
jako indeks kolumny i indeksując oba od 0, zaczyna się
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 ...
. . . . . . . .
. . . . . . . .
. . . . . . . .
Wracając do programu,
n%{~ <<STUFF>> }/
dzieli dane wejściowe na linie, a następnie dla każdej linii ocenia je, umieszczając n
i k
na stosie, a następnie wywołuje <<STUFF>>
, co jest następujące:
),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;
Oblicza to pierwsze k+1
wpisy w n+1
th rzędzie tej siatki. Początkowo stos jest n k
.
),
daje stos n [0 1 2 ... k]
{!}%
daje stos n [1 0 0 ... 0]
gdzie są k
0.
\{ <<MORE STUFF>> }*
przynosi n
do góry i sprawia, że wiele razy wykonujemy <<MORE STUFF>>
.
Nasz stos jest obecnie rzędem tabeli: [f(i,0) f(i,1) ... f(i,k)]
0.@
stawia kilka zer przed tą tablicą. Pierwszy będzie, j
a drugi będzie f(i,j-1)
.
{ <<FINAL LOOP>> }/
zapętla się przez elementy tablicy; dla każdego z nich kładzie go na stosie, a następnie wykonuje ciało pętli.
.@+2$*@)@
to nudna manipulacja stosami, aby zabrać ... j f(i,j-1) f(i,j)
i ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]
wyskoczyć z resztekk+1 f(i,k)
i zbiera wszystko do tablicy, gotowe do następnego okrążenia.
Wreszcie, gdy wygenerowaliśmy n
th rząd tabeli,
)p;
bierze ostatni element, drukuje go i odrzuca resztę wiersza.
Dla potomnych trzy rozwiązania 38 znaków na tej zasadzie:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/