[JS] 코딩테스트 연습 - 6 (TIL)

이해용·2022년 10월 10일
0
post-thumbnail

같은 숫자는 싫어

문제 설명
배열 arr가 주어집니다. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다. 이때, 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하려고 합니다. 단, 제거된 후 남은 수들을 반환할 때는 배열 arr의 원소들의 순서를 유지해야 합니다. 예를 들면,

  • arr = [1, 1, 3, 3, 0, 1, 1] 이면 [1, 3, 0, 1] 을 return 합니다.
  • arr = [4, 4, 4, 3, 3] 이면 [4, 3] 을 return 합니다.

배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return 하는 solution 함수를 완성해 주세요.

제한사항

  • 배열 arr의 크기 : 1,000,000 이하의 자연수
  • 배열 arr의 원소의 크기 : 0보다 크거나 같고 9보다 작거나 같은 정수

입출력 예

arranswer
[1,1,3,3,0,1,1][1,3,0,1]
[4,4,4,3,3][4,3]

입출력 예 설명
입출력 예 #1,2
문제의 예시와 같습니다.

나의 풀이

function solution(arr) {
    let answer = [];
    for (let i = 0; i < arr.length; i++) {
      if (arr[i] !== arr[i+1]) {
        answer.push(arr[i]);
      } 
    }
    return answer;
}
  1. 새로운 배열을 선언한다.
  2. arr 배열에 for문을 사용하여 배열의 순서와 그 다음 순서를 비교하여 같지 않으면 answer 배열에 추가하여 마지막에 리턴한다.

다른 풀이

function solution(arr) {
  	return arr.filter((x, i) => x !== arr[i+1])
}

filter

filter() method 는 함수에 의해 제공된 테스트를 통과하는 요소로 채워진 새 배열을 만듭니다.
filter() method 는 빈 요소에 대해 함수를 실행하지 않습니다.
filter() method 는 원본 배열을 변화시키지 않습니다.

syntax
array.filter(function(currentValue, index, arr), thisValue)

Parameters

ParameterDescription
function()Required. 각 배열 요소에 대해 실행할 함수입니다.
currentValueRequired. 현재 요소의 value 입니다.
indexOptional. 현재 요소의 index입니다.
arrOptional. 현재 요소의 배열입니다.
thisValueOptional. Default undefined. this 값으로 함수에 전달된 값입니다.

Return Value

TypeDescription
An array테스트를 통과한 요소를 포함합니다. 테스트를 통과한 요소가 없으면 빈 배열을 반환합니다.

이상한 문자 만들기

문제 설명
문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

제한 사항

  • 문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.
  • 첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.

입출력 예

sreturn
"try hello world""TrY HeLlO WoRlD"

입출력 예 설명
"try hello world"는 세 단어 "try", "hello", "world"로 구성되어 있습니다. 각 단어의 짝수번째 문자를 대문자로, 홀수번째 문자를 소문자로 바꾸면 "TrY", "HeLlO", "WoRlD"입니다. 따라서 "TrY HeLlO WoRlD" 를 리턴합니다.

나의 풀이

function solution(s) {
  let arr = s.split(' ');
  let result = '';
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      if(j % 2 === 1) {
        result += arr[i][j].toLowerCase();
      } else {
        result += arr[i][j].toUpperCase();
      }
    }
    if (i < arr.length - 1) {
      result += ' ';
    }
  } return result;
}
  1. 문자열 s를 split 으로 나눈다.
  2. 빈 문자열 result 를 선언한다.
  3. 이중 for문을 사용하여 홀수번째 문자열은 소문자, 짝수번째 문자열은 대문자로 만든다.
  4. i < arr.length - 1 조건에 arr 배열의 끝이 더해질 땐 띄어쓰기가 될 수 있도록 result 에 추가한다.
  5. result를 return 한다.

다른 풀이

function solution(s) {
  return s.split(' ').map(i => i.split('').map((j, index) => index % 2 === 0 ? j.toUpperCase() : j.toLowerCase()).join('')).join(' ')
}
  1. s문자열을 split으로 나눠서 배열을 만든다.
  2. map을 사용하여 s.split(' ')로 나눠진 배열요소들을 또 split 하여 map을 사용한다.
  3. 두 번째 map에서 삼항연산자를 사용하여 짝수 문자열은 대문자, 홀수면 소문자로 설정한 후 join 메서드를 사용한다.
  4. 그 다음 join 메서드에서는 띄어쓰기가 될 수 있도록 .join(' ') 로 설정해준다.

예산

문제 설명

S사에서는 각 부서에 필요한 물품을 지원해 주기 위해 부서별로 물품을 구매하는데 필요한 금액을 조사했습니다. 그러나, 전체 예산이 정해져 있기 때문에 모든 부서의 물품을 구매해 줄 수는 없습니다. 그래서 최대한 많은 부서의 물품을 구매해 줄 수 있도록 하려고 합니다.

