cametan_42さんが、興味深いこと書かれてます。リンクを張っておきます。最後の方に、再帰のプログラムのことがあります。少しだけやってましたので、Rubyでも出来るだろうか?但し、高校の教科書から持ってきた問題をそのまま、コードにするのは、無理だと思います。一般a(n)を求めるのに、a(n+1)を使っては駄目ではないんでしょうか?数学的な表現ができないので、多分こういうことと推察をお願いします。答えからなら、書けそうです。
多分、等差級数のジェネレータ式と言えると思います。
再帰の最も単純な形だと思います。問題は、同じ計算を繰り返すことだと思います。
ここからは、「Rubyプログラミング入門」の例にあるもので、同じ計算をしない部類ですが、forを使っている部分ではすると思います。試行錯誤でやってますので、理解できてません。
上も、ほぼもう一個上と同じ部類です。説明できません。(笑)
Rubyもそうかも知れません、pythonのリスト内包表記なども、そうかも知れません。いろんな書き方ができるので、力が試されるかも、知れませんね。
> どんどん呼ばれて、最後にリターンが纏まって行われる。スタックが消費される場面ですかね?C言語でのデバッグだったかもしれません。
比較的、ANSI Common Lispで再帰が学びやすいのは、traceって言うコマンドを内蔵してるから、なんですよね・・・。
っつーか、Common Lispは80年代の言語で、しかもルーツを辿ると50年代、IDEなんかもありませんでした、と言う時代からの開発ノウハウも込みで、その集大成で出来た言語仕様なんで、凄く巨大で(個人情報保護法施行前の電話帳以上の厚さ?)、デバッガなんかも言語仕様に内蔵されてるんですよね・・・・・・・。今だと全部IDEとの連携考えてますが、当時だと「何でも言語本体にツッコんだ」のです。
生憎、まずはPythonにそれがなく、自作trace関数を公開してる人がいました。
・・・とリンク貼りたかったんですが、例によってgoo blogのクソ仕様の為貼れません。
「Python: trace recursive function | Codementor」で検索してみてください。
RubyだとMatz氏自身がLisperの割には(Common Lispのような)traceは実装してない模様です・・・まぁ、Ruby界隈はPython以上に「データ型」とその操作メソッド(イテレータ)が豊富でしょうからね・・・・・・。元々再帰しよう!なんつー人がPython以上にいないと考えられます。
(しかも、手元のRuby2.7のデバッガは、再帰を追うとあっと言う間に「スタックレベルが深すぎる」になって再帰を追いかけるには実用性が低い、と思う)
どんどん呼ばれて、最後にリターンが纏まって行われる。スタックが消費される場面ですかね?C言語でのデバッグだったかもしれません。
うん、そうですね。
ただ、a(n-1)を使っても結果同じなんですよ(笑)。
例えば、
a[1] = 3、 a[n+1] - a[n] - 2 = 0
って漸化式があるとして。
これはこういうことですよね。
a[1] = 3、 a[n+1] = a[n] + 2
後者が問題になってるわけですが。
これって結局、添字をズラシて
a[1] = 3、 a[n] = a[n-1] + 2
としても全く同じなんです。
まぁ数学的トリックって言われればそれまでなんですけどね・・・・・・。
結果、もうちょっとプログラミングぽくすると、上は疑似コード的には
if n == 1
3
else
a[n-1] + 2
って事になって、これを使えばa[n]を定義出来る、と言う事です。
そこまで持ち込めば、Pythonだと
def a(n):
if n == 1:
return 3
else:
return a(n-1) + 2
Rubyだと
def a(n)
if n == 1
3
else
a(n-1) + 2
end
end
Cだと
int a(int n) {
if (n == 1) {
return 3;
} else {
return a(n-1) + 2;
}
}
JavaScriptだと
function a(n) {
if (n == 1) {
return 3;
} else {
return a(n-1) + 2;
}
}
と言うように「全部同じ形式で記述可能」と言うのが再帰の強みです。
(もっともJavaScript「だけ」は早めにスタックオーバーフロー起こす可能性が高いですが)