甘くてさくさく?んなわきゃない

N予備校日記、その他雑記、備忘録

Paiza の プログラミング練習問題「多重ループ」を考える過程メモ(JavaScript) その1

(まだ解けてません)

練習問題に関しては問題やコードについて語っても良いという事で。

これですね。

paiza.jp

for文を使った初心者向け問題の中の一つ。

問題を簡単に噛み砕くと、入力されたある言葉にある文字が入っていれば「YES」、入っていなければ「NO」と出力するという問題。

入出力例1では

入力例1

1
a
2
paiza
kyoko

出力例1

YES
NO

例2では

入力例2

2
c
d
2
cat
dog

出力例2

YES
NO
NO
YES

のように、言葉と文字の組み合わせ分、出力が増えていく処理を考えていく。

また出力の順番も重要で例2の場合

  1. cはcatに含まれている?→「YES」
  2. cはdogに含まれている?→「NO」
  3. dはcatに含まれている?→「NO」
  4. dはdogに含まれている?→「YES」

という順番で処理されてることが分かる。

PaizaのJavaScriptは標準入力の形がちょっと分かりづらいのだが

let lines = ["1","a","2","paiza","kyoko"];

という感じで、linesという変数に配列で格納されて用意されてるのでこれを使うことになる。

必要そうな変数の準備。

(最初に全部用意したわけでなく、考えながら増やしてます)

        let m = parseInt(lines[0]); //文字の数
        let n = parseInt(lines[m + 1]); //言葉の数
        let mN = parseInt(lines[1]); //最初の文字が格納されている配列番号
        let nN = m + n; //最初の言葉が格納されている配列番号
        let c = ; //文字を入れる空の配列
        let s = ; //言葉を入れるからの配列

PaizaでJavaScriptをやってて最初に詰みそうなポイント。

標準入力で渡された1とか2とかの数字はおそらく?文字列の型になっているので、

parseInt()やNumber()などのメソッドで数値に型変換しないと使えない時があるぞ!

for (let i = 1; i <= m; i++) {
            c += lines[i] + " ";
        }

        c = c.split(` `);
       
for (let i = nN; i <= lines.length - 1; i++) {
            s += lines[i] + " ";
        }
       
        s = s.split(` `);

文字と言葉の文字列を変数cとsそれぞれに配列で格納するための処理。

まずはfor文で空白が入るように文字列連結してからsplit(` `)で分割して配列にしてますね。

sの方のfor文は前提が独特だな・・・。

例1でいうとnNは3、lines.lengthは配列の中の数5を-1で4となり

3スタート4以下までのループでpaizaとkyotoの2回分回るということになります。

最初のループで"paiza"と" "が連結した"paiza "がsに入り、

2回目のループで"paiza "の後ろに"kyoto "が連結して"paiza kyoto "がsに入ってます。

それをs.split(` `)して空白部分で文字列分割し、sの中身は["paiza","kyoto"]となります。

 

ここからが多重ループになるんだろうなーと感づいたものの

考えようとすると頭が爆発しそうになり・・・

少し間が空いたのですがとりあえず肝となる文字が入ってるか判定して出力する部分から書いてみよう!

として書いたのが

for(let i = 0;i < n;i++){
            let sSplit = lines[nN + i].split(``);
            for(let i = 0;i < sSplit.length;i++){
            if(sSplit[i] === lines[m]){
                console.log("YES")
                break;
            }else if(i === sSplit.length - 1){
                console.log("NO");
            }
        }
}
 

解説に飽きてきたので簡単に

一番外側のfor文は言葉の数分だけループします、この例では2回。

sSpilitは言葉、例えば"kyoto"なら["k","y","o","t","o",]と一文字ずつ格納する変数。

その内側のfor文はsSpilitの文字数の回だけループします、この例では5回。

if文、["k","y","o","t","o",]のそれぞれと、この場合はaを比較して同じだったら「YES」と出力してbreakでループも終了します。

文字数回ループしても同じではなかったらelse ifに分岐して「NO」が出力されます。

この条件を書かずにelseで処理をすると同じではなかった文字数分だけ「NO」が出力されることになるので重要。

 

出来た!と思ったのだが

これだと例2のような文字が2つ(cとd)用意されてる場合でも1度しか判定出来ない!

ので!

その機能は明日に追加したい!のだが忘れてしまいそうな為のメモでした。

(if文の外側にもう一個ループ作ったらできそうじゃね?)