1

由于我是 J 的初学者,我决定使用这种语言解决一个简单的任务,特别是实现冒泡排序算法。我知道在函数式语言中解决此类问题并不是惯用的,因为在 C 等命令式语言中使用数组元素转置自然地解决了它,而不是在声明性语言中构造修改后的列表。然而,这是我写的代码:

    (((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)) ^: #

这是语句的结构:

┌────────────────────────────────────────────────────────────────────────────┬──┬─┐
│┌───────────────────────────────────────────────────────────────┬──┬───────┐│^:│#│
││┌───────────────────┬─┬───────────────────────────────────────┐│^:│┌─┬─┬─┐││  │ │
│││┌──────┬─┬────────┐│,│┌──┬─┬────────────────────────────────┐││  ││1│&lt;│#│││  │ │
││││┌──┬─┐│@│┌─┬─┬──┐││ ││$:│@│┌───────────────────┬─┬────────┐│││  │└─┴─┴─┘││  │ │
│││││&lt;.│/││ ││2│&amp;│{.│││ ││  │ ││┌──────┬─┬────────┐│,│┌─┬─┬──┐││││  │       ││  │ │
││││└──┴─┘│ │└─┴─┴──┘││ ││  │ │││┌──┬─┐│@│┌─┬─┬──┐││ ││2│&amp;│}.│││││  │       ││  │ │
│││└──────┴─┴────────┘│ ││  │ ││││>.│/││ ││2│&amp;│{.│││ │└─┴─┴──┘││││  │       ││  │ │
│││                   │ ││  │ │││└──┴─┘│ │└─┴─┴──┘││ │        ││││  │       ││  │ │
│││                   │ ││  │ ││└──────┴─┴────────┘│ │        ││││  │       ││  │ │
│││                   │ ││  │ │└───────────────────┴─┴────────┘│││  │       ││  │ │
│││                   │ │└──┴─┴────────────────────────────────┘││  │       ││  │ │
││└───────────────────┴─┴───────────────────────────────────────┘│  │       ││  │ │
│└───────────────────────────────────────────────────────────────┴──┴───────┘│  │ │
└────────────────────────────────────────────────────────────────────────────┴──┴─┘

让我们将其应用于数组:

    (((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)) ^: # 5 3 8 7 2
2 3 5 7 8

让我感到困惑的是$:指最外面的括号内的陈述。帮助说:

$:表示包含它的最长动词。

另一本书(~300 KiB)说:

    3+4 
7  
    5*20  
100  

上述短语中加号时间的+ 和 * 等符号称为动词,表示功能。J 短语中可能有多个动词,在这种情况下,它就像简单英语中的句子一样,从左到右阅读,即 添加到后面的任何内容,4+6%2即除以。462

让我们重写我的代码片段,省略最外层()

    ((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#) ^: # 5 3 8 7 2
2 3 5 7 8

结果是一样的。我无法解释自己为什么这样有效,为什么 only((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)被视为最长的动词$:而不是整个表达式((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#) ^: #,而不仅仅是(<./@(2&{.)), $:@((>./@(2&{.)),2&}.),因为如果((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)是动词,它还应该在与 连词后形成另一个动词#,即一个人可能会对待整个句子(第一个片段)作为动词。一个连词限制的动词长度可能有一些限制。

看下面的代码(从这里):

    factorial =: (* factorial@<:) ^: (1&<)
    factorial 4
24

factorialwithin 表达式是指整个函数,即(* factorial@<:) ^: (1&<).

在此示例之后,我使用了函数名称而不是$:

    bubblesort =: (((<./@(2&{.)), bubblesort@((>./@(2&{.)),2&}.)) ^: (1<#)) ^: #
    bubblesort 5 3 8 7 2
2 3 5 7 8

我希望bubblesort引用整个函数,但对我来说似乎并不正确,因为结果是正确的。

如果您有其他实现,我还想看看其他实现,甚至稍微重构。

谢谢。

4

3 回答 3

1

我正在调查它。同时,您实施冒泡排序是因为您特别需要冒泡排序,还是因为您只是需要一种排序(即您可以改用冒泡排序/:~)?

编辑:您是否尝试过在像这样的数据集上运行冒泡排序3 1 2 9 2 9 86 5 9 6 9 6 45?当我在我的机器上尝试它时系统挂起,但如果你用 _ 替换结尾的 # 就可以了。

于 2010-05-08T10:29:14.050 回答
1

根据这个参考(175 KiB) ,合是:

接受两个论点并通常产生一个动词的词性。例如,*:^:3是一个迭代平方三次的函数(^:是一个连词)。

由于^:属于上述类别,将其应用于参数会导致更长的动词:

((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)

因为$:表示包含它的最长动词,所以指的是上面刚刚写的代码。

同样,下一个从and^:生成一个新的更长的动词: ((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)#

(((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)) ^: #

这反过来又被称为,$:因为它比前一个更长。

由于这是不受欢迎的行为,可能唯一的解决方案是拆分整个动词,以便$:指代((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)虽然它不是单行符:

    bubbleiter =: ((<./@(2&{.)), $:@((>./@(2&{.)),2&}.)) ^: (1<#)
    bubblesort =: bubbleiter ^: #
    bubblesort 3 1 2 9 2 9 86 5 9 6 9 6 45
1 2 2 3 5 6 6 9 9 9 9 45 86

这篇文章有一些评论$:

解释$:(自我引用)是什么以及如何使用它对于一些完全不熟悉该语言的人来说是一个相当不幸的起点,因为这是一个高级功能,并且与 J. John 中通常的做法不同提到 Roger 曾评论说,如果他现在正在设计该语言,他将不会包含此内容。

再次总结一下:

  • ^:是一个连词,并从它的论点组成一个新动词;
  • $:表示包含它的最长动词。

感谢飞到estanford3 1 2 9 2 9 86 5 9 6 9 6 45在他的回答中获取数据集。

于 2010-05-09T02:37:10.173 回答
0

这是在 J 中实现冒泡排序的另一种方法:http ://rosettacode.org/wiki/Sorting_algorithms/Bubble_sort#J

于 2011-02-24T13:18:17.990 回答