Код гольфу: розподіл м'ячів (I)


12

Виклик

У цьому завданні ви обчислите кількість способів розподілу кульок А у В-клітинах, при цьому кожна клітина має хоча б одну кулю.

Входи A і B задаються в один рядок, розділений порожнім, введення закінчується EOF.

Ви можете перевірити свої рішення тут .

Вхідні дані

0 0
1 0
12 4
6 3
18 17
20 19
15 13
18 9
20 20
17 14
9 2
14 13
18 11

Вихідні дані

1
0
14676024
540
54420176498688000
23112569077678080000
28332944640000
38528927611574400
2432902008176640000
21785854970880000
510
566658892800
334942064711654400

Обмеження

  • Кожен A і B можна відрізнити.
  • 0 <= A, B <= 20
  • Ви можете використовувати будь-яку мову на ваш вибір
  • Найкоротше рішення виграє!

1
Чи існують часові обмеження?

@ Тім Nordenfur: Оновлене :-)
донкіхотського

Це посилання для мене недійсне.
mellamokb

3
@Debanjan Мені не подобається ідея вставляти запитання від SPOJ тут. Люди подають свій код, щоб там змагатися, і це було б несправедливо до них.
fR0DDY

1
@Debanjan, я бачу твою посилання і піднімаєш тебе Mathworldрівнянні 5 сказано, що S(n,0)це 1якщо n=0і 0інакше). Якщо ви хочете, я можу знайти посилання на більш сильне твердження, що Стірлінг2 входить в асоціативну підгрупу експоненціальної групи Ріордана.
Пітер Тейлор

Відповіді:


4

JavaScript (90 93 )

function f(a,b){n=m=r=1;for(i=b;i>0;n*=-1){r+=n*m*Math.pow(i,a);m=m*i/(b-i--+1)}return--r}

http://jsfiddle.net/RDGUn/2/

Очевидно, будь-яка мова, заснована на математиці, наприклад APL, обіграє мене через багатослівність синтаксису та відсутність вбудованих математичних конструкцій :)

Редагувати Також у мене немає ніяких функцій, пов’язаних із входом, крім параметрів, переданих у функцію, не знаю, як використовувати стандартний ввід із JavaScript ...

Редагувати: перейти i--до m=m*вираження; переїхати n*=-1в for; почніть r=1комбінувати завдання та видаляти сторонні повернення. (збережіть 3 символи)


Можна скористатися оболонкою павутинної мавпи - вона принаймні має readlineі print. Я не знаю, що тут використовують інші.
Джессі Мілікан

@Jesse: Цікаво. Я все одно втрачу, хаха.
mellamokb

promptі alertвони є "стандартним" io, оскільки вони є типовим блокуванням викликів io, незважаючи на те, що ви ніколи не використовуєте блокування io з JavaScript.
zzzzBov

4

Гольфскрипт - 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;}/


1
Досить добре для початківця, є кілька можливих невеликих скорочень масштабу, відразу я знаходжу [0]-> 1,, простір після zip можна просто видалити, а інший простір можна видалити, якщо ви просто зберігаєте в операторі замість k. Я ще не переглянув ваш код, але я підозрюю, що ви можете піти, просто використовуючи значення, не вкладаючи його в масив в деяких місцях.
aaaaaaaaaaaa

1
+ 1, я не розумію Гольфскрипта, але це виглядає досить швидко, але все ж дуже коротко.
Кіхот

@eBusiness і @Peter Taylor: З іншого приводу .. скільки ви, хлопці, оцінюєте Golfscript за шкалою, легко зрозуміти?
Кіхот

@Debanjan, залежить від того, що ти вже знаєш. Це функціональна мова на основі стека. Раніше я використовував функціональні мови (SML - плюс я написав код функціонального стилю на мовах ОО), і раніше я використовував мови на основі стека (байт-код Java, зібраний з Jasmin, PostScript), тож єдине справжнє перешкода Я стикаюсь з тим, щоб дізнатися, які оператори доступні. Якщо ви знаєте лише мови з сімейства Algol (C, Java та ін.), Вам доведеться одразу три стрибки.
Пітер Тейлор

@Debanjan - Це набагато простіше, ніж це виглядає, ви можете почати писати код майже одразу, але, звичайно, потрібно трохи часу, щоб вивчити всі маленькі хитрощі.
aaaaaaaaaaaa

3

J, 40

4 :'|-/x(^~*y!~])i.1x+y'/&.".;._2(1!:1)3 

Напр

4 :'-/((x^~|.@:>:)*y&(!~))i.y'/x:".>{.;:(1!:1)3
15 13
28332944640000

<1сек для всіх тестових випадків.

