“保加利亚接龙”是一种数学好奇心。它是一个45级的牌组(任何三角形数字都可以使用)无标记牌。把它们放入随机大小的桩中。然后,要打一个圆形,从每个堆中取出一张牌,并用移除的牌创建一个新的堆。重复此步骤最终会产生配置1 2 3 4 5 6 7 8 9
(对于45张牌),这显然是游戏的固定点,因此也就是单人纸牌的结束。我想在J中模拟这个游戏。
经过几天的思考和一些期待已久的对J gerunds的洞察,我想出了一个解决方案,我希望得到一些意见。它从这个动词开始:
bsol =: ((#~ ~:&0) , #)@:(-&1)^:(<_)
给定一个正整数向量,其和为三角形,这个动词返回一个2级数组,显示结果的轮次。我也想出了这个动词来生成一个初始配置,但我对它不太满意:
t =: 45 & - @ (+/) NB. Would work with any triangular number
cards =: (]`(]@,>:@?&t@]))@.(0&<@t)^:_
给定正整数的向量y
,t
返回45的缺陷,即在参数表示的桩中未计入的卡的数量45 - +/ y
。使用t
,动词cards
会反复向y
这样的向量>: i. t y
添加一个整数,直到缺陷为0。
明确地展开t
,我得到了
cards =: (]`(]@,>:@?&(45 & - @ (+/))@]))@.(0&<@(45 & - @ (+/)))^:_
我觉得这不是很简短,也许过于括号。但它确实有效,完整的解决方案现在看起来像这样:
bsol @ cards @ >: @ ? 44 NB. Choose the first pile randomly from >: i. 44
没有命名动词:
(((#~ ~:&0) , #)@:(-&1)^:(<_)) @: ((]`(]@,>:@?&(45 & - @ (+/))@]))@.(0&<@(45 & - @ (+/)))^:_)@>:@? 44
我不太了解J idiom,我对此有同感:它不是很简短,当然多余(在这里使用像t
这样的本地动词会更好吗,因为它重复了,例如?)并且可能过于括号。我有什么机会改进这个计划?
答案 0 :(得分:2)
您可以使用
改进t
t =: 45 - +/
使用46 - +/
将为您节省一些>:
。
您可以使用递归定义替换cards
:
cards =: }.`(($:@] , -) ?)@.(0&<)
现在,cards n
生成一个总和为n
的初始配置。
在bsol
中,如果删除(-&1
)零,则不需要-.
,并将其重新排列为:
bsol =: (0 -.~ [: (, #) <:)^:(<_)