문제

순서대로 누를 번호가 담긴 배열 numbers

왼손잡이인지 오른손잡이인지를 나타내는 문자열 hand

→ 각 번호를 누른 엄지손가락이 왼손인지 오른손인지를 나타내는 연속된 문자열 형태로 return

 

 

코드

const solution = (numbers, hand) => {
  let answer = '';

  let keypad = {
    1: [0, 0],
    2: [0, 1],
    3: [0, 2],
    4: [1, 0],
    5: [1, 1],
    6: [1, 2],
    7: [2, 0],
    8: [2, 1],
    9: [2, 2],
    '*': [3, 0],
    0: [3, 1],
    '#': [3, 2],
  };

  let leftHand = keypad['*'];
  let rightHand = keypad['#'];

  for (let x of numbers) {
    let [i, j] = keypad[x];

    if (j === 0) {
      answer += 'L';
      leftHand = keypad[x];
    }
    else if (j === 2) {
      answer += 'R';
      rightHand = keypad[x];
    }
    else {
      // 왼쪽 손가락 위치와 현재 위치와 떨어진 거리계산
      let leftDistance = Math.abs(i - leftHand[0]) + Math.abs(j - leftHand[1]);
      // 오른쪽 손가락 위치와 현재 위치와 떨어진 거리계산
      let rightDistance = Math.abs(i - rightHand[0]) + Math.abs(j - rightHand[1]);

      if (leftDistance > rightDistance) {
        rightHand = keypad[x];
        answer += 'R';
      }
      else if (leftDistance < rightDistance) {
        leftHand = keypad[x];
        answer += 'L';
      }
      else if (leftDistance === rightDistance) {
        if (hand === 'left') {
          leftHand = keypad[x];
          answer += 'L';
        } else {
          rightHand = keypad[x];
          answer += 'R';
        }
      }
    }
  }
  return answer;
}

문제

부서별로 신청한 금액만큼 모두 지원해줘야한다. 

부서별로 신청한 금액이 들어있는 배열 d, 예산 budget이 주어질 때, 

최대 몇 개의 부서에 물품을 지원할 수 있는지 return 

 

코드

const solution = (d, budget) => {
  let answer = 0;
  // 가장 작은 예산을 가진 부서부터 총 예산을 차감해가야 지원할 수 있는 부서가 최대로 된다. 
  d.sort((a, b) => a - b); // 오름차순 정렬

  d.reduce((acc, cur) => {
    acc + cur <= budget ? answer++ : answer;
    return acc + cur;
  }, 0);

  return answer;
}

문제

주어진 자연수 n을 3진법 상에서 앞뒤로 뒤집고, 이를 다시 10진법으로 표현한 수를 return

 

풀이

const solution = (n) => {
  let answer = n.toString(3).split('').reverse().join('');
  return parseInt(answer, 3);
}

 

 

사용한 메소드

1) Number.toString()

10진법 -> 2, 8, 16진법으로 변환

let value = 16;

value.toString(2); // 10000
value.toString(8); // 20
value.toString(16); // 10

2) parseInt

문자열을 정수로 해석하여 반환한다. 전달받은 인수가 문자열이 아니면 문자열로 변환한 다음, 정수로 해석하여 반환한다.  

두 번째 인수로 진법을 나타내는 기수를(2~36)을 전달할 수 있다. 기수를 생략하면 첫 번째 인수로 전달된 문자열을 10진수로 해석하여 반환한다. 

parseInt('10', 2); // 문자열 10을 2진수로 해석
parseInt('10', 8); // 문자열 10을 8진수로 해석

문제

다트게임의 3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력

 

입출력예제

 

 

다트게임의 점수 계산 로직

・ 총 3번의 기회

・ 각 기회마다 얻을 수 있는 점수는 0점에서 10점 까지

・ S, D, T 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (S, D, T는 점수마다 하나씩 존재)

・ 스타상(*) : 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다.

・ 첫 번째 기회에서도 나올 수 있다.

・ 첫 번째 스타상의 점수만 2배가된다. 

