[Lv.1][1回戦]ダーツゲーム

35775 ワード

質問:https://programmers.co.kr/learn/courses/30/lessons/17682

🔶 私のやり方

function solution(dartResult) {
  const result = [0, 0, 0];
  const bonus = { S: 1, D: 2, T: 3 };

  // 0. 점수|보너스|[옵션] 대로 각각 배열의 요소로 만든다.
  const rx2 = /\d{1,2}[A-Z]["*"|"#"]?/g;
  const arr = dartResult.match(rx2).map((el) => el); // ['1D', '2S#', '10S']

  for (let i = 0; i < arr.length; i += 1) {
    // arr의 각 요소를 돌면서 요소마다
    // 1. 숫자만 찾아, result 배열에 담는다.
    result[i] = +arr[i].match(/\d{1,2}/g); // 1, 2, 10

    // 2. S,D,T를 찾아 제곱한다
    const b = arr[i].match(/[A-Z]/g); // D, S, S
    result[i] **= bonus[b[0]];

    // 3.옵션 있으면, *(직전 점수와 해당점수에 2곱하고), #(해당점수 -1 곱한다)
    const op = arr[i].match(/["*"|"#"]$/g); // null, # , null
    if (op) {
      // *
      if (op[0] === '*') {
        result[i] *= 2;
        if (result[i - 1]) {
          result[i - 1] *= 2;
        }
      }
      // #
      if (op[0] === '#') {
        result[i] *= -1;
      }
    }
  }

  return result.reduce((acc, cur) => acc + cur);
}

// 실행코드
console.log('1:', solution('1S2D*3T')); // 37 ←11 * 2 + 22 * 2 + 33
console.log('2:', solution('1D2S#10S')); // 9 ←12 + 21 * (-1) + 101
console.log('3:', solution('1D2S0T')); // 3 ←12 + 21 + 03
console.log('4:', solution('1S*2T*3S')); // 23 ←-11 * 2 * 2 + 23 * 2 + 31
console.log('5:', solution('1D#2S*3S')); // 5 ←12 * (-1) * 2 + 21 * 2 + 31
console.log('6:', solution('1T2D3D#')); // -4 ←13 + 22 + 32 * (-1)
console.log('7:', solution('1D2S3T*')); // 59 ←12 + 21 * 2 + 33 * 2

