高尔夫代码:发球(I)


12

挑战

在此任务中,您计算​​了将A球分配到B单元中的方式的数量,每个单元至少有一个球。

输入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
有时间限制吗?

@Tim Nordenfur:更新:-)
堂吉诃德式的

该链接对我无效。
mellamokb 2011年

3
@Debanjan我不喜欢在这里粘贴来自SPOJ的问题的想法。人们提交自己的代码以参加比赛,这对他们来说是不公平的。
fR0DDY 2011年

1
@Debanjan,我看到你的参考,提高你Mathworld(公式5说S(n,0)1如果n=00其他)。如果需要,我可以找到一个更强的陈述的参考资料,即Stirling2在指数Riordan组的关联子组中。
彼得·泰勒

Answers:


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*=-1for; 开始r=1合并作业,并在返回时删除无关的作业。(节省3个字符)


您可以使用Spidermonkey shell-至少具有readlineand print。我不知道这里的其他人在用什么。
杰西·米利坎

@Jesse:有趣。无论如何我都会迷路的。
mellamokb

prompt并且alert是JavaScript的“标准” io,因为它们是典型的阻塞io调用,尽管事实上您通常不会在JavaScript中使用阻塞io。
zzzzBov 2011年

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>> }/

将输入分为几行,然后为每一行求值,将nk放在堆栈上,然后调用<<STUFF>>,如下所示:

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

这将计算该网格k+1n+1第th行的第一个条目。最初的堆栈是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.@在该数组之前放置两个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表的第t行时,
)p;获取最后一个元素,将其打印,然后丢弃该行的其余部分。

对于后代,基于此原理的三个38个字符的解决方案:
n%{~),{!}%\{0.@{.@+@.@*\)@}/;;]}*)p;}/
n%{~),{!}%\{0:x\{x\:x+1$*\)}/;]}*)p;}/
n%{~),{!}%\{0.@{@1$+2$*\@)}/;;]}*)p;}/


1
对于初学者来说非常不错,可以进行一些小规模的缩减,我立即找到[0]-> 1,,就可以删除zip之后的空格,而如果只是存储在运算符中而不是k则可以删除其他空格。我还没有遍历您的代码,但是我怀疑您可能只使用一个值而不将其放在某些位置的数组中而无法使用。
aaaaaaaaaaaaa

1
+1,我听不懂Golfscript,但这看起来足够快,但很短。
Quixotic

@eBusiness和@Peter Taylor:不同的是..你们对Golfscript的易学程度评价多少?
Quixotic

@Debanjan,取决于您已经知道的内容。这是一种基于堆栈的功能性语言。我以前使用过一种功能语言(SML-再加上我已经用OO语言编写了功能样式代码),并且我曾经使用过基于堆栈的语言(Java字节码与Jasmin,PostScript组合在一起),因此这是唯一的障碍我面对的是学习可用的运算符。如果您仅了解Algol家族的语言(C,Java等),那么您将有三个障碍需要一次跳跃。
Peter Taylor

@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

普通Lisp(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个较长的交互式控件:用Under()4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)3
    替换Compose&)将返回一个字符串向量,该字符串的显示结果以单独的行结尾。&.
  • 42批处理模式:4 :'echo|-/(!&y*^&x)i.1x+y'/&".;._2(1!:1)3
    从命令行运行为$ jconsole balls.ijs < balls.in

如果您对此表示赞成,那么您可能还想赞扬Eelvex的解决方案


您需要一个Under &.才能在交互模式下正常工作。
Eelvex 2011年

@Eelvex您必须对“正确”有不同的解释。我启动jconsole,粘贴代码,粘贴输入,Cd,并接收输出。没有需要。你的是啥呢?
JB

我们的代码组合为:4 :'|-/(!&y*^&x)i.1x+y'/&.".;._2(1!:1)339个字符。
Eelvex 2011年

如果没有echoUnder,则仅在一行中输出(而不是多行)。
Eelvex 2011年

确实是@Eelvex,但这不是明确禁止的。
JB

3

GolfScript- 45 38 36个字符