물품을 구매해 줄 때는 각 부서가 신청한 금액만큼을 모두 지원해 줘야 합니다. 예를 들어 1,000원을 신청한 부서에는 정확히 1,000원을 지원해야 하며, 1,000원보다 적은 금액을 지원해 줄 수는 없습니다.

부서별로 신청한 금액이 들어있는 배열 d와 예산 budget이 매개변수로 주어질 때, 최대 몇 개의 부서에 물품을 지원할 수 있는지 return 하도록 solution 함수를 완성해주세요.

제한사항

  • d는 부서별로 신청한 금액이 들어있는 배열이며, 길이(전체 부서의 개수)는 1 이상 100 이하입니다.
  • d의 각 원소는 부서별로 신청한 금액을 나타내며, 부서별 신청 금액은 1 이상 100,000 이하의 자연수입니다.
  • budget은 예산을 나타내며, 1 이상 10,000,000 이하의 자연수입니다.

입출력 예

dbudget
[1,3,2,5,4]9
[2,2,3,3]10

입출력 예 설명

입출력 예 #1
각 부서에서 [1원, 3원, 2원, 5원, 4원]만큼의 금액을 신청했습니다. 만약에, 1원, 2원, 4원을 신청한 부서의 물품을 구매해주면 예산 9원에서 7원이 소비되어 2원이 남습니다. 항상 정확히 신청한 금액만큼 지원해 줘야 하므로 남은 2원으로 나머지 부서를 지원해 주지 않습니다. 위 방법 외에 3개 부서를 지원해 줄 방법들은 다음과 같습니다.

1원, 2원, 3원을 신청한 부서의 물품을 구매해주려면 6원이 필요합니다.
1원, 2원, 5원을 신청한 부서의 물품을 구매해주려면 8원이 필요합니다.
1원, 3원, 4원을 신청한 부서의 물품을 구매해주려면 8원이 필요합니다.
1원, 3원, 5원을 신청한 부서의 물품을 구매해주려면 9원이 필요합니다.
3개 부서보다 더 많은 부서의 물품을 구매해 줄 수는 없으므로 최대 3개 부서의 물품을 구매해 줄 수 있습니다.

입출력 예 #2
모든 부서의 물품을 구매해주면 10원이 됩니다. 따라서 최대 4개 부서의 물품을 구매해 줄 수 있습니다.

나의 풀이

function solution(d, budget) {
    let answer = 0;
  	let sortArr = d.sort((a, b) => a - b);
    
  	for (let i = 0; i < sortArr.length; i++) {
      if (sortArr[i] <= budget) {
        budget -= sortArr[i];
        answer += 1;
      } 
    }
    return answer;
}
  1. 최대한 많은 부서에게 지원을 해줘야하므로 오름차순으로 정렬 후 예산을 배정해주면 될 것이라고 생각했다.
  2. d 배열을 오름 차순으로 정렬한 sortArr 을 선언한다.
  3. for문을 사용하여 예산이 적어질 때까지 for문을 추가하고 answer에는 부서의 개수를 추가해준 뒤 for문이 멈추면 answer를 return한다.

위처럼 진행시 sort() 라고만 작성하니 오류가 발생되었다. 숫자를 정렬할 때는 sort((a, b) => a - b)라고 정확히 명시해야하는 것을 알았다.

Numeric Sort

By default, sort() 함수는 문자열의 값을 정렬합니다.

문자열에서는 잘 작동합니다. ("Apple" comes before "Banana").

그러나, 만약 숫자가 문자열로써 정렬된다면 1보다 2가 크기 때문에 "25"는 "100"보다 큽니다.

이러한 이유로 sort() method 는 숫자를 정렬할 때 부정확한 결과를 출력하게 됩니다.

다른 풀이

function solution(d, budget) {
    d.sort((a, b) => a - b);
    while (d.reduce((a, b) => (a + b), 0) > budget) {
      d.pop();
    }
    return d.length;
}
  1. d 배열을 오름차순으로 정렬한다.
  2. while문을 사용하여 reduce를 사용하여 계산한 d배열의 값이 budget보다 클 때까지 계산하고 마지막에 d에 마지막 배열의 값을 제거한다.
  3. 마지막에 d 배열의 길이를 반환한다.

시저 암호

문제 설명

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

제한 조건

  • 공백은 아무리 밀어도 공백입니다.
  • s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
  • s의 길이는 8000이하입니다.
  • n은 1 이상, 25이하인 자연수입니다.

입출력 예

snresult
"AB"1"BC"
"z"1"a"
"a B z"4"e F d"

나의 풀이

어떻게 풀어야하는지 감은 잡았으나 코드로 작성하려니 쉽지 않았다... 많은 고민을 했지만 포기를 하고 다른 풀이를 보게 되었다...

다른 풀이

function solution(s, n) {
    return s.split("").map(x => {
      if (x === ' ') {
        return x;
      };
      return x.toUpperCase().charCodeAt() + n > 90 ? String.fromCharCode(x.charCodeAt() + n - 26) : String.fromCharCode(x.charCodeAt() + n);      
    }).join('')
}