・ 스타상의 효과는 다른 스타상의 효과와 중첩될 수 있다. 중첩된 아차상의 점수는 -2배가 된다. 

・ 아차상(#) - 해당 점수 마이너스

・ 스타상, 아차상은 점수마다 둘 중 하나만 존재할 수 있으며, 존재할지 않을 수도 있다. 

 

 

접근방법

문자열 내에서 먼저 문자나 기호 기준으로 구획을 나누어 잘라서 배열화 하고, 다음에 각각 개별 연산을 해준다. 마지막에 한 번에 곱해서 결과값을 찾는다. 

 

원래 하고싶었던 방법은 정규식으로 각 숫자의 앞에서 자른 다음에 각각 계산을 해주고싶었는데, 생각보다 정규식 가공이 마음대로 되지않았다. 나중에 다시 한 번 풀어보면서 이 방법을 시도해보아야할 것 같다. 

 

 

코드

const solution = (dartResult) => {
  let answer = 0;
  let score = 0;
  let scoreArr = [];

  for (let i = 0; i < dartResult.length; i++) {
    // 점수가 10인 경우 찾아줘서 분리
    if (!isNaN(dartResult[i])) {
      score = Number(dartResult[i - 1]) === 1 ? 10 : Number(dartResult[i]);
    }
    else if (dartResult[i] === 'S') { // 1제곱
      scoreArr.push(score);
    }
    else if (dartResult[i] === 'D') { // 2제곱
      scoreArr.push(Math.pow(score, 2));
    }
    else if (dartResult[i] === 'T') { // 3제곱
      scoreArr.push(Math.pow(score, 3));
    }
    else if (dartResult[i] === '*') {
      scoreArr[scoreArr.length - 2] = scoreArr[scoreArr.length - 2] * 2;
      scoreArr[scoreArr.length - 1] = scoreArr[scoreArr.length - 1] * 2;
    }
    else if (dartResult[i] === '#') {
      scoreArr[scoreArr.length - 1] = -1 * scoreArr[scoreArr.length - 1];
    }
  }
  answer = scoreArr.reduce((acc, cur) => acc + cur, 0);
  return answer;
}

1-9까지는 괜찮은데 10을 잘 찾아서 걸러주어야했다. 

 

Math.pow(밑, 지수)

첫 번째 인수를 '밑'으로 두 번째 인수를 '지수'로 거듭제곱한 결과를 반환한다. 

 

String.match(찾을단어)

.match()는 정규표현식에 맞는 문자열을 찾아서 배열 객체로 반환

정규표현식에 맞는 문자열이 없다면 null을 반환

특정 텍스트 안에 검색할 단어, 찾고싶은 단어가 있는 경우 해당 텍스트가 문구에 포함되어있는지를 확인

문제

전체 지도는 지도1과 지도2를 겹쳐서 얻을 수 있다. 

지도1 또는 지도2 중 어느 하나라도 벽인 부분은 전체 지도에서 벽이다. 

지도1 과 지도2 에서 모두 공백인 부분은 전체 지도에서 공백이다. 

 

지도1(arr1)과 지도2(arr2)는 정수 배열로 암호화

암호화된 배열은 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다. 

 

조건

1. 지도1 또는 지도2 중 어느 하나라도 벽인 부분은 전체 지도에서 벽이다.

2. 지도1 과 지도2 에서 모두 공백인 부분은 전체 지도에서 공백이다. 

3) 겹쳐진 지도를 #과 공백으로 구성된 문자열 배열로 출력한다. 

 

비트연산

출제 의도는 비트 연산을 이용해서 풀기를 원했던 문제였다. 

주어진 수를 2진수로 변환 -> 비교 -> 비교결과값을 10진수로 변환 및 출력

 

비트 : 컴퓨터에서 정보 표현의 최소 단위

비트연산자는 기본적으로 2진수 표현법

 

