プログラマコード問題2021、02/15-Lv.さっきの歌


[質問]


ラジオをよく聴くニオは、ラジオから出たばかりの音楽がどんな音楽なのかよく知りたい.この時、ニオは次のポータルサイトの「さっきの歌」サービスをよく利用した.さっきの歌はテレビやラジオなどの音楽のテーマなどの情報を提供するサービスでした.
ニオは自分の覚えているメロディーを持って、さっきの歌で音楽を探していました.しかし、放送中に1曲の音楽を繰り返し再生する場合もあり、ニオの記憶の中のメロディーは、音楽の終わり部分と冒頭部分から続くメロディーかもしれない.逆に、途中で音楽を中断すると、原曲にニオの記憶のメロディーがあっても、ニオが聞いたことのない曲ではない可能性があります.そこで、ニオは記憶の中のメロディーを再生時間と提供された楽譜と比較したいと思っています.以下の仮定をすると、ニオが探している音楽のテーマを求めます.
  • 先ほどの曲サービスでは、音楽タイトル、放送開始・終了時刻、楽譜を提供しています.
  • ニオの記憶するメロディーと楽譜に使われる音は、C、C、D、D、E、F、F、G、G、A、A、Bの12個.
  • 1音につき1分間に1本再生.音楽は最初から再生しなければならず、再生時間が音楽の長さより長い場合、音楽会は絶えず最初から繰り返し再生しなければならない.再生時間が音楽の長さより短い場合は、最初から再生時間のみとなります.
  • 00:00を超えるまで音楽は流れない.
  • 条件が一致した複数の音楽の場合、ラジオで最も長く再生された音楽タイトルに戻る.再生時間と同時に、入力した音楽タイトルに戻ります.
  • 条件が一致していない音楽の場合は、「None」に戻る
  • 入力フォーマット
    入力として、ニオの記憶を含む旋律の文字列mと、再生曲情報を含む配列musicinfosが与えられる.
  • mは、音1個以上1439個以下からなる.
  • musicinfosは100個以下の曲情報を含む配列であり、各曲情報は音楽で始まる
    1つの時刻、終了時刻、音楽タイトル、楽譜情報は「,」で区切られた文字列である.
  • 音楽の開始時刻と終了時刻は24時間HH:MM形式.
  • 音楽タイトルは、「、」以外の出力可能文字で表される長さが1以上64以下の文字列である.
  • 楽譜情報は音1個以上1439個以下からなる.
  • 出力フォーマット
    条件を満たす音楽タイトルを出力します.
    I/O例
    m
    musicinfos
    answer
    ABCDEFG
    [12:00,12:14,HELLO,CDEFGAB, 13:00,13:05,WORLD,ABCDEF]
    HELLO
    CC#BCC#BCC#BCC#B
    [03:00,03:30,FOO,CC#B, 04:00,04:08,BAR,CC#BCC#BCC#B]
    FOO
    ABC
    [12:00,12:14,HELLO,C#DEFGAB, 13:00,13:05,WORLD,ABCDEF]
    WORLD
    説明:
    第1の例では、HELLOの長さは7分であるが、12:00から12:14まで再生されるので、実際には記憶のメロディーABCDEFGを含むCDEFGABCDEFGABで再生される.
    第3の例では、HELLOはC#DEFGABC#DEFGABで再生され、WOLDはABCDEで再生される.HELLO中のABC#は記憶中のメロディーABCと一致せず、WORLD中のABC記憶中のメロディーと一致する.

    [回答]

    function solution(m, musicinfos) {
      var answer = '';
      const reg = /\w/;
      let mChange = '';
    
      // m을 #앞에 있는 알파벳은 소문자로 변환
      for(let i = 0; i < m.length; i++) {
        if(m[i + 1] === '#') {
          mChange += m[i].toLowerCase() + '#';
        }
        else if(reg.test(m[i])) {
          mChange += m[i];
        }
      }
     
      // 주어진 배열에서 원하는 값을 만들기 위해
      const infoChange = musicinfos.map(str => {
        const splitArr = str.split(',');
        let hour = '0'
       
        // 시간 계산
        if(splitArr[1].split(':')[0] !== splitArr[0].split(':')[0]) {
          hour = (splitArr[1].split(':')[0] === '00' ? '24' : splitArr[1].split(':')[0]) - splitArr[0].split(':')[0];
        }
        else {
          hour = '0';
        }
        
        const time = (hour * 60) + (splitArr[1].split(':')[1] * 1) - splitArr[0].split(':')[1];
        let music = '';
        let index = 0;
      
        // 플레이 타임동안 재생된 음들을 구함
        for(let i = 0; i < time; i++) {
          if(splitArr[3][index + 1] === '#') {
            music += splitArr[3][index].toLowerCase() + '#';
            index += 2;
          }
          else {
            music += splitArr[3][index];
            index += 1;
          }
          
          if(index >= splitArr[3].length) {
            index = 0;
          }
        }
        
        return [time, splitArr[2], music];
      })
      
      // 해당 되지 않는 곡은 버림
      const infoFilter = infoChange.filter(arr => arr[2].includes(mChange));
       
      // 여러 곡일 경우 플레이 타임이 긴 것을 찾기 위해
      infoFilter.sort((a, b) => b[0] - a[0]);
       
      return infoFilter.length ? infoFilter[0][1] : '(None)';
    }
    これは、途中までうまくいって最後まで苦労した問題です.#有と無を区別するため#これらのアルファベットを小文字に変換します.
    次にmap所与の配列から必要な値を抽出して変換する.[플레이 타임, 제목, 플레이 타임동안 재생된 음]抽出.filter条件に合わない曲を除く.
    複数曲であれば、放送時間順に先頭の曲returnを並べます.
    試合時間を稼ぐために長い時間がかかった.
    分で計算したいだけなので、結果はあまりよくないので、何度も質問をしたり、何度も質問をしたりします.
    特殊な症例を探すために,思いがけず終了時間は00としばらくうろうろしていた.