Правки

  • (52 → 47) Скорочення за допомогою -/заміни чергування (1 _1)*(ідея JB)
  • (47 → 53) Помічена багатоканальна потреба вводу: - /
  • (53 → 48) Використовуйте симетрію двочленів.
  • (48 → 48) Робіть мовчки!
  • (48 → 41)
  • (41 → 40) Стисніть приріст + перетворення в1x+

1
Гей! То була моя ідея! O :-)
JB

Гаразд, я вкраду це 1x+тоді, але це повертає мені лише 1 персонаж, тоді як ти взяв 5!
JB

3

Лис звичайний (83)

(defun b (x y)
  (if (= (* x y) 0)
      (if (= (+ x y) 0) 1 0)
      (* y (+ (b (decf x) y) (b x (1- y)))))))

Схоже, має бути коротший спосіб перевірити базові випадки, але мені нічого не трапляється начебто.


3

J, 38 - 42

Залежно від ваших уподобань щодо строгості щодо інтерактивних мов та виведення презентацій, виберіть свій вибір у J-спектрі рішень:

  • 38 найкоротший інтерактивний: 4 :'|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    Запустіть jconsole, введіть його, а потім вставте вхід (закінчіть Cd). Ви помітите, що вихід розділений пробілом (J - векторна мова; він виконує обчислення на вхідному цілому в цілому і повертає його як 1D-вектор, представлення якого за замовчуванням знаходиться в одному рядку). Я вважаю, що добре, дух цієї проблеми - обчислення, а не презентація. Але якщо ви наполягаєте на тому, щоб натомість були нові рядки:
  • 39 довше інтерактивне: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3
    Заміна Compose ( &) на Under ( &.) повертає вектор рядків, презентація яких закінчується окремими рядками.
  • 42 пакетний режим: 4 :'echo|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    запустіть з командного рядка як$ jconsole balls.ijs < balls.in

Якщо ви проголосували за це, ви, можливо, захочете надати рішення Евенкс також і деяку заслугу.


&.Для правильної роботи в інтерактивному режимі вам потрібен Under .
Енадкс

@Eelvex у вас має бути інше тлумачення "правильно". Я запускаю jconsole, вставляю код, вставляю введення, Cd і отримую вихід. Ні під потрібні. Що твоє?
JB

Наші коди об'єднані: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3. 39 символів.
Вісімнадцять

Без відлуння або Under я отримую вихід лише в одному рядку (замість кількох рядків).
Енадкс

@Eelvex дійсно, але це прямо не заборонено.
JB

3

GolfScript - 45 38 36 символів

Відношення рецидивів брудної реалізації середньої сили ( 38 36 символів):

n%{~{.2$*{\(.2$f\2$(f+*}{=}if}:f~p}/

Відношення рецидиву, яке я вкрав з рішення Пітера Тейлорса, виглядає так:

f(x, y) = y * ( f(x-1, y) + f(x-1, y-1) )

У особливих випадках, якщо будь-яка змінна дорівнює 0.

Моя реалізація не використовує повторно попередні результати, тому кожна функція виклику функціонує на два нові виклики, якщо не досягнуто жодного з нульових випадків. Це дає найгірший випадок 2 ^ 21-1 виклику функції, який займає 30 секунд на моїй машині.

Легка сила серії (45 символів):

n%{~.),0\{.4$?3$,@[>.,,]{1\{)*}/}//*\-}/p;;}/

2

J, 55 символів

(wd@(4 :'(y^x)--/(!&y*^&x)|.i.y')/@".@,&'x');._2(1!:1)3
  • Проходить поточні тестові випадки. Я думаю, що я розумію математику ...
  • j602, лише консоль ( wd). Вхід на stdin, вихід на stdout.

Тест сценарію Баша:

jconsole disballs.ijs <<END
12 4
6 3
END

Що це робить j6xx wd?
JB

Я справді мав на увазі j602 ... Я здогадуюсь, що це також у j601. Це визначено як echo, що визначається як 0 0&$@(1!:2&2). Я не впевнений, що це означає, але він робить щось на кшталт симпатичного друку позицій 1-го рангу з розривом рядка. (Я тільки зараз помічаю, що використовує 2, а не 4 ... Я думаю, що це все ще переходить до stdout в консольному режимі, принаймні.)
Jesse Millikan

У мене виникають проблеми із запуском цього коду. Я просто набираю його в консоль?
mellamokb

@mellamokb Я використовую щось на зразок тестового сценарію вище, програма збережена як disballs.ijs і правильний шлях до j602 / bin / jconsole.
Джессі Мілікан

@Jesse: Я запускаю це на Windows. Мені << was unexpected at this time. прикро, що я новачок у введенні J, я завжди використовував його в консольному режимі.
mellamokb

2

Гольфскрипт - 26 символів

Попередження: У випадку 12 4 потрібно багато пам’яті (хоча не стільки, як відповідь нижче), і для запуску потрібно досить багато часу

~:)\?:x,{x+)base(;.&,)=},,

Очевидно, що ця відповідь має деякі проблеми, але я залишу її тут, оскільки коментарі посилаються на неї, і відповідь mellamokb базується на цьому.

Гольфскрипт - 24 символи

Попередження: корпус 12 4 потребує багато пам’яті та займає досить багато часу

~:o)\?,{o)base[0]-,o=},,

