完全な答えはまだありませんが、 Roger Hui によるこのエッセイには、明示的な while ループを置き換えるために使用できる暗黙の構文があります。別の (関連する) 手段は、ブロックの内部ロジックを次のような暗黙の式にすることです。
FUNWITHTACIT =: ] , {: + {: +. 1 + #
rowland =: monad define
result =. >a:
t =. 7x
while. (# result) < y do.
t =. FUNWITHTACIT t
d =. | -/ _2 {. t
result =. ~.result,((d>1)#d)
end.
result
)
result
(ただし、条件が満たされているかどうかに関係なく変更されるような方法でコードを記述したため、効率のために if ブロックを保持したい場合があります。満たされていない場合、変更は効果がありません。 if
Agenda 演算子を使用して、ロジックを暗黙の式に書き戻すこともできます。)
完全な解決策は、while ループ内のすべてのロジックを 1 つの関数として表現する方法を見つけてから、ロジャーのトリックを使用して while ロジックを暗黙の式として実装することです。何ができるか見てみます。
余談FUNWITHTACIT
ですが、コードの最初の数行を取り、宣言した変数値の関数を手動で置き換えることで、J をビルドしてもらいました (これらはすべて単一の引数でさまざまな方法で操作されていたため、これを行うことができました)。のすべてのインスタンスをt
withに置き換え、y
J に結果の式の暗黙の等価物を構築するように指示しました。
]FUNWITHTACIT =: 13 : 'y,({:y)+(1+#y)+.({:y)'
] , {: + {: +. 1 + #
モナドを宣言するために 13 を使用することは、J がモナドを取り (それ以外の場合は で明示的に宣言する3 : 0
かmonad define
、プログラムで記述したように)、明示的な式を暗黙的な式に変換する方法を知っている方法です。
編集:
コメントで言及したアベニュー(2)用に書いた関数は次のとおりです。
candfun =: 3 : '(] , {: + {: +. 1 + #)^:(y) 7'
firstdiff =: [: | 2 -/\ ]
triage =: [: /:~ [: ~. 1&~: # ]
rowland2 =: triage @firstdiff @candfun
この関数は、Rowland 再帰関係を使用して最初の n 個の候補番号を生成し、それらの最初の差分を評価し、1 に等しいすべての最初の差分を破棄し、すべての重複を破棄し、それらを昇順に並べ替えます。引数は結果の数ではなく、試行する候補の数を設定するため、まだ完全に満足できるものではないと思います。しかし、それはまだ進歩です。
例:
rowland2 1000
3 5 7 11 13 23 47 101 233 467 941
これは私が投稿した最初の関数のバージョンで、各引数のサイズを最小限に抑えています:
NB. rowrec takes y=(n,an) where n is the index and a(n) is the
NB. nth member of the rowland candidate sequence. The base case
NB. is rowrec 1 7. The output is (n+1,a(n+1)).
rowrec =: (1 + {.) , }. + [: +./ 1 0 + ]
rowland3 =: 3 : 0
result =. >a:
t =. 1 7
while. y > #result do.
ts =. (<"1)2 2 $ t,rowrec t
fdiff =. |2-/\,>(}.&.>) ts
if. 1~:fdiff do.
result =. ~. result,fdiff
end.
t =. ,>}.ts
end.
/:~ result
)
最初の y 個の異なるローランド素数を見つけ、それらを昇順に表示します。
rowland3 20
3 5 7 11 13 23 47 53 101 233 467 941 1889 3779 7559 15131 30323 60647 121403 242807
この関数の複雑さのほとんどは、ボックス化された配列の処理に起因しています。これはきれいなコードではありませんが、4+#result
計算中に多くのデータ要素 (対数スケールで増加) をメモリに保持するだけです。元の関数は要素をメモリにrowland
保持(#t)+(#result)
します (線形スケールで増加します)。rowland2 y
-many 要素の配列を構築します。これにより、メモリ プロファイルは、指定された境界を超えて大きくならない場合y
とほぼ同じになります。rowland
私rowland2
はそのコンパクトさを気に入っていy
ますが、 n 個の異なる素数を生成するために必要な の正確なサイズを予測する式がなければ、そのタスクは試行錯誤に基づいて実行する必要があり、したがって、rowland
またはrowland3
よりも多くのサイクルを使用する可能性があります。冗長な計算。rowland3
は、ループの反復ごとに再計算するrowland
ため、私のバージョンの よりもおそらく効率的です。カウンターをインクリメントするだけで、計算量が少なくなります。FUNWITHTACIT
#t
rowland3
それでも、私はrowland3
の明示的な制御構造には満足していません。再帰などを使用してこの動作を実現する方法があるはずです。