Код гольфа: раздача мячей (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

Ограничения

  • Каждые А и В могут быть различимы.
  • 0 <= A, B <= 20
  • Вы можете использовать любой язык на ваш выбор
  • Самое короткое решение побеждает!

1
Есть ли ограничения по времени?

@Tim Nordenfur: Обновлено :-)
Quixotic

Эта ссылка недействительна для меня.
mellamokb

3
@Debanjan Мне не нравится идея вставлять вопросы от SPOJ здесь. Люди подают свой код для участия в соревнованиях, и это было бы несправедливо по отношению к ним.
fR0DDY

1
@Debanjan, я вижу вашу ссылку и поднимаю MathWorld (уравнение. 5 говорит , что S(n,0)это 1если n=0и в 0противном случае). Если хотите, я могу найти ссылку на более сильное утверждение, что Stirling2 находится в ассоциативной подгруппе экспоненциальной группы Риордана.
Питер Тейлор

Ответы:


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 символа)


Вы можете использовать оболочку spidermonkey - по крайней мере, имеет readlineи print. Я не знаю, что здесь используют другие.
Джесси Милликен

@Jesse: интересно. Я все равно проиграю лол.
mellamokb

promptи alertявляются «стандартными» JavaScript для io, так как они являются типичными блокирующими io-вызовами, несмотря на тот факт, что вы никогда не будете использовать блокировку io в JavaScript.
zzzzBov

4

Golfscript - 56 50 49 48 41 40 38 37 символов

n%{~),{!}%\{0.@{.@+2$*@)@}/;;]}*)p;}/

Примечание: это обрабатывает несколько строк ввода, быстро (1/8 секунды, чтобы выполнить тестовые случаи) и не прерывается для любого легального ввода.

(Первая версия была также моей первой в истории программой Golfscript; спасибо eBusiness за указание на несколько уловок, которые я пропустил).

Чтобы сделать этот пост полезным, вот объяснение того, как оно работает. Начнем с повторения 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+1th-й строки этой сетки. Изначально стек есть n k.
),дает стек n [0 1 2 ... k]
{!}%дает стек, n [1 0 0 ... 0]где есть k0.
\{ <<MORE STUFF>> }*приводит nк вершине и делает это количество раз, которое мы выполняем <<MORE STUFF>>.
Наш стек в настоящее время является строкой таблицы: [f(i,0) f(i,1) ... f(i,k)]
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)и собирает все в массив, готовый к следующему обходу цикла.
Наконец, когда мы сгенерировали nth-ю строку таблицы,
)p;берём последний элемент, печатаем его и отбрасываем оставшуюся часть строки.

Для потомков три 38-символьных решения по этому принципу:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/


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

1
+1, я не понимаю Golfscript, но это выглядит достаточно быстро, но очень коротко.
Quixotic

@eBusiness и @Peter Taylor: С другой стороны ... насколько вы, ребята, оцениваете Golfscript по шкале лёгкости в освоении?
Quixotic

@Debanjan, зависит от того, что ты уже знаешь. Это функциональный язык на основе стека. Я раньше использовал функциональные языки (SML - плюс я написал код функционального стиля на языках OO), и раньше я использовал языки на основе стека (Java-байт-код, собранный с Jasmin, PostScript), поэтому единственное реальное препятствие Я сталкиваюсь с изучением того, какие операторы доступны. Если вы знаете только языки из семейства Algol (C, Java и т. Д.), Вам придется прыгнуть сразу через три препятствия.
Питер Тейлор

@Debanjan - это гораздо проще, чем кажется, вы можете начать писать код практически сразу, но, конечно, требуется некоторое время, чтобы выучить все маленькие хитрости.
аааааааааааа

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 является векторным языком, он выполняет вычисления для всего ввода в целом и возвращает его как одномерный вектор, представление которого по умолчанию находится в одной строке). Я считаю, что все в порядке, дух этой проблемы - вычисления, а не представление. Но если вы настаиваете на использовании новых строк:
  • 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

Если вы проголосовали за это, вы, возможно, захотите и отдать должное решению Eelvex .


Вам нужен Under, &.чтобы он правильно работал в интерактивном режиме.
Eelvex

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

Наши коды объединены: 4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3. 39 символов
Eelvex

Без echo или 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 секунд на моей машине.

Решение серии Light-force (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). Вход на стандартный вывод, вывод на стандартный вывод.

Скрипт Bash Test:

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

Что делает этот J6xx wd?
JB

Я действительно имел в виду j602 ... Я предполагаю, что это также в j601. Это определяется как echo, который определяется как 0 0&$@(1!:2&2). Я не уверен, что это значит, но он делает что-то вроде довольно печатных элементов ранга 1 с разрывом строки. (Я только сейчас заметил, что использует 2, а не 4 ... Я думаю, что он по-прежнему идет на стандартный вывод в консольном режиме, по крайней мере.)
Джесси Милликен

У меня проблемы с запуском этого кода. Должен ли я просто ввести его в консоль?
mellamokb

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

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

2

Golfscript - 26 символов

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

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

Очевидно, у этого ответа есть некоторые проблемы, но я оставлю его здесь, потому что комментарии относятся к нему, а ответ mellamokb основан на нем.

Golfscript - 24 символа

Предупреждение: корпус 12 4 требует много памяти и требует много времени для запуска

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

2
Я не могу понять, как вы пришли к этому коду, не только у этого метода не хватит памяти для больших входов, я также не могу понять, для чего нужны операторы приращения. То, что вы на самом деле попали в цель на 6 3, похоже, не что иное, как удача.
аааааааааааа

Это не клоун, это моя жена!
Джесси Милликен

2
Я не понимаю Golfscript, но, как вы сказали, я согласен, что ваш подход слишком медленный.
Quixotic

3
@mellamokb, хорошо, что вы решили, как это должно работать :) Для исправления этой ошибки потребовалось всего 2 дополнительных символа. Теперь мы находимся в темном районе, где самый короткий код может быть правильным, но не практичным. Код-гольф полон безумно неэффективных ответов, но микросекунды против секунд обычно не имеют значения. Это крайний случай ( много памяти тоже). Debanjan указал , что ответы должны быть быстрее, но этот сайт не SPOJ, этот вопрос является меченый код-гольф
gnibbler

1
@gnibbler, 0 0должен производить 1; 0 kдля любого другого kследует производить 0; n 1ибо n > 0должен производить 1.
Питер Тейлор

2

Python 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 не поддерживается ideone. Там может быть персонаж или два еще выжать, но это время сна.

Примечание: он поддерживает несколько строк ввода, имеет достаточную точность, чтобы дать правильный вывод даже для 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. И, возможно, вы можете сохранить кучу других символов в целом, но я подожду, пока он будет короче, чтобы понять его.
Набб

@ Набб, ах, я недостаточно внимательно прочитал справочную страницу. Я использую только 8 или 9 регистров, поэтому я не столкнулся с последствиями своего недопонимания. Спасибо.
Питер Тейлор

1

Golfscript (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], числа 0-27 в формате base-3 имеют длину менее 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любом n, заставляет его висеть. хм ..
mellamokb

1
Преобразование чисел в базу 1 сделает это :)
gnibbler

@gnibbler: Есть ли у вас какие-либо предложения? Должен ли я просто добавить некоторые операторы if в начале, чтобы поймать эти случаи? Похоже, таким образом я потеряю много сил.
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

Порт @mellamokb ответ JavaScript , так что не забудьте поднять его!

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

Î                    # 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.