2
Я не можу зрозуміти, як ви придумали цей код, і не тільки у цього методу не вистачить пам’яті для великих входів, я також не можу зрозуміти, для чого корисні оператори приросту. Те, що ви насправді потрапили в ціль на 6 3, здається, не що інше, як удача.
aaaaaaaaaaaa

Це не клоун, це моя дружина!
Джессі Мілікан

2
Я не розумію Гольфскрипта, але, як ви сказали, і я згоден, ваш підхід занадто повільний.
Кіхотик

3
@mellamokb, добре для вас, що ви працювали, як це мало працювати :) Для виправлення помилки знадобилося лише 2 додаткових символи. Зараз ми перебуваємо в темній зоні, де найкоротший код може бути правильним, але не практичним. Код-гольф пронизаний шалено неефективними відповідями, але мікросекунди проти секунд зазвичай не мають значення. Це надзвичайний випадок (теж багато пам’яті). Debanjan вказав , що відповіді повинні бути швидше, але цей сайт НЕ SPOJ, це питання є мічений код-гольф
gnibbler

1
@ gnibbler, 0 0має виробляти 1; 0 kдля будь-якого іншого kслід виробляти 0; n 1для n > 0повинні виробляти 1.
Пітер Тейлор

2

Пітон 140 символів

import sys
f=lambda n,k:(n and k and n>=k and k*(f(n-1,k-1)+f(n-1,k)))or(n+k==0 and 1)or 0
for l in sys.stdin:print f(*(map(int,l.split())))

2

постійного струму, 100 символів

[0q]s5[1q]s6[l2l3>5l3 0>5l2 0=6l2 1-S2l3dS3 1-S3l1xL3s9l1xL2s9+L3*]s1[?z0=5S3S2l1xL3L2+s9fs9l4x]ds4x

На жаль, DC, схоже, не підтримується ідеоном. Можливо, ще один персонаж може вичавитись, але це перед сном.

Примітка: це підтримує кілька рядків введення, має достатню точність, щоб дати правильний вихід навіть для 20 19(проклинайте вас, Perl, за те, що я витратив налагодження свого рішення!), І дає правильний вихід для 0 0.

Пропозиції від Nabb дозволяють скоротити принаймні наскільки це можливо

[0q]sZ[1q]sI[?z0=ZSkSn[lnlk>Zlk0>Zln0=Iln1-SnlkdSk1-SklFxLks9lFxLns9+Lk*]dsFxfs9l4x]ds4x

