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:)それを元の入力リストに適用する方法がいくつかあります。(つまり、「このボックス化された配列は、深さ 1 でボックス化された最初の要素、深さ 1 でボックス化された 2 番目の要素、深さ 1 で一緒にボックス化された 3 番目、4 番目、および 5 番目の要素、...、そこのボックス化されていないリストを取得します。同じようにボックスに入れます。") ;.S:L:、をいじってその動作を生成しようL.&.しましたが、うまくいきませんでした。これを実現するために、私が見逃しているある種の演算子または原則はありますか? 問題全体を考えすぎていたとしても驚かないでしょうが、アイデアが不足しています。

編集:

現時点で、私が持っている唯一の実用的な解決策はこれです:

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

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

これは、リストのランレングス エンコーディングを生成し、ボックスを削除せずにエンコーディングを元に戻す 2 段階のプロセスです。もともとJとHaskellを使って99問を連立で解こうと思ってやっているので、12問を先に解いて9問を解けばいいのか、という感じです。

4

3 に答える 3

2

もうすぐです。を追加し~、括弧を別の方法で配置します。これで完了です。

   (<;.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)。あるいは、これをフォークとして暗黙のうちに書くこともできます(f g ]) s

詳細については、「Learning 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、リストに適用し、その先頭を別のリストに移動し、元のリストの先頭を切って、元のリストが完全に空になるまでそれを続けることです。その論理を暗黙の表現で表現する方法が本当にあるべきだと思います。(実際、オンライン ドキュメントでも見たことがあると思います。)最後の釘を棺桶に入れる必要がある、 ^:$:の適切な順序が思い浮かびません。@.

于 2010-06-06T19:14:54.587 に答える