私は現在、魅力的なJプログラミング言語を学んでいますが、私が理解できていないことの1つは、リストをフィルタリングする方法です。
任意のリストが3 2 2 7 7 2 9
あり、2を削除したいが、他はすべて変更しないと仮定します。つまり、結果はになります3 7 7 9
。一体どうやってこれを行うのですか?
私は現在、魅力的なJプログラミング言語を学んでいますが、私が理解できていないことの1つは、リストをフィルタリングする方法です。
任意のリストが3 2 2 7 7 2 9
あり、2を削除したいが、他はすべて変更しないと仮定します。つまり、結果はになります3 7 7 9
。一体どうやってこれを行うのですか?
2 (~: # ]) 3 2 2 7 7 2 9
3 7 7 9
私はあなたのために答えを持っています、しかしあなたがいくつかの詳細に精通する前に。どうぞ。
Jには、モナドとダイアドの2種類の動詞があります。前者は1つのパラメーターのみを受け入れ、後者は2つのパラメーターを受け入れます。
たとえば、 tallyと呼ばれる単調動詞に唯一の引数を渡すと、リスト内の要素の数がカウントされます。#
# 3 2 2 7 7 2 9
7
#
2つの引数(左と右)を受け入れる動詞はコピーと呼ばれ、二項であり、左のリストのそれぞれの要素で指定された回数だけ右のリストから要素をコピーするために使用されます(唯一の要素がある場合があります)リストにもあります):
0 0 0 3 0 0 0 # 3 2 2 7 7 2 9
7 7 7
Jにはフォークの概念があります。これは、2項または1項で引数に適用される一連の3つの動詞です。
これは、最初のスニペットで使用した一種のフォークの図です。
x (F G H) y
G
/ \
F H
/ \ / \
x y x y
動詞が引数に適用される順序を説明します。したがって、これらのアプリケーションが発生します。
2 ~: 3 2 2 7 7 2 9
1 0 0 1 1 0 1
この例で~:
は(等しくない)は二項であり、引数が等しくない場合に真となるブール値のリストになります2
。これはF
図によるアプリケーションでした。
次のアプリケーションはH
:
2 ] 3 2 2 7 7 2 9
3 2 2 7 7 2 9
]
(identity)はモナドまたはダイアドにすることができますが、常に動詞に渡された右の引数を返します(反対の動詞が[
あります。これは..はい、左の引数を返します!:)
ここまでは順調ですね。F
アプリケーションがそれH
に応じてこれらの値を返した後:
1 0 0 1 1 0 1
3 2 2 7 7 2 9
実行する唯一のステップは、G
動詞の適用です。
前に述べたように、二項#
(2つの引数を受け入れる)である動詞を使用すると、左の引数のそれぞれの位置で指定された回数だけ、右の引数から項目を複製できます。したがって:
1 0 0 1 1 0 1 # 3 2 2 7 7 2 9
3 7 7 9
sからリストを除外しました2
。
わずかに異なる種類のフォーク、フック、およびその他のプリミティブ(上記のものを含む)は、次の2つのドキュメントで説明されています。
その他の有用な情報源は、ウィキとインターネット上のいくつかのメールリストアーカイブを備えたJsoftwareサイトです。
明確にするために、元の質問に答える直接的な方法は次のとおりです。
3 2 2 7 7 2 9 -. 2
これは
3 7 7 9
より複雑な方法(ブール値を生成し、それを使用してベクトルを圧縮する)は、よりAPLishです。
非常に長い投稿で他の質問に答えるために、最初の要素とそれが発生する回数を返すことは、単にこれです:
({. , {. +/ .= ]) 1 4 1 4 2 1 3 5
1 3
これは「{」を使用したフォークです。最初の項目を取得するには、「{。+ /。=]」を使用して最初の項目が各要素に等しい回数を合計し、「、」を中間の動詞としてこれら2つの部分を連結します。
また:
2 ( -. ~ ]) 3 2 2 7 7 2 9
3 7 7 9
これを行うには何百万もの方法があります-漠然と、これらのものが厳密に右から左に評価されないのは気になります、私は古いAPLプログラマーであり、そうでない場合でも右から左に物事を考える。
ある数を引き出したいプログラムに入れようとしていて、その数が定数である場合、次のようにします。
(#~ 2&~:) 1 3 2 4 2 5
1 3 4 5
これはフックのようなものだと思います。式の右半分は、2ではない真理ベクトルを生成します。次に、左のオクトソープの引数が入れ替わり、真理ベクトルがコピーする左の引数になり、ベクトルが右の引数になります。フックが引数コピー付きのフォークよりも速いか遅いかはわかりません。
+/3<+/"1(=2&{"1)/:~S:_1{;/5 6$1+i.6
156
上記のプログラムは、「Yatzeeサイコロのすべての可能な組み合わせについて、1つのロールに4つまたは5つの一致する数字があるのはいくつですか?」という質問に答えます。ボックス内のすべての順列を生成し、各ボックスを個別に並べ替え、副作用としてボックスを解除し、列2を抽出して、ボックスを独自の列2と比較し、これまでに作成できた唯一の成功したフォークまたはフックを使用します。理論では、5回以上のリストに表示される番号がある場合、リストを並べ替えると、真ん中の番号が最も頻繁に表示される番号になります。私は他の多くのフックやフォークを試しましたが、私が得られないものがあるため、すべてが失敗しました。とにかく、その真理値表はベクトルに還元され、5つのサイコロの各グループが中央値に何回一致したかが正確にわかります。ついに、
このプログラムは、「記号1から5までの可能な8桁の数字すべてについて、繰り返しで、いくつが4で割り切れるのか」という質問に答えます。
最初の25個のうち4で割り切れて乗算できる数を決定するだけでよいことはわかっていますが、プログラムは多かれ少なかれ瞬時に実行されます。ある時点で、私はこのプログラムのはるかに複雑なバージョンを持っていました。これは、個々の桁が0から4の間になるように、基数5の数値を生成し、生成された数値に1を加算して、基数10に入れました。1+(8$5)#:i.5^8
+ / 0 = 4 |、(8 $ 10)#。> {; / 8 5 $ 1 + i.5 78125動詞のトレインと選択だけがある限り、問題はありません。動詞の中で議論を繰り返さなければならないので、フォークとフックを使わざるを得なくなると、迷子になり始めます。
たとえば、これは私が仕事に就けないものです。
((1&{~+/)*./\(=1&{))1 1 1 3 2 4 1
常にインデックスエラーが発生します。
ポイントは、2つの数値を出力することです。1つはリストの最初の数値と同じで、もう1つはその数値が繰り返される回数と同じです。
だからこれはうまくいく:
*./\(=1&{)1 1 1 3 2 4 1
1 1 1 0 0 0 0
最初の数字をリストの残りの部分と比較します。次に、と圧縮を挿入します。これにより、1の文字列が途切れていない限り、1が得られます。これが壊れて失敗し、ゼロが出てくると、
次に、別のペアのセットを追加し、リストからリード要素を再度取得して、それらの数値を何らかの方法で記録できると思いました。最終的なアイデアは、ベクトルの逆を元のリストに適用する別のステージを作成することです。次に、$:を使用して、同じ動詞の再帰的なアプリケーションに戻ります。クイックソートの例のように、私はある程度理解していると思いましたが、理解していないと思います。
しかし、私は近づくことさえできません。人々が答えるために適切な信用を得られるように、私はこれを別の質問として尋ねます。