ціною залишення мотлоху в стеках реєстру (і, таким чином, не вистачає пам'яті, якщо ми обчислимо мільярди відповідей).


Регістри - це завжди одиничні символи (ви можете використовувати будь-який символ, що зробить код більш читабельним), тому l11він аналізується як l1 1(ви можете використовувати Kяк маркер одного символу, 0якщо ви все одно не збираєтесь змінювати точність) Ви можете змінити цикл введення на ?[...?z1=4]. Ви можете вбудувати макрос в регістр 1. І, напевно, ви можете зберегти купу більше символів взагалі, але я зачекаю, коли це буде коротше, щоб зрозуміти це.
Набб

@Nabb, ах, я недостатньо уважно прочитав сторінку чоловіка. Я використовую лише 8 або 9 регістрів, тому я не стикався з наслідками мого непорозуміння. Дякую.
Пітер Тейлор

1

Гольфскрипт (28 31 37 )

~):$\.($\?:@;?,{@+}%{$base$,\-[0]=},,

Модифікація gnibblerрішення GolfScript. Я думаю, що це робоче рішення - перевірене [3,2], [4,2], [6,3] та [9,2] з правильними відповідями. (Я використовував $і @для змінних, щоб збільшити простір навколо baseключового слова).

Є дві проблеми з gnibblerпоточним рішенням Росії.

  1. Перевірка довжини після видалення [0] не гарантує рішення, оскільки [1,1,1,1] буде дійсним для введення [4,2], навіть якщо всі 4 кулі знаходяться в одній комірці (1). Тому я змінив, щоб перевірити також, чи використовуються всі цифри, тобто масив містить 1-2, так що кожна комірка містить принаймні одну кульку.
  2. У випадку введення [4,2] формат базових-3 чисел 0-27 становить менше 4 цифр, а ліві-найбільші 0 не включаються. Це означає, що [1,1] включено як правильне рішення, навіть якщо це технічно фактично [0,0,1,1], що означає, що перші два кулі не розміщені ніде. Я виправляю, додаючи 3 ^ 3 до кожного запису (загалом k ^ n-1 до масиву k ^ n записів), так що перші записи зміщуються вгору, щоб мати принаймні n-цифр у форматі base-k, а останній записи автоматично все-таки будуть недійсними і не впливатимуть на рішення (адже друга цифра завжди буде 0).

Редагувати

~:@\?:$,{$+}%{@base(;@,\-,0=},,

`~:@\?:$,{$+@base(;@,\-,0=},,`

Краще рішення ще! Не потрібно збільшувати, просто додайте всі цифри, щоб вони починалися з [1], і жодні цифри не будуть відсутні (включаючи лівий пробіл 0), коли ви декодуєте цю першу цифру. Це рішення має працювати і було протестовано з тими ж записами, які були описані вище. Це також набагато швидше, тому що ми не збільшуємось перед тим, як приймати експонент для генерування масиву (але все ж страждає від тієї ж проблеми / продуктивності / пам'яті для більшого введення).

Редагувати : Використовуйте gnibblerідею переміщення додавання $всередину фільтра замість додаткового кроку. (збережіть 3 символи).


Перерви на вході 0 0.
Пітер Тейлор

Також з'являється обробка лише одного рядка введення.
Пітер Тейлор

І перерва на n 1будь-яке п, викликає звисання. хм ..
mellamokb

1
перетворення чисел на базу 1 зробить це :)
gnibbler

@gnibbler: Чи є у вас якісь пропозиції? Мені просто потрібно буде накинути деякі, якщо на початку заяви, щоб спіймати ці випадки? Здається, я таким чином втрачу багато землі.
mellamokb

0

05AB1E , 19 байт

#D`ULX.Œʒ€gßĀ}gs_P+

ПРИМІТКА. Це надзвичайно повільно, і це вже вичерпано 12 4. Хоча це працює як задумано. Побачимо, чи можу я придумати альтернативний метод, який працює у всіх тестових випадках у розумні строки. Дивіться нижче для набагато швидшої версії, яка запускає всі тестові справи менше ніж за секунду.

Спробуйте в Інтернеті або перевірте ще кілька (з менших) тестових випадків .

Пояснення:

#               # Split the (implicit) input-string by spaces
 D              # Duplicate it
  `             # Push both values to the stack
   U            # Pop and store the second value in variable `X`
    L           # Create a list in the range [1,n] for the first value
     X        # Create a list of all possible ways to divide this list into `X` partitions
                # (including empty sublists, so we'll have to filter them out:)
        ʒ       # Filter this list of lists of partition-lists by:
         g     #  Get the length of each partition-list
           ß    #  Get the minimum length
            Ā   #  Truthify; 0 remains 0 (falsey); anything else becomes 1 (truthy)
             }g # After the filter, take the length to get the amount left
 s              # Swap so the duplicated input-list is at the top of the stack again
  _             # Check for each value if they're equal to 0 (1 if truthy; 0 if falsey)
   P            # Take the product of the two to check if both input-values are 0
    +           # And add it to the earlier calculated product (edge case for [0,0] = 1)
                # (After which the result is output implicitly)

05AB1E , 29 байт

Ось набагато швидша версія, яка працює для всіх тестових випадків приблизно за 0,5 секунди на TIO:

Î#R`V©LRvyYmX*NÈ·<*+Xy*®y->÷U

Відповідь JavaScript на порт @mellamokb , тому обов'язково підтримайте його!

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

Î                    # Push (result=) 0 and the input
 #                   # Split the input by spaces
  R`                 # Push the values to the stack reversed
    V                # Pop and store the first value in variable `Y`
     ©               # Store the second value in variable `®` (without popping)
      LRv            # Loop `y` in the range [`®`,1], with index `N` in the range [0,`®`):
         yYm         #  Calculate `y` to the power `Y`
            X*       #  Multiply it by `X`
                     #  (Note: `X` is 1 before setting it to another value initially)
              NÈ     #  Check if index `N` is even (1 if truthy; 0 if falsey)
                ·<   #  Double it; and decrease it by 1 (1 if truthy; -1 if falseY0
                  *  #  Multiply it to the earlier number
                   + #  And add it to the result
         Xy*         #  Push `X` multiplied by `y`
         ®y->        #  Push `®` - `y` + 1
             ÷       #  Integer divide them
              U      #  Pop and store it as new variable `X`
                     # (output the result at the top of the stack implicitly after the loop)

ПРИМІТКА. 0 0У цьому випадку працює крайовий випадок (на відміну від відповіді JavaScript, з якого я переніс цей метод), оскільки Lвбудований створить список [0,1].

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.