中型脏实施重复关系(38 36个字符):

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

我从Peter Taylors解决方案中窃取的递归关系如下所示:

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上输出。

Bash测试脚本:

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 2011年

2

Golfscript-26个字符

警告:12 4例需要大量内存(尽管不如下面的答案那么多),并且运行需要相当长的时间

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

显然,这个答案有一些问题,但是我将其留在此处,因为评论是针对它的,而mellamokb的答案就是基于它的。

Golfscript-24个字符

警告:12 4外壳需要大量内存,并且需要花费相当长的时间才能运行

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

2
我无法弄清楚您是如何编写该代码的,不仅对于大型输入,此方法将耗尽内存,而且也无法弄清楚增量运算符的用途。实际击中目标6 3似乎只是运气。
aaaaaaaaaaaa

那不是小丑,那是我的妻子!
杰西·米利坎

2
我不了解Golfscript,但正如您所说,我同意您的方法太慢。
Quixotic

3
@mellamokb,对您应该如何工作很有帮助:)只需花费两个额外的字符即可解决该错误。现在我们处于最阴暗的地方,最短的代码可能是正确的,但是不切实际。代码高尔夫球充满了效率低下的疯狂答案,但微秒与秒通常无关紧要。这是一个极端的情况(也有很多内存)。Debanjan表明,答案必须要快,但本网站 SPOJ,这个问题标记代码高尔夫
gnibbler

1
@gnibbler,0 0应该产生10 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

DC,100个字符

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

las,ideone似乎不支持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(如果您始终不打算更改精度K0则可以将其用作单个字符标记)。您可以将输入循环更改为?[...?z1=4]。您可以在register中内联宏1。通常,您可能可以为堆节省更多字符,但是我将等待它缩短以便理解。
2011年

@Nabb,啊,我没有足够仔细地阅读手册页。我只使用8或9个寄存器,所以没有遇到误解的后果。谢谢。
彼得·泰勒

1

高尔夫球稿(28 31 37

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

修改gnibbler的GolfScript解决方案。我认为这是一个可行的解决方案-使用[3,2],[4,2],[6,3]和[9,2]进行了正确的答案测试。(我使用$@用于变量来缩小base关键字周围的空间)。

gnibbler当前的解决方案存在两个问题。

  1. 删除[0]之后检查长度不能保证解决方案,因为即使所有4个球都在同一个单元格(1)中,[1,1,1,1]对于输入[4,2]也将有效。因此,我进行了修改以检查是否也使用了所有数字,即数组包含1-2,因此每个单元格至少包含一个球。
  2. 在输入[4,2]的情况下,数字0-27的以3为基的格式小于4位,并且不包括最左边的0。这意味着[1,1]被包括为有效的解决方案,即使从技术上来说实际上是[0,0,1,1],这意味着前两个球没有放置在任何地方。我通过在每个条目上添加3 ^ 3(通常是在k ^ n个条目的数组中添加k ^ n-1)来解决问题,以便使第一个条目向上移动以具有以k为基数格式的至少n位数字,最后一个条目无论如何都会自动无效,并且不会影响解决方案(因为第二个数字始终为0)。

编辑

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

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

更好的解决方案了!无需增加,只需将所有数字相加,使它们以[1]开头,并且在对第一个数字进行解构后就不会丢失任何数字(包括0的左填充)。该解决方案应该可以使用,并且已经在上面的相同条目中​​进行了测试。它的速度也快得多,因为在采用指数生成数组之前我们不需要增加(但是对于较大的输入,仍然会遇到相同的性能/内存问题)。

编辑:使用gnibbler的想法,将$过滤器内部的附加项移动而不是额外的步骤。(节省3个字符)。


输入中断0 0
彼得·泰勒

似乎也只能处理一行输入。
彼得·泰勒

并中断n 1任何n,导致其挂起。嗯..
mellamokb 2011年

1
将数字转换为基数将做到这一点:)
gnibbler 2011年

@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 个字节

这是一个更快的版本,可在TIO上约0.5秒内适用于所有测试用例:

Î#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内置将创建一个list [0,1]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.