私は 4clojure.com から 45 の問題を解決しましたが、再帰とアキュムレータを使用していくつかの問題を解決しようとしているときに、繰り返し発生する問題に気付きました。
一部のClojurerが私が得ていないものを「得る」ことを期待して、醜い解決策に終わるために私がしていることをできる限り説明しようとします。
たとえば、問題 34 では、2 つの整数を引数として ( rangeを使用せずに) 関数を作成し、( range を使用せずに) 範囲を作成するよう求めています。簡単に言えば、(... 1 7) を実行すると、(1 2 3 4 5 6) が得られます。
さて、この質問は、この特定の問題を解決することではありません。
再帰とアキュムレータを使用してこれを解決したい場合はどうすればよいですか?
私の思考プロセスは次のようになります。
(fn [xy] )で始まる、2 つの引数を取る関数を作成する必要があります。
再帰する必要があり、リストを追跡する必要があります。アキュムレータを使用するので、追加の引数を取る最初の関数内に 2 番目の関数を記述します。
(fn [xy]
((fn g [xy acc] ...) x y '())
(明らかに、SO で Clojure コードを適切にフォーマットできません!?)
最初の関数は正確に 2 つの整数引数 (私の呼び出しではない) を取る必要があり、確信が持てません: アキュムレータを使用したい場合、作成せずにアキュムレータを使用できますか?ネストされた関数?
次に、 conjしたいのですが、できません:
(conj 0 1)
そのため、最初にシーケンスを取得するために奇妙なことを行い、最終的には次のようになります。
(fn
[x y]
((fn g [x y acc] (if (= x y) y (conj (conj acc (g (inc x) y acc)) x)))
x
y
'()))
しかし、これはこれを生成します:
(1 (2 (3 4)))
これの代わりに:
(1 2 3 4)
そのため、追加のフラット化を行うことになり、機能しますが、完全に醜いです。
私はいくつかのことを理解し始めており、場合によっては、よりクロジュレスクな方法で「考え」始めていますが、解決策を書くのに問題があります。
たとえば、ここで私は次のように決めました。
- アキュムレータを使用するには
- yに達するまでxをインクリメントして再帰する
しかし、私は上記の怪物になってしまいます。
この問題を解決する方法はたくさんありますが、繰り返しになりますが、それは私が求めているものではありません。
私が求めているのは、cons/conj を決定し、アキュムレータを使用し、再帰することを決定した後、次のようになる方法です (私が書いたものではありません)。
#(loop [i %1
acc nil]
(if (<= %2 i)
(reverse acc)
(recur (inc i) (cons i acc))))
これの代わりに:
((fn
f
[x y]
(flatten
((fn
g
[x y acc]
(if (= x y) acc (conj (conj acc (g (inc x) y acc)) x)))
x
y
'())))
1
4)
いくつかの問題を解決できるようになり始めたと思いますが、私が作成する傾向がある醜い解決策に少しがっかりしています...