新しいアカウントで始めました。

身の回りの出来事や写真が中心です。

cametan_42さんのブログ、Lispの話題。

2021-10-11 08:45:32 | Ruby

 cametan_42さんが、興味深いこと書かれてます。リンクを張っておきます。最後の方に、再帰のプログラムのことがあります。少しだけやってましたので、Rubyでも出来るだろうか?但し、高校の教科書から持ってきた問題をそのまま、コードにするのは、無理だと思います。一般a(n)を求めるのに、a(n+1)を使っては駄目ではないんでしょうか?数学的な表現ができないので、多分こういうことと推察をお願いします。答えからなら、書けそうです。

多分、等差級数のジェネレータ式と言えると思います。

再帰の最も単純な形だと思います。問題は、同じ計算を繰り返すことだと思います。

 ここからは、「Rubyプログラミング入門」の例にあるもので、同じ計算をしない部類ですが、forを使っている部分ではすると思います。試行錯誤でやってますので、理解できてません。

上も、ほぼもう一個上と同じ部類です。説明できません。(笑)


コメント (4)    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« cametan_42さんの練習問題fou... | トップ | cametan_42さんの練習問題fif... »
最新の画像もっと見る

4 コメント

コメント日が  古い順  |   新しい順
cametan_42さん、コメントありがとうございます (isam)
2021-10-12 19:34:54
 専門的な内容で、理解できませんが、再帰が物事の本質であることがある、らしいことは多少気づいてました。?。昔のことですが、smalltalkはLispなんですか?評判があまり良くない記事を読んで、勉強しないでしまいました。
 Rubyもそうかも知れません、pythonのリスト内包表記なども、そうかも知れません。いろんな書き方ができるので、力が試されるかも、知れませんね。
 
返信する
trace (cametan_42)
2021-10-11 17:49:31
> 再帰の書き方自体は、何度もやっているので、何となく分かるのですが、Eclipseのデバッガでその様子を見ることが出来ません。
> どんどん呼ばれて、最後にリターンが纏まって行われる。スタックが消費される場面ですかね?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のデバッガは、再帰を追うとあっと言う間に「スタックレベルが深すぎる」になって再帰を追いかけるには実用性が低い、と思う)
返信する
cametan_42さん、コメントありがとうございます (isam)
2021-10-11 14:51:25
 数学が苦手なので、気付きませんでした。再帰の書き方自体は、何度もやっているので、何となく分かるのですが、Eclipseのデバッガでその様子を見ることが出来ません。
 どんどん呼ばれて、最後にリターンが纏まって行われる。スタックが消費される場面ですかね?C言語でのデバッグだったかもしれません。
返信する
ちょっとしたトリック (cametan_42)
2021-10-11 14:19:48
> 一般a(n)を求めるのに、a(n+1)を使っては駄目ではないんでしょうか?

うん、そうですね。
ただ、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「だけ」は早めにスタックオーバーフロー起こす可能性が高いですが)
返信する

Ruby」カテゴリの最新記事