위의 코드 처럼 unicode 를 사용하는 방법이 있었고 n의 숫자가 1이상 25이하의 자연수이므로 a부터 z까지 두 번 작성하여 푸는 방법도 있었다.

unicode를 사용하는 방법이 있다는 것을 알게 되었다.

[1차] 비밀지도

문제 설명

비밀지도

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

  1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.
  2. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
  3. "지도 1"과 "지도 2"는 각각 정수 배열로 암호화되어 있다.
  4. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

secret map

네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.

입력 형식
입력으로 지도의 한 변 크기 n 과 2개의 정수 배열 arr1, arr2가 들어온다.

  • 1 ≦ n ≦ 16
  • arr1, arr2는 길이 n인 정수 배열로 주어진다.
    정수 배열의 각 원소 x를 이진수로 변환했을 때의 길이는 n 이하이다. 즉, 0 ≦ x ≦ 2n - 1을 만족한다.

출력 형식

원래의 비밀지도를 해독하여 '#', 공백으로 구성된 문자열 배열로 출력하라.

입출력 예제

매개변수
n5
arr1[9, 20, 28, 18, 11]
arr2[30, 1, 21, 17, 28]
출력["#####","# # #", "### #", "# ##", "#####"]

매개변수
n6
arr1[46, 33, 33 ,22, 31, 50]
arr2[27 ,56, 19, 14, 14, 10]
출력["######", "### #", "## ##", " #### ", " #####", "### # "]

나의 풀이

function solution(n, arr1, arr2) {
    let answer = [];
  	let a = arr1.map(x => x.toString(2).padStart(n, '0'));
  	let b = arr2.map(x => x.toString(2).padStart(n, '0'));
  	for(let i = 0; i < n; i++) {
      let hashTag = '';
      for(let j = 0; j < n; j++) {
        a[i][j] === '0' && b[i][j] === '0' ? hashTag += ' ' : hashTag += '#';
      }
      answer.push(hashTag);
    } 
    return answer;
};
  1. toString을 사용하여 2진법을 바꾸고 n의 숫자만큼 빈 숫자가 있다면 0으로 채울 수 있도록 padStart 메서드를 사용한다.
  2. 이중 for문을 사용하여 hashTag 빈 문자열을 선언하고 a와 b에 해당하는 숫자가 0이라면 ' ' 를 추가하고 아니라면 '#'을 추가한 값을 answer 배열에 push 한다.

최소직사각형

문제 설명

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호가로 길이세로 길이
16050
23070
36030
48040

가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.

모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • sizes의 길이는 1 이상 10,000 이하입니다.
    - sizes의 원소는 [w, h] 형식입니다.
    - w는 명함의 가로 길이를 나타냅니다.
    - h는 명함의 세로 길이를 나타냅니다.
    - w와 h는 1 이상 1,000 이하인 자연수입니다.

입출력 예

sizesresult
[[60, 50], [30, 70], [60, 30], [80, 40]]4000
[[10, 7], [12, 3], [8, 15], [14, 7], [5, 15]]120
[[14, 4], [19, 6], [6, 16], [18, 7], [7, 11]]133

입출력 예 설명

입출력 예 #1
문제 예시와 같습니다.

입출력 예 #2
명함들을 적절히 회전시켜 겹쳤을 때, 3번째 명함(가로: 8, 세로: 15)이 다른 모든 명함보다 크기가 큽니다. 따라서 지갑의 크기는 3번째 명함의 크기와 같으며, 120(=8 x 15)을 return 합니다.

입출력 예 #3
명함들을 적절히 회전시켜 겹쳤을 때, 모든 명함을 포함하는 가장 작은 지갑의 크기는 133(=19 x 7)입니다.

나의 풀이

function solution(sizes) {
  	let x = sizes.map((a) => a.sort((a, b) => a - b));
  	let a = [];
  	let b = [];
  	for (let i = 0; i < x.length; i++) {
      a.push(x[i][0]);
      b.push(x[i][1]);
    }
    return Math.max(...a) * Math.max(...b);
}

명함 번호의 가로길이와 세로길이를 정렬하여 작은 수를 가로길이에 넣고 큰 수를 세로길이에 넣어 가로 길이 중 가장 큰 수와 세로 길이의 가장 큰 수를 곱하면 원하는 값이 나올 수 있을거라고 생각했다.

  1. x 에 모든 배열안에 sort하여 오름차순을 진행핬다.
  2. for문을 사용하여 a 배열과 b 배열에 가로 길이와 세로 길이를 push 한다.
  3. a 배열과 b 배열의 가장 큰 값들을 곱하여 리턴한다.

reference
https://school.programmers.co.kr/
https://www.w3schools.com/jsref/jsref_filter.asp
https://www.w3schools.com/js/js_array_sort.asp

profile
프론트엔드 개발자입니다.

0개의 댓글