Гольфскрипт - 56 50 49 48 41 40 38 37 символів
n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/
Примітка: це обробляє кілька рядків введення, швидко (1/8 сек для тестових випадків) і не порушується для жодного юридичного введення.
(Перша версія була також моєю першою в історії програмою Golfscript; завдяки електронному бізнесу було вказано кілька хитрощів, які я пропустив).
Щоб зробити це також корисним навчальним дописом, ось пояснення того, як це працює. Починаємо з рецидиву f(n, k) = k * (f(n-1, k) + f(n-1, k-1)). Це можна зрозуміти комбінаторно, як кажучи, що для розміщення nпомітних кульок у kвідрізних відрах таким чином, щоб кожне відро містило щонайменше одну кульку, ви вибираєте одне із kвідра для першої кулі ( k *) і тоді або вона буде містити принаймні ще одну кулю ( f(n-1, k)) або не буде ( f(n-1, k-1)).
Значення, отримані внаслідок цього, утворюють сітку; приймаючи nяк індекс рядка і kяк індекс стовпця та індексуючи обидва з 0, він починається
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 ...
. . . . . . . .
. . . . . . . .
. . . . . . . .
Тож звертаючись до програми,
n%{~ <<STUFF>> }/
розбиває введення на рядки, а потім для кожного рядка оцінює його, ставлячи nі kв стек, а потім викликає <<STUFF>>, що таке:
),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;
Тут обчислюються перші k+1записи першого n+1ряду цієї сітки. Спочатку стек є n k.
),дає стек n [0 1 2 ... k]
{!}%give стек того, n [1 0 0 ... 0]де є k0s.
\{ <<MORE STUFF>> }*підводить nдо вершини і робить це кількість разів, коли ми виконуємо <<MORE STUFF>>.
Наш стек на даний момент є рядком таблиці: [f(i,0) f(i,1) ... f(i,k)]
0.@ставить пару 0 перед цим масивом. Перший буде, jа другий буде f(i,j-1).
{ <<FINAL LOOP>> }/петлі через елементи масиву; для кожного з них він ставить його поверх стека, а потім виконує тіло циклу.
.@+2$*@)@нудна маніпуляція стеком, щоб взяти ... j f(i,j-1) f(i,j)та ... j*(f(i,j-1)+f(i,j)) j+1 f(i,j)
;;]випустити спливи зліваk+1 f(i,k)і збирає все в масив, готовий до наступного обходу циклу.
Нарешті, коли ми створили nтретій рядок таблиці,
)p;бере останній елемент, друкує його та відкидає решту рядка.
Для нащадків три принципові рішення за цим принципом:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/