본문 바로가기
codingtest

[programmers] 공 던지기, 주사위의 개수, 2차원으로 만들기, 배열 회전시키기, 최댓값 만들기(1)

by 안자두 2023. 3. 13.

📝 [Lv0] 공 던지기

👀 문제 설명

머쓱이는 친구들과 동그랗게 서서 공 던지기 게임을 하고 있습니다. 공은 1번부터 던지며 오른쪽으로 한 명을 건너뛰고 그다음 사람에게만 던질 수 있습니다. 친구들의 번호가 들어있는 정수 배열 numbers와 정수 K가 주어질 때, k번째로 공을 던지는 사람의 번호는 무엇인지 return 하도록 solution 함수를 완성해보세요.

 

🚨 제한 사항

  • 2 < numbers의 길이 < 100
  • 0 < k < 1,000
  • numbers의 첫 번째와 마지막 번호는 실제로 바로 옆에 있습니다.
  • numbers는 1부터 시작하며 번호는 순서대로 올라갑니다.

 

💻 입출력 예

numbers k result
[1, 2, 3, 4] 2 3
[1, 2, 3, 4, 5, 6] 5 3
[1, 2, 3] 3 2

 

✨ 풀이 설명

처음에는 총인원이 짝수인지 홀수인지에 따라 다르게 계산하여 풀었다. 짝수일 경우에는 k가 무슨 값이든지 간에 무조건 짝수번째만 공을 받기 때문이다. 하지만 홀수일 경우에는 짝수번째가 받을 수도, 홀수번째가 받을 수도 있기 때문에 나누어 계산해 줄 필요가 있다고 생각했다.
그래서 처음에는 아래처럼 긴 코드가 나왔다.

function solution(numbers, k) {
  const len = numbers.length;
  let order, idx;
  if (len % 2) {
    order = k % len || len;
    idx = order - 1 < len / 2 ? (order - 1) * 2 : (order - Math.ceil(len / 2)) * 2 - 1;
     
  } else {
    order = k % (len / 2) || (len / 2);
    idx = (order - 1) * 2;
  }
  return numbers[idx];
}

그런데 다시 생각해 보니, 한 번을 건너 공을 전달해 주기 때문에 처음부터 두 배로 생각해서 계산하면 모두가 짝수 길이가 될 테고, 그렇다면 한 가지 방법으로도 해결할 수 있게 됨을 깨달았다. 

우선 인덱스를 계산하기 위해 1을 빼준 다음, 2를 곱해주어 두 배의 길이만큼 만든다. 그다음 배열의 길이로 나눈 나머지를 인덱스로 배열에서 숫자를 찾아주면 된다.

만약, [1, 2, 3, 4, 5, 6, 7, 8, 9]라는 numbers가 있고, k가 6일 경우, 답은 1 idx에 위치한 2가 되어야 한다.
홀수의 경우는 짝수 번째와 홀수 번째가 섞여서 존재하게 된다.
하지만 이를 n번째를 두 배를 해서 계산하면 아래와 같다.
계산하기 전, 인덱스로 접근하기 위해 1을 빼고 계산해 주었다.

number [idx] n번째 (n번째 - 1) * 2
1 [0] 1 0
2 [1] 6 10
3 [2] 2 2
4 [3] 7 12
5 [4] 3 4
6 [5] 8 14
7 [6] 4 6
8 [7] 9 16
9 [8] 5 8

그냥 보기엔 비슷해 보이지만, 배열의 길이로 나눈 나머지로 생각하면 결과가 달라진다.

number [idx] (n번째 - 1) * 2 ((n번째 - 1) * 2) % numbers의 길이
1 [0] 0 0 % 9 = 0
2 [1] 10 10 % 9 = 1
3 [2] 2 2 % 9 = 2
4 [3] 12 12 % 9 = 3
5 [4] 4 4 % 9 = 4
6 [5] 14 14 % 9 = 5
7 [6] 6 6 % 9 = 6
8 [7] 16 16 % 9 = 7
9 [8] 8 8 % 9 = 8

