4

我一直在研究一个 J 函数,它应该扫描一个列表并将一个元素的连续副本放入单独的连接框中。我的努力已经把我带到了功能

(<;. 2) ((2&(~:/\)),1:)

它测试连续列表条目的不等式,返回布尔值列表,并将列表切割成每次出现数字 1 时结束的框。这是一个示例应用程序:

   (<;. 2) ((2&(~:/\)),1:) 1 2 3 3 3 4 1 1 1
+-+-+-----+-+-----+
|1|1|0 0 1|1|0 0 1|
+-+-+-----+-+-----+

如果我可以用输入参数中的相应值替换所有这些布尔值,那么任务就完成了。我一直在寻找某种神秘的功能,可以让我做类似的事情

   final =: mysteryfunction @ (<;. 2) ((2&(~:/\)),1:)

   final 1 2 3 3 3 4 1 1 1    
+-+-+-----+-+-----+
|1|2|3 3 3|4|1 1 1|
+-+-+-----+-+-----+

在理想情况下,将有某种方法可以抽象地表示由生成的嵌套模式(<;. 2) ((2&(~:/\)),1:)并将其应用于原始输入列表。(即“这里的装箱数组的第一个元素在深度一装箱,第二个元素在深度一装箱,第三、第四和第五个元素在深度一装箱......,所以把那个未装箱的列表放在那里并以相同的方式将其装箱。”)我尝试使用;., S:, L:,L.&.产生这种行为,但我没有太多运气。是否有某种我缺少的运算符或原则可以使这种情况发生?如果我过度思考整个问题,我不会感到惊讶,但我已经没有想法了。

编辑:

目前,我唯一可行的解​​决方案是这个:

isduplicate =: ((2&(~:/\)),1:)

testfun =: 3 : 0
numduplicates =. #S:0 ((<;.2) isduplicate y)
distinctboxes =. <"0 (isduplicate#]) y
numduplicates # each distinctboxes
)

这是一个两步过程,生成列表的游程编码,然后撤消编码而不删除框。由于我最初这样做的目的是使用 J 和 Haskell 一起解决99 个问题,所以如果我通过首先解决问题 12 来解决问题 9,感觉就像在乞求这个问题。

4

3 回答 3

2

您快到了。添加 a~并以不同的方式放置括号,就是这样:

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

快速解释/插图:

   s =: 1 2 3 3 3 4 1 1 1

   f =: 2&(~:/\) , 1:
   f s
1 1 0 0 1 1 0 0 1

   g =: <;.2

   (f s) g s
┌─┬─┬─────┬─┬─────┐
│1│2│3 3 3│4│1 1 1│
└─┴─┴─────┴─┴─────┘

现在 final (f s) g s,有时被称为“左钩子”,可以写出来(g~ f) s(副词~在 J 中被称为“被动”,Haskell 对应的是flip)。或者,您也可以默认将其写为 fork (f g ]) s

如果您想了解更多信息,“学习 J”的第 9 章会广泛讨论这个主题。

更新:我以前使用过基于分组的方法(</.~ (+/\&(1,(2&(~:/\))))),但是您原来的基于剪切的方法比这更优雅(也更短)。因为这真的是关于左勾拳,所以我更新为直接使用你的方法。

于 2010-06-14T03:13:28.390 回答
1

我觉得你想多了。需要完全默契吗?这是我刚刚拼凑起来的东西:

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

显然它只是将输入列表分配给 s 然后将其放入;.表达式中。如果它需要完全默认,我相信你可以按摩它以将输入列表分解为布尔列表,然后使用类似{. < ;.2 {:的东西来获取输出。

于 2010-06-14T01:06:02.803 回答
0

我心目中的这个版本的功能更好,但还是不够默契完美。(至少它不会为未来的另一个问题提出问题,无论如何。)一旦我弄清楚如何将 while 循环的逻辑表示为默认表达式,我就准备好了。

NB. boxmerge takes a boxed argument and razes the first two
NB. elements together into a new box.
boxmerge =: [:}.]1}~[:<[:;2&{.

NB. conseq checks to see whether the first two boxes of a boxed
NB. array contain the same distinct element. (By assumption, each
NB. box contains only one distinct element.) The name is an
NB. abbreviation of the question, "consecutive boxes equal?"
conseq =: [:=/[:~.&.>2&{.

partfun =: ]`(boxmerge)@.conseq ^:_

listpack =: 3 : 0
mylist =. y
listbin =. >a:
while. (mylist -: (>a:)) = 0 do.
 newlist =. partfun mylist
 listbin =. listbin,{. newlist
 mylist =. }. newlist
end.
listbin
)

while 循环背后的想法是应用于partfun一个列表,将它的头放到另一个列表上,斩首原始列表,然后继续这样做,直到原始列表完全清空。我觉得真的应该有一种方法可以用默认的表达方式来表示这种逻辑。(实际上,我想我什至在在线文档中都看到过。)我只是想不出合适的^:'s、$:'s 和@.'s 顺序,我需要把最后一颗钉子钉在棺材里。

于 2010-06-06T19:14:54.587 回答