🔶 他人を解く


  • function solution(dartResult) {
      const bonus = { S: 1, D: 2, T: 3 };
      const options = { '*': 2, '#': -1, '': 1 };
    
     // 1.정규식으로 ['1S', '2D*', '3T'] 만들기
      const darts = dartResult.match(/\d{1,}[SDT][*#]?/g); // 방법1 -\d{1,}(한자리 수 이상 숫자 추출함), [SDT](S,D,T 중 문자하나), [*#](*,# 중 문자하나), ?(있을수도 없을수도 있음)
      // const darts = dartResult.match(/\d.\D?/g); // 방법2 - \d(0-9숫자 다 추출함), .(any sigle character), \D( 숫자가 아닌 문자), ?(있을수도 없을수도 있음)
    
      for (let i = 0; i < darts.length; i += 1) {
     // 2. 각 요소를 돌면서 숫자,문자,특수문자를 각각 변수로 만듦.
        const [, digit, b, op] = darts[i].match(/(\d{1,})([SDT])([*#]?)/);
        // ['1S', '1', 'S', '', index: 0, input: '1S', groups: undefined]
        // console.log(digit, b, op); // digit :1, S / b :2 D * / op:3 T
        const score = digit ** bonus[b] * options[op];
    // 3. option이 *이면 직전 점수도 2곱해줌
        if (op === '*' && darts[i - 1]) {
          darts[i - 1] *= options['*'];
        }
    
        darts[i] = score;
      }
    
      return darts.reduce((a, b) => a + b);
    }

  • function solution(dartResult) {
      const reg = /[\d]+[SDT][*#]*/g;
      // [\d](0-9중 숫자 한개), +(한개 이상), [SDT](S,D,T 중 한개) , [*#](*,#중 한개), *(0개 이상)
      // +(1개 이상) *(0개 이상)
      const darts = dartResult.match(reg); // ['1D', '2S#', '10S']
      const result = [];
    
      for (let i = 0; i < darts.length; i += 1) {
        let number = darts[i].match(/[\d]+/g)[0];
        const bonus = darts[i].match(/[SDT]/g)[0];
        const option = darts[i].match(/[*#]/g);
    
        switch (bonus) {
          case 'S':
            number **= 1;
            break;
          case 'D':
            number **= 2;
            break;
          default:
            number **= 3;
        }
    
        result[i] = number;
    
        if (option) {
          switch (option[0]) {
            case '*':
              result[i - 1] *= 2;
              result[i] *= 2;
              break;
            default:
              result[i] *= -1;
          }
        }
      }
    
      return result.reduce((acc, cur) => acc + cur);
    }

    🔶 フィードバック


    1.正規表現、文字抽出(スクリーンショットグループ)が不明です。


  • スクリーンショットグループとは?
    1)正規表現または一致配列のIDを使用して、将来参照されるすべての一致の一部を区切ります.
    2)IDは1から始まる.←[全体モード、1番組み合わせ($1)、2番組み合わせ($2)…]このように現れる
    3)正規表現にグローバル(/g)タグが含まれていない場合、キャプチャグループは失敗します.

  • 説明:
  • 1)match는 유사배열로 반환됨(배열안에 내용의 자료형은 "문자"[""])
    -첫 번째 요소는 정규식에 매치된 "전체 문자열", 두번째부터는 괄호로 "추출된 문자열"~이 나옴.
    
    2)() 괄호는 String.prototype.match 호출 시 RegExpMatchArray로 유사배열로 "추출됨".
    
    3)괄호를 추출하지 않고 싶다면 (?:...) 를 사용해서 무시할 수 있음.
    const arr = "abcdef00".match(/ab(?:cd|ef)(e)(f)(00)/); 
    console.log(arr); // ["abcdef00", "e", "f", "00"] ← ?:를 붙여 cd또는 ef를 추출하지 않음.
    
    4)global에서는 추출이 안됨.(mdn :캡처된 그룹은 반환되지 않습니다.)
     :g쓰면 괄호 추출은 의미가 사라지고, 그냥 정규식 패턴에 맞는 텍스트를 모두 찾아
      유사배열로 반환함(그냥 ()없이 쓰는거랑 똑같이 됨.)
    console.log("a12bc3a1".match(/a(\d)/)); //["a1", "1"] ←() 지정된게 1개 추출됨
    console.log("a12bc3a1".match(/a(\d)/g)); //["a1", "a1"] ←()가 추출되지 않음.★

    2.正規製作1 D 2 S#10 S→[‘1 D’‘2 S’‘10 S’]の方法−方法3つ

    // <방법1>
    const dartResult = '1D2S#10S';
    const darts = dartResult.match(/\d{1,}[SDT][*#]?/g); 
    // \d(0-9 중 한개), {1,}(한개 이상 숫자 추출함), 
    // [SDT](S,D,T 중 문자하나), [*#](*,# 중 문자하나), ?(있을수도 없을수도 있음) 
    // <방법2>
    const dartResult = '1D2S#10S';
    const darts = dartResult.match(/\d.\D?/g); 
    // \d(0-9 중 한개), .(문자 중 하나),  <- 1D, 2S, 10 나옴
    // \D('0' ~ '9'가 아닌 문자 즉,숫자가 아닌 문자), ?(있을수도 없을수도 있음) <- "", # , S
    // <방법3>
    const dartResult = '1D2S#10S';
    const reg = /[\d]+[SDT][*#]*/g;
    const darts = dartResult.match(reg);
    // [\d](0-9중 숫자 한개), +(한개 이상), [SDT](S,D,T 중 한개) ,
    // [*#](*,#중 한개), *(0개 이상)
    // +(1개 이상) *(0개 이상)

    3.例

  • 「880925-1184015」→「1988男子」返却
  • function jumin(str) {
      let year = '';
      let gender = '';
    
      let [, second, third] = str.match(/(^\d{2})\d{4}-(\d)/); // ["880925-1", "88(추출)", "1(추출)"] ["940207-2", "94(추출)", "2(추출)"]
    
      year = second[0] <= '2' ? `20${second}` : `19${second}`; // second는 88임, second[0]은 8
      gender = third === '1' ? '남자' : '여자';
    
      console.log(`${year} ${gender}`);
    }
    
    jumin('880925-1184015'); // 1988 남자;
    jumin('100207-2188107'); // 1994 여자;