이렇게 인덱스의 순서와 같아지게 된다.
따라서 이 식을 코드로 옮기면 아래와 같다.

나는 너무 복잡하게 생각해서 시간도 오래 걸리고 코드도 복잡해졌지만, 이렇게 간단한 식으로 도출되는 문제였다🙄😂
실제 코테였다면... 아찔...

 

🕵️‍♂️ 코드

function solution(numbers, k) {
  return numbers[((k - 1) * 2) % numbers.length];
}

 


📝 [Lv0] 주사위의 개수

👀 문제 설명

머쓱이는 직육면체 모양의 상자를 하나 가지고 있는데 이 상자에 정육면체 모양의 주사위를 최대한 많이 채우고 싶습니다. 상자의 가로, 세로, 높이가 저장되어있는 배열 box와 주사위 모서리의 길이 정수 n이 매개변수로 주어졌을 때, 상자에 들어갈 수 있는 주사위의 최대 개수를 return 하도록 solution 함수를 완성해주세요.

 

🚨 제한 사항

  • box의 길이는 3입니다.
  • box[0] = 상자의 가로 길이
  • box[1] = 상자의 세로 길이
  • box[2] = 상자의 높이 길이
  • 1 ≤ box의 원소 ≤ 100
  • 1 ≤ n ≤ 50
  • n  box의 원소
  • 주사위는 상자와 평행하게 넣습니다.

 

💻 입출력 예

box n result
[1, 1, 1] 1 1
[10, 8, 6] 3 12

 

✨ 풀이 설명

위의 문제에서 탈탈 털려서 그런지 '주사위를 어긋나게 넣으면 많이 들어가지 않나'라고 생각했는데 제한 사항을 보고 어긋난 내 마음이나 고쳐먹기로 했다.

평행하게 놓는다면, 문제는 간단히 각 면의 길이를 n으로 나눈 몫의 곱으로 해결할 수 있다.
나머지가 생길 경우는 어차피 주사위를 꾸겨서 넣을 수도 없는 모양이니 남은 공간을 포기해야 한다.
그래서 reduce()를 사용해서 초깃값 1에 각 면을 n으로 나눈 몫을 곱해 반환해 주었다.

 

🕵️‍♂️ 코드

function solution(box, n) {
  return box.reduce((count, side) => count * Math.floor(side / n), 1);
}

 


📝 [Lv0] 2차원으로 만들기

👀 문제 설명

정수 배열 num_list와 정수 n이 매개변수로 주어집니다. num_list를 다음 설명과 같이 2차원 배열로 바꿔 return하도록 solution 함수를 완성해주세요.

num_list가 [1, 2, 3, 4, 5, 6, 7, 8] 로 길이가 8이고 n이 2이므로 num_list를 2 * 4 배열로 다음과 같이 변경합니다. 2차원으로 바꿀 때에는 num_list의 원소들을 앞에서부터 n개씩 나눠 2차원 배열로 변경합니다.

 

🚨 제한 사항

  • num_list의 길이는 n의 배 수개입니다.
  • 0 ≤ num_list의 길이 ≤ 150
  • 2 ≤ n < num_list의 길이

 

💻 입출력 예

num_list n result
[1, 2, 3, 4, 5, 6, 7, 8] 2 [[1, 2], [3, 4], [5, 6], [7, 8]]
[100, 95, 2, 4, 5, 6, 18, 33, 948] 3 [[100, 95, 2], [4, 5, 6], [18, 33, 948]]

 

✨ 풀이 설명

2차원으로 바뀐 배열의 길이는 num_list의 길이를 n으로 나눈 개수가 된다.
즉, num_list / 2 크기만큼의 배열을 만들고, 각 인덱스에 n 개씩 차례로 넣어주면 된다.

reduce()를 사용해 새로운 배열을 생성해 보았다.
먼저, 빈 배열을 초깃값으로 설정해 준 후, num_list의 값을 n으로 나눈 값이 0일 경우와 아닐 경우를 구분해 주었다.
이렇게 한 이유는, n으로 나누어 떨어질 때는 새로운 인덱스를 추가해 주어야하기 때문이다.
두 번째 예제를 기준으로 각 반복문에 newList를 console.log()로 찍어보면 아래와 같이 출력된다.