비트 연산자

  • & : 비교하는 비트가 모두 1이면 1 반환
  • | : 비교하는 비트 중에서 하나라도 1이면 1반환
  • ^ : 비교하는 비트가 같으면 0, 다르면 1 반환
  • << : 지정한 수 만큼 비트 전체를 왼쪽으로 이동
  • >> : 지정한 수 만큼 비트 전체를 오른쪽으로 이동
  • >>> : 지정한 수 만큼 비트를 전부 오른쪽으로 이동, 새로운 비트는 전부 0이된다. 

 

 

해결방법

일단 첫 번째로는 지도 2개를 해석해서 겹쳐야겠다. 

1) 십진수로 주어진 숫자를 이진수로 바꾼다. 

2) 지도 2개를(arr1, arr2)를 겹친다(합친다)

 

 

코드

const solution = (n, arr1, arr2) => {
  let answer = [];

  // 2진수로 변환하고, 0을 채워서 n자리 맞추기
  let binaryNumArr1 = arr1.map((i, idx) => arr1[idx].toString(2).padStart(n, '0'));
  let binaryNumArr2 = arr2.map((i, idx) => arr2[idx].toString(2).padStart(n, '0'));

  // 이중for문으로 비교하면서 #또는 공백으로 맞춰주기
  for (let i = 0; i < n; i++) {
    let allArr = '';

    for (let j = 0; j < n; j++) {
      if (binaryNumArr1[i][j] === '1' || binaryNumArr2[i][j] === '1') {
        allArr += '#';
      } else {
        allArr += ' ';
      }
    }
    answer.push(allArr);
  }
  return answer;
}

toString메소드

숫자를 문자열로 변환하여 반환한다. 

 

 

비트연산을 이용한 다른 풀이

한줄로 해결할 수가 있었다....

const solution = (n, arr1, arr2) => {
  return arr1.map((i, index) => ('0'.repeat(n) + (i | arr2[index]).toString(2)).slice(-n)).map(i => i.replace(/0/g, ' ').replace(/1/g, '#'));
}

문제

동적으로 게임시간을 늘려서 난이도를 조절한다. 

실패율 = 스테이지에 도달했으나 아직 클리어하지못한 플레이어 수 / 스테이지에 도달한 플레이어 수

 

전체 스테이지 개수 N

게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages

실패율이 높은 스테이지부터 내림차순으로 스테이지 번호가 담겨있는 배열을 return

 

 

방법

실패율을 구해서 배열안에 넣고, 내림차순으로 정렬해서 return 하자

 

 

코드

const solution = (N, stages) => {
  let answer = [];

  // 인원수
  let totalNum = stages.length;

  for (let i = 1; i <= N; i++) {
    // 현재 스테이지에 도달한 인원 찾기
    let stageNum = stages.filter(ele => ele === i).length;

    // 실패율 기본 세팅
    let failRatio = 0;

    // 실패율 계산
    if (stageNum === 0) {
      failRatio = 0;
    } else {
      failRatio = (stageNum) / totalNum;
    }

    // 인원수에서 현재 스테이지에 있는 인원 빼주기
    totalNum -= stageNum;
    answer.push({ idx: i, ratio: failRatio });
  }

  // 정렬
  answer.sort((a, b) => {
    // 실패율이 같다면 오름차순 정렬
    if (a.ratio === b.ratio) {
      return a.idx - b.idx;
    } else {
      return b.ratio - a.ratio;
    }
  })
  return answer.map(ele => ele.idx);
}

문제 

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다. 1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ... 2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ... 3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ... 1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

 

조건

시험은 최대 10,000 문제로 구성되어있습니다.
문제의 정답은 1, 2, 3, 4, 5중 하나입니다.
가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.

 

 

코드

