[Javascript]おばあとおじいの1週間の献立を無理やり再帰にする準備をする

# 背景
「どうせ学んでいるのならアウトプットせい！」と~~お叱り~~愛の叱咤激励をもらいました。
ごもっともなので毎日投稿を習慣化してみる。

#自己紹介（=~~情報の信頼度~~)
2020年4月から学習をはじめた駆け出しエンジニア
HTML、CSS、Javascript、React、Vue、Laravelを学習
AWSもamplifyとかS3、EC2あたりをちょこっと。ふくおか。

#今日のおはなし
〜おじいおばあの家〜

おばあ「今週のごはんは何にしようか。」

おじい「精のつくものとらねばねえ。」

おじい「しかし、ついつい昨日のごはんも忘れてしまうとよ。困ったもんちゃ！」

おばあ「では、私が「1週間の献立」をつくってみようかね」

おばあ「最近、ぷろぐらみんぐ教室で学んだの。」


#お題
[朝、昼、夜]の献立表をつくる。

献立表＝[
 [🍛、🍛、🍛][🍛、🍛、🍣][🍛、🍛、🍜]
 [🍛、🍣、🍛][🍛、🍣、🍣][🍛、🍣、🍜]
 [🍛、🍜、🍛][🍛、🍜、🍣][🍛、🍜、🍜]
 [🍣、🍛、🍛][🍣、🍛、🍣][🍣、🍛、🍜]
 [🍣、🍣、🍛][🍣、🍣、🍣][🍣、🍣、🍜]
 [🍣、🍜、🍛][🍣、🍜、🍣][🍣、🍜、🍜]
 [🍜、🍛、🍛][🍜、🍛、🍣][🍜、🍛、🍜]
 [🍜、🍣、🍛][🍜、🍣、🍣][🍜、🍣、🍜]
 [🍜、🍜、🍛][🍜、🍜、🍣][🍜、🍜、🍜]
]

※おじいさんとおばあさんは、カレー、寿司、ラーメンしかたべません。

#再帰を学ぼう！

##再帰とは
関数が自分自身を呼ぶこと。
たとえば、繰り返し処理（forループ）を、
<img width="741" alt="Screen Shot 2020-07-01 at 21.44.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/aade6b13-f0e0-4421-9d40-eadd841e384c.png">
こう書き換えられる。
<img width="729" alt="Screen Shot 2020-07-01 at 21.45.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/06844906-5302-5826-e875-08bccf45723d.png">

この場合、
n==3であれば、x*pow(2,3)  //-> 2*2
n==2であれば、x*pow(2,3)　//-> 2*2*2
n==1になるとき、x*pow(2,3)//-> 8

となっている。

##@fujitanozomu様にご指摘いただきました！ありがとうございます！

>0乗が正しく求まらないので書き換えられていないのでは

仰られる通りです。ご指摘いただきありがとうございます。
下記に訂正いたします。

```js
function pow(x, n) {
  if (n == 0) {
    return 1;
  } else {
    return x * pow(x, n - 1);
  }
}
```

##再帰を考えるときのコツ
再帰を終了する条件：ベースケース
再帰を継続する条件：リカーシブケース
と呼ぶらしい。

再帰関数自体にベースケース、リカーシブケースに関係する値を引数としていれておくこと。

#実際に再帰で考えてみよう！
おばあ「まず、全体の流れを理解しよう。」

おばあ「すべての献立パターンがつくれて、関数を実行すると「献立表」が返ってくる。」

おばあ「食べ物は、食糧庫からとってこよう。」

おばあ「朝、昼、夜、の３食決まったら再帰は終了だね。間食はしないからね」

おばあ「じゃあ、まだ朝、昼までしか決まっていないときは、再帰を継続する必要があるね。」

<img width="723" alt="Screen Shot 2020-07-01 at 22.55.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/1451d24b-3259-0878-81f9-bec6765b2b94.png">
おばあ「あ、再帰したときに、減らす引数がない！」
<img width="733" alt="Screen Shot 2020-07-01 at 22.55.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/71e2e217-b8d6-ba4e-2d46-bffbf2471c90.png">

おばあ「これでよしっと。」



おばあ「繰り返し処理になっている部分は、、と。」

おばあ「各食事に対してpantryからすべての食事を取り出す。」

おばあ「まず、[🍛、🍛、🍛]をつくるには、」

おばあ「1回目の食事を[🍛]いれて、2回目の食事にする。」

おばあ「2回目の食事を[🍛]いれて、3回目の食事にする。」

おばあ「3回目の食事を[🍛]いれて、３食分の献立をresultにいれる。」

おばあ「このあたりが繰り返しの処理っぽいな。」

おばあ「次に、[[🍛、🍛、🍣]をつくる。]

おばあ「途中まで[🍛、🍛]をつくってるから、その上に対して🍣を入れたいけど、どうしようか」

おばあ「作成途中の献立[🍛、🍛]を受けとれるようにしよう。」

おばあ「作成途中の献立を受け取れるように引数を変更して、」

おばあ「それらに対してpantryから次の食事を加えよう。」
<img width="762" alt="Screen Shot 2020-07-01 at 22.53.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/f97ff510-b39e-3958-2e1d-c8e911aa87cc.png">

おばあ「これで、自分自身を呼ぶことで、配列を作るrecuse関数ができあがった」

おばあ「あ。recuse関数の発火をしてない。えい。」

```
const menu = (numberOfMeals=3) => {
  // Your code here
  const pantry = ["🍛", "🍣", "🍜"];
  let result = [];
   　function recurse(meal=[],numberOfMeals) {
    if (numberOfMeals > 0) {
      //再帰の処理
      for (let i = 0; i < pantry.length; i++) {
       recurse(meal.concat(pantry[i]),numberOfMeals - 1,) 
      }
    } else {
      //３食分の献立ができたので終了する
      result.push(meal)
    }
    return result;
  }
  return recurse([],numberOfMeals)
};

```


#その後

おばあ「meal()[1]」

おじい「もぐもぐ」

おばあ「meal()[4]」

おじい「もぐもぐ」


##補足

###pushではなく、concatで記述している理由は、配列のままにしたいからです。

pushだと要素数を返す
=>数字になる。
=>昼のごはんが選べなくなる
＝cannnot read proptyとなるため避けています。

###recuse関数外にresultを定義しているのはクロージャーを使いたいためです。
後日記事にします。


####解釈間違い等、何かあればぜひコメントください。
誰か再帰の使いみちを教えてください・・・。