ありおりはべりいまそかり
最近、ひたすら紙を折り続けるということがマイブームとなっているあなたは、今日もひたすら紙を折り続けています。それも、折り紙のような凝った折り方ではなく、紙の右辺が上から左辺に重なるような二つ折りを、ただひたすら繰り返すだけです。
おいおいおい、プログラムのし過ぎで頭おかしくなったんか?
刺し身にたんぽぽ載せる仕事とかに転職したほうがいいんじゃない?
かと不安になる問題文の冒頭。。。
面倒くさいので画面パタメータをListでもらった後のFunctionだけ
ちなみに引数のListを作ってる箇所はこっちの記事に書いてあるYO!!
// [問題文(原文)]
// 最近、ひたすら紙を折り続けるということがマイブームとなっているあなたは、今日もひたすら紙を折り続けています。それも、折り紙のような凝った折り方ではなく、紙の右辺が上から左辺に重なるような二つ折りを、ただひたすら繰り返すだけです。
// さて、上記のように N 回折ったあと手順を逆に辿るように紙を広げます。すると、山折りと谷折りの折り目が等間隔に並んだ紙の完成です。あなたはこの折り目を眺めるのが好きですが、実際に紙を折るには紙の大きさや厚さから数回が限界です。
//
// そこで、紙を上記のように折る回数 N が与えられるので、紙を折って広げたあとの山折り谷折りの折り目を計算するプログラムを作成してください。
//
// 2回折り (N = 2) の場合は以下のように折り目が付きます。
function origami(lines) {
// 入力は以下のフォーマットで与えられます。
//
// N
//
// N は紙を上記の形式で折る回数を表します。
const foldPattern = getFoldPattern(Number(lines[0]));
// 山折りの折り目を "1"、谷折りの折り目を "0" として、答えとなる折り目を左から順に "0" と "1" からなる文字列として一行に出力してください。
console.log(foldPattern.join(''));
}
// 折り目取得
function getFoldPattern(foldCnt) {
// Nが0の場合、折り目は存在しないので空配列
if (foldCnt === 0)
return [];
// 再帰的にN-1回の折り目パターンを取得
const previousPattern = getFoldPattern(foldCnt - 1);
// 真ん中は谷折りなので0固定で、右側は左側の値を反転させたやつになるためリバースして値を入れ替えた
return [...previousPattern, 0, ...previousPattern.reverse().map(fold => fold === 0 ? 1 : 0)];
}
module.exports = {
origami
};
再帰で折り目をドンドン作っていくような作りになってます。
以下の部分を解説
return [...previousPattern, 0, ...previousPattern.reverse().map(fold => fold === 0 ? 1 : 0)];
1回目のループ:[][0][]
→0
真ん中は必ず谷折りになるので0を固定で(2回目以降も同じ)
2回目のループ:[0][0][0→1]
→001
左側:1回目のループで出来た値
右側:谷折りの反対は山折りなので値を入れ替える
3回目のループ:[001][0][001→100→011]
→0010011
左側:2回目のループで出来た値
右側:右側を反転して値も逆さにした感じ
つまるところ。。。
- 1つ前の結果が左側に出来る
- 真ん中は絶対に谷折りの0
- 反対側は左側の結果を並び順と値を逆にしたもの
っていうのが分かれば、再帰で求めるのが1番分かりやすいのかなって言うことで、こんな実装になってます。