const solution = (answers) => {
  let answer = [];
  const list = [
    [1, 2, 3, 4, 5],
    [2, 1, 2, 3, 2, 4, 2, 5],
    [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
  ];

  let point = [0, 0, 0];
  let max = 0;

  for (let i = 0; i < answers.length; i++) {
    if (answers[i] === list[0][i % 5]) {
      point[0]++;
    }
    if (answers[i] === list[1][i % 8]) {
      point[1]++;
    }
    if (answers[i] === list[2][i % 10]) {
      point[2]++;
    }
  }

  for (let j = 0; j < point.length; j++) {
    if (point[j] > max) {
      max = point[j];
    }
  }

  for (let k = 0; k < point.length; k++) {
    if (max === point[k]) {
      answer.push(k + 1);
    }
  }

  if (answer.length !== 1) {
    answer.sort((a, b) => a - b);
  }
  return answer;
}

찍는 방식을 리스트로 배열 안에 담는다. for문으로 answers의 i와 list[0][0] -  list[0][5]까지 찾는다.  

 

 

다른 풀이

function solution(answers) {
    var answer = [];
    var a1 = [1, 2, 3, 4, 5];
    var a2 = [2, 1, 2, 3, 2, 4, 2, 5]
    var a3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5];

    var a1c = answers.filter((a,i)=> a === a1[i%a1.length]).length;
    var a2c = answers.filter((a,i)=> a === a2[i%a2.length]).length;
    var a3c = answers.filter((a,i)=> a === a3[i%a3.length]).length;
    var max = Math.max(a1c,a2c,a3c);

    if (a1c === max) {answer.push(1)};
    if (a2c === max) {answer.push(2)};
    if (a3c === max) {answer.push(3)};


    return answer;
}

찍는 방식 1,2,3을 배열로 만들어놓는다. answers 배열과 a1, a2, a3 배열을 filter메소드로 다른 것은 걷어내며 갇은 것 만 있는 배열을 구하고 length를 구한다. 세 개 중에서 큰 값을 찾는다. max인 값을 answer 배열에 push 한다. 

반복문으로 문자열 탐색, 비교해서 문자열로 리턴하는 문제였다.

 

1. 문제

알파벳 대문자로 이루어진 문자열을 입력받아 같은 문자가 연속으로 반복되는 경우 반복되는 문자 바로 오른쪽에 반복 횟수를 표기하는 방법으로 문자열을 압축하는 프로그램을 작성하시오. 단 반복횟수가 1인 경우 생략합니다.

 

입력예제 | KKHSSSSSSSE

출력예제 | K2HS7E

 

2. 접근방법

반복문으로 문자열 탐색해서 두개씩 비교해서 counting해주고 숫자를 문자열로 바꾸어서 넣어준다. 

 

 

3. 문제 풀이 

1. 결과물이 문자열이다.

2. 개수를 카운팅해서 answer로 출력해야한다.

3. -> 문자열 내 문자 두개 비교해서 같으면 카운팅 

    -> 다른 경우 answer에 문자 누적하고

    -> 개수도 문자열로 바꿔서 answer에 누적한다. (count > 1 인 경우에만)

    -> 카운트는 원래대로 초기화해준다. 

function solution(str){
	let answer = "";
    let count = 1;
    for(let i=0; i<str.length; i++){
    	if(str[i] === str[i+1]{
        	count++;
        } else {
        	answer += str[i];
            answer += count.toString();
            count = 1;
        }
    }
    return answer;
}

let str = "KKHSSSSSSSE";
console.log(solution(str));
    

반복횟수가 1인 경우 생략하는 코드를 추가하지 못했다. 

 

 

해결방법

else안에 또 if문을 작성할 수가 있었다!
function solution(str){
	let answer = ""; //출력이 문자열로 나와야하니까
    let count = 1; //제일 앞에 문자하나는 기본으로 있으니까 1로 저장해주기
    for(let i=0; i<str.length: i++){
    	if(str[i] === str[i+1]){
        	count++;
        } else {
        	answer += str[i]; // answer에 문자누적해주고
            if(count>1) answer += count.toString();
            // count가 1보다 크면 문자로 바꿔서 answer에 누적
            count = 1; // count는 다시 1로 초기화시켜준다. 
          }
      }
      return answer;
}

let str = "KKHSSSSSSSE";
console.log(solution(str));

반복횟수가 1인경우 생략하려면 count 가 1보다 큰 경우에만 출력하도록하는 코드를 써주었다. 

 

 

 

3. 사용한 개념

Number.toString()

숫자를 문자열로 바꿔주기

 

String(Number)

숫자를 문자열로 바꿔주기

+ Recent posts