如何在J中实现分组算法?

时间:2012-03-05 08:53:47

标签: j

我正在尝试在J.中实现A006751。在Haskell中很容易做到,例如:

concat . map (\g -> concat [show $ length g, [g !! 0]]) . group . show

(显然这不完整,但它是它的基本核心。我花了大约10秒钟,所以相应地对待它。)我可以在J中相当容易地实现任何这一点,但是那个躲过我的部分是与Haskell的group函数对应的好的,惯用的J算法。我可以写一个笨拙的,但感觉不好J。

任何人都可以在好的J中实现Haskell的group吗?

2 个答案:

答案 0 :(得分:4)

群组通常使用/.副词完成。

   1 1 2 1 </. 'abcd'
┌───┬─┐
│abd│c│
└───┴─┘

正如您所看到的,它不是连续的。只需按顺序设置你的键顺序(基本上确定一个项目是否与下一项不同,并对结果0和1进行运行总和):

   neq =. 13 : '0, (}. y) ~: (}: y)'
   seqkey =. 13 : '+/\neq y'
   (seqkey 1 1 2 1) </. 'abcd'
┌──┬─┬─┐
│ab│c│d│
└──┴─┴─┘

我需要的是一个对项目(#)进行计数的函数,并告诉我它们是什么({。只选择第一个)。我从nubcount获得了一些灵感:

   diffseqcount =. 13 : ',(seqkey y) (#,{.)/. y'
   diffseqcount 2
1 2
   diffseqcount 1 2
1 1 1 2
   diffseqcount 1 1 1 2
3 1 1 2

如果你想要第n个结果,只需使用电源:

   diffseqcount(^:10) 2  NB. 10th result
1 3 2 1 1 3 2 1 3 2 2 1 1 3 3 1 1 2 1 3 2 1 2 3 2 2 2 1 1 2

答案 1 :(得分:3)

我同意/.(密钥)是将动词应用于J中的群组的最佳通用方法。在这种情况下,我们需要对连续数字进行分组的另一种方法是二元{{1} (剪切):

;.

我们可以将frets用作左参数,如下所示:

   1 1 0 0 1 0 1 <(;.1) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘

把两者放在一起:

   1 , 2 ~:/\ 3 1 1 1 2 2 3   NB. inserts ~: in the running sets of 2 numbers 
1 1 0 0 1 0 1

使用与之前建议相同的机制:

   (] <;.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘

如果您正在寻找一个很好的J实现的外观和说法序列,那么我建议the one on Rosetta Code

   ,@(] (# , {.);.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
1 3 3 1 2 2 1 3