[ [ 100 ] ]
[ [ 100, 95 ] ]
[ [ 100, 95, 2 ] ]
[ [ 100, 95, 2 ], [ 4 ] ]
[ [ 100, 95, 2 ], [ 4, 5 ] ]
[ [ 100, 95, 2 ], [ 4, 5, 6 ] ]
[ [ 100, 95, 2 ], [ 4, 5, 6 ], [ 18 ] ]
[ [ 100, 95, 2 ], [ 4, 5, 6 ], [ 18, 33 ] ]
[ [ 100, 95, 2 ], [ 4, 5, 6 ], [ 18, 33, 948 ] ]

이렇게 반복하다 보면, n 개씩 들어있는 2차원 배열이 완성된다.

 

🕵️‍♂️ 코드

function solution(num_list, n) {
  return num_list.reduce((newList, item, idx) => {
    if (idx % n) newList[newList.length - 1].push(item);
    else newList.push([item]);
    return newList;
  }, []);
}

 


📝 [Lv0] 배열 회전시키기

👀 문제 설명

정수가 담긴 배열 numbers와 문자열 direction가 매개변수로 주어집니다. 배열 numbers의 원소를 direction방향으로 한 칸씩 회전시킨 배열을 return하도록 solution 함수를 완성해주세요.

 

🚨 제한 사항

  • 3 ≤ numbers의 길이 ≤ 20
  • direction은 "left" 와 "right" 둘 중 하나입니다.

 

💻 입출력 예

numbers direction result
[1, 2, 3] "right" [3, 1, 2]
[4, 455, 6, 4, -1, 45, 6] "left" [455, 6, 4, -1, 45, 6, 4]

 

✨ 풀이 설명

오른쪽으로 밀게 되면 가장 마지막의 숫자가 맨 앞으로 오게 되고, 왼쪽으로 밀게 되면 가장 앞의 숫자가 맨 뒤로 가게 된다.
이번 문제는 push(), pop(), shift(), unshift()를 할 줄 알면 간단히 풀 수 있는 문제다.
push(x) - 배열의 가장 마지막에 원소를 추가함
pop() - 배열의 가장 마지막 원소를 뺌
shift() - 배열의 가장 첫 원소를 뺌
unshift(x) - 배열의 가장 첫 부분에 원소를 추가함

즉, 방향이 오른쪽일 때에는 pop()으로 뺀 원소를 unshift()로 맨 앞에 추가해 주면 되고, 방향이 왼쪽일 때에는 shift()로 맨 앞 원소를 빼, push()로 맨 뒤에 추가해주면 된다.

 

🕵️‍♂️ 코드

 
function solution(numbers, direction) {
  if (direction === 'right') {
    const last = numbers.pop();
    numbers.unshift(last);
  } else {
    const first = numbers.shift();
    numbers.push(first);
  }
  return numbers;
}
 

📝 [Lv0] 최댓값 만들기(1)

👀 문제 설명

정수 배열 numbers가 매개변수로 주어집니다. numbers의 원소 중 두 개를 곱해 만들 수 있는 최댓값을 return하도록 solution 함수를 완성해주세요.

 

🚨 제한 사항

  • 0 ≤ numbers의 원소 ≤ 10,000
  • 2 ≤ numbers의 길이 ≤ 100

 

💻 입출력 예

numbers result
[1, 2, 3, 4, 5] 20
[0, 31, 24, 10, 1, 9] 744

 

✨ 풀이 설명

numbers의 원소 중 두 개를 곱해 만들 수 있는 최댓값은 가장 큰 수 두 개를 곱하는 것이다. 따라서 sort()를 통해 내림차순 정렬을 해주면 0번째와 1번째가 가장 큰 두 수임을 알 수 있다. 두 수의 곱을 반환해 주면 된다.

 

🕵️‍♂️ 코드

function solution(numbers) {
  numbers.sort((prev, next) => next - prev);
  return numbers[0] * numbers[1];
}

 

728x90