web-dev-qa-db-ja.com

Adaでの再帰によるボーリングピン(ピラミッド)の描画

私はこれがコミュニティの善意を押し上げていることを知っています。誰かが来て私を救うことを期待して、私の最低限の手の込んだ仕事を提示しますが、失うものは何もありません。過去数週間、パケット、ファイル、タイプ、フラグ、ボックスを調べましたが、再帰についてはあまり取り上げていません。特に再帰的に描画しない。私の試験は約1週間です。ボウリングのピンや他のパターンを描くような簡単な再帰のトリックを繰り返して学ぶには、これが十分な時間であることを願っています。

I I I I I
 I I I I
  I I I
   I I
    I
n = 5

再帰に関して私が抱えている問題は、それを完全に理解できないことです。再帰を使用して、このようなピンを描くような問題にどのように取り組むべきですか?

一番近いのは

I I I
I I
I
n = 3

そしてそれは使用しています

このコードは機能します

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure pyramidchaser is

   subtype X_Type is Integer range 0..30;
   X: X_Type;
   Indent : Integer := 0;

   procedure Numbergrabber (X : out Integer) is
   begin

      Put("Enter a number: ");
      Get(X);
      Skip_Line;
   end Numbergrabber;


   procedure PrintSpaces(I : in Integer) is
   begin 
      if I in X_Type then
      Put(" ");
      else
     return;
      end if;

      PrintSpaces(I - 1);
   end Printspaces;




   procedure PrintPins(i, n: in Integer) is
   begin
      if i >= n then 
     return;
      end if;

    Put('I');
    Put(' '); 

    PrintPins(i + 1, n);
    end Printpins;




   function Pins (X, Indent: in Integer) return Integer is

      Printed : Integer;

   begin

      Printed:= 0;
      if X > 0 then
     PrintSpaces(Indent);
     PrintPins(0, X);
     New_Line; 

     Printed := X + Pins(X - 1, Indent + 1);
      end if;
      return Printed;

   end Pins;

   Bowlingpins : Integer;

begin

   Numbergrabber(X);
   Bowlingpins:= Pins(X, Indent);

end pyramidchaser;




しかし、それで私は合計を投入します。再帰部分を開始するだけで本当に必要はありませんが、そこにいる必要があるように見えることを除いて、なぜ私がそうするのか本当にわかりません。私は完全に異なる割り当てのコードを試してみました。そのため、コードはそのように見えます。 mod 2が多くの新しいラインを許可することは知っていますが、少なくともピラミッドの高さを見つけるためのアプローチでした。成長するピラミッドの各ステップで新しいラインが必要になるため、実際のアプローチはN + 1に似ていることを理解していますが、それを実装する方法がわかりません。

誰もが完全なコードを提示することを期待していませんが、誰かが解決策を見つける途中で考える方法について手がかりを得ることができることを願っています。

再帰を知らなくても試験に合格することができます。通常、再帰は2つあり、1つは再帰で、もう1つは再帰ではないため、どちらか一方に合格する必要があります。

いつものように、良い戦いを戦っている人にとても感謝しています!

この投稿を見て注目を集めましたピラミッドをもう少し複雑なものに拡張したいと思います:

ピラミッドの問題2

誰かがそれを見てほしい。良い答えはそんなに多くはないだろうと思っていました。

Level 1
|=|

Level 2
|===|
||=||
|===|

Level 3

|=====|
||===||
|||=|||
||===||
|=====|

it needs to be figured out recursively. so some way it has to build both upwards and downwards from the center. 

Imが試験のために勉強していることを明確にするために、そして確かにコードが歯を沈めるために感謝するだろう他の多くの人もそうです。

2
Gustav Agrell

再帰的アルゴリズムを開発する方法は、最初のビットを除いて、必要なことを実行するサブプログラムがすでにあり、最初のビットを実行する方法を知っているか、または理解できるふりをすることです。次に、アルゴリズムは

Do the first bit
Call the subprogram to do the rest on what remains,
   taking into account the effect of the first bit, if necessary

トリックは、「残りを行うためにサブプログラムを呼び出す」が、作成しているサブプログラムへの再帰的な呼び出しであるということです。

何もする必要がないときにサブプログラムが呼び出される可能性は常にあるので、それを考慮に入れる必要があります。

if Ending Condition then
   Do any final actions

   return [expression];
end if;

Do the first bit
Call the subprogram to do the rest

これで完了です。終了条件がTrueになるまで最初のビットを繰り返し実行することで、すべてを実行することになります。

例として、関数Get_LineAda.Text_IOは、「行の最初の文字を取得する方法を知っています。行の残りを返す関数がある場合、最初の文字を返すことができます。関数の結果と連結された文字。」そう:

function Get_Line return String is
   C : Character;
begin
   Get (Item => C);

   return C & Get_Line;
end Get_Line;

しかし、すでに行の終わりにいて、取得する行がない場合はどうでしょうか。

function Get_Line return String is
   C : Character;
begin
   if End_Of_Line then
      Skip_Line;

      return "";
   end if;

   Get (Item => C);

   return C & Get_Line;
end Get_Line;

あなたの問題の最初のビットは、インデントとピンの数がある行を印刷することであり、終了条件は、印刷する行がなくなったときです。

ピラミッド問題の場合、この末尾再帰スキームは機能しません。 「中間再帰」を実行する必要があります。

if Level = 1 then
   Print the line for Level

   return
end if

Print the top line for Level
Recurse for Level - 1
Print the bottom line for Level
1

このプログラムのバリエーションは、同じ手順でヘッド再帰とテール再帰の両方を使用することです。そのようなプログラムの出力は

Enter the number of rows in the pyramid: 5
I I I I I 
 I I I I 
  I I I 
   I I 
    I 
    I 
   I I 
  I I I 
 I I I I 
I I I I I 

N = 5

末尾の再帰は上三角形を作成し、頭の再帰は下三角形を作成します。

1
Jim Rogers