컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 wallpaper
가 주어집니다. 파일들은 바탕화면의 격자칸에 위치하고 바탕화면의 격자점들은 바탕화면의 가장 왼쪽 위를 (0, 0)으로 시작해 (세로 좌표, 가로 좌표)로 표현합니다. 빈칸은 ".", 파일이 있는 칸은 "#"의 값을 가집니다. 드래그를 하면 파일들을 선택할 수 있고, 선택된 파일들을 삭제할 수 있습니다. 머쓱이는 최소한의 이동거리를 갖는 한 번의 드래그로 모든 파일을 선택해서 한 번에 지우려고 하며 드래그로 파일들을 선택하는 방법은 다음과 같습니다.
lux
, luy
)를 마우스 왼쪽 버튼으로 클릭한 상태로 격자점 E(rdx
, rdy
)로 이동한 뒤 마우스 왼쪽 버튼을 떼는 행동입니다. 이때, "점 S에서 점 E로 드래그한다"고 표현하고 점 S와 점 E를 각각 드래그의 시작점, 끝점이라고 표현합니다.lux
, luy
)에서 점 E(rdx
, rdy
)로 드래그를 할 때, "드래그 한 거리"는 |rdx
- lux
| + |rdy
- luy
|로 정의합니다.예를 들어 wallpaper
= [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다.
(0, 0)에서 (3, 5)로 드래그해도 모든 파일을 선택할 수 있지만 이때 드래그 한 거리는 (3 - 0) + (5 - 0) = 8이고 이전의 방법보다 거리가 늘어납니다.
머쓱이의 컴퓨터 바탕화면의 상태를 나타내는 문자열 배열 wallpaper
가 매개변수로 주어질 때 바탕화면의 파일들을 한 번에 삭제하기 위해 최소한의 이동거리를 갖는 드래그의 시작점과 끝점을 담은 정수 배열을 return하는 solution 함수를 작성해 주세요. 드래그의 시작점이 (lux
, luy
), 끝점이 (rdx
, rdy
)라면 정수 배열 [lux, luy, rdx, rdy]
를 return하면 됩니다.
wallpaper
의 길이 ≤ 50wallpaper[i]
의 길이 ≤ 50wallpaper
의 모든 원소의 길이는 동일합니다.wallpaper[i][j]
는 바탕화면에서 i + 1
행 j + 1
열에 해당하는 칸의 상태를 나타냅니다.wallpaper[i][j]
는 "#"
또는 "."
의 값만 가집니다.lux
, luy
)와 끝점 (rdx
, rdy
)는 lux < rdx
, luy < rdy
를 만족해야 합니다.function solution(wallpaper) {
const height = wallpaper.length;
const width = wallpaper[0].length;
let minHeight = wallpaper.length;
let minWidth = wallpaper[0].length;
let maxHeight = 0;
let maxWidth = 0;
for (let i = 0; i < height; i++) {
for (let j = 0; j < width; j++) {
if (wallpaper[i][j] === '#') {
if (i <= minHeight) {
minHeight = i;
}
if (i >= maxHeight) {
maxHeight = i;
}
if (j <= minWidth) {
minWidth = j;
}
if (j >= maxWidth) {
maxWidth = j;
}
}
}
}
return [minHeight, minWidth, maxHeight + 1, maxWidth + 1];
}
어느 학교에 페인트가 칠해진 길이가 n
미터인 벽이 있습니다. 페인트가 벗겨진 벽이 보기 흉해져 학교는 벽에 페인트를 덧칠하기로 했습니다.
이를 위해 벽을 1미터 길이의 구역 n
개로 나누고, 각 구역에 왼쪽부터 순서대로 1번부터 n
번까지 번호를 붙였습니다. 그리고 페인트를 다시 칠해야 할 구역들을 정했습니다.
벽에 페인트를 칠하는 롤러의 길이는 m
미터이고, 롤러로 벽에 페인트를 한 번 칠하는 규칙은 다음과 같습니다.
즉, 롤러의 좌우측 끝을 구역의 경계선 혹은 벽의 좌우측 끝부분에 맞춘 후 롤러를 위아래로 움직이면서 벽을 칠합니다. 현재 페인트를 칠하는 구역들을 완전히 칠한 후 벽에서 롤러를 떼며, 이를 벽을 한 번 칠했다고 정의합니다.
정수 n
, m
과 다시 페인트를 칠하기로 정한 구역들의 번호가 담긴 정수 배열 section
이 매개변수로 주어질 때 롤러로 페인트칠해야 하는 최소 횟수를 return 하는 solution 함수를 작성해 주세요.
m
≤ n
≤ 100,000section
의 길이 ≤ n
section
의 원소 ≤ n
section
의 원소는 페인트를 다시 칠해야 하는 구역의 번호입니다.section
에서 같은 원소가 두 번 이상 나타나지 않습니다.section
의 원소는 오름차순으로 정렬되어 있습니다.function solution(n, m, section) {
let answer = 0;
let lastPaintedWall = 0;
for (let i = 0; i < section.length; i++) {
if (section[i] < lastPaintedWall) {
continue;
}
if (section[i] >= lastPaintedWall) {
lastPaintedWall = section[i] + m;
answer += 1;
}
}
return answer;
}
코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.
예를 들어 첫 번째 카드 뭉치에 순서대로 ["i", "drink", "water"], 두 번째 카드 뭉치에 순서대로 ["want", "to"]가 적혀있을 때 ["i", "want", "to", "drink", "water"] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 "i"를 사용한 후 두 번째 카드 뭉치에서 "want"와 "to"를 사용하고 첫 번째 카드뭉치에 "drink"와 "water"를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.
문자열로 이루어진 배열 cards1
, cards2
와 원하는 단어 배열 goal
이 매개변수로 주어질 때, cards
1과 cards2
에 적힌 단어들로 goal
를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를 return하는 solution 함수를 완성해주세요.
cards1
의 길이, cards2
의 길이 ≤ 10cards1[i]
의 길이, cards2[i]
의 길이 ≤ 10cards1
과 cards2
에는 서로 다른 단어만 존재합니다.goal
의 길이 ≤ cards1
의 길이 + cards2
의 길이goal[i]
의 길이 ≤ 10goal
의 원소는 cards1
과 cards2
의 원소들로만 이루어져 있습니다.cards1
, cards2
, goal
의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다.function solution(cards1, cards2, goal) {
const cards1Count = cards1.length;
const cards2Count = cards1.length;
let cards1Index = 0;
let cards2Index = 0;
for (let i = 0; i < goal.length; i++) {
const word = goal[i];
if (cards1[cards1Index] === word) {
cards1Index += 1;
} else if (cards2[cards2Index] === word) {
cards2Index += 1;
} else {
return 'No';
}
}
return 'Yes';
}
틱택토는 두 사람이 하는 게임으로 처음에 3x3의 빈칸으로 이루어진 게임판에 선공이 "O", 후공이 "X"를 번갈아가면서 빈칸에 표시하는 게임입니다. 가로, 세로, 대각선으로 3개가 같은 표시가 만들어지면 같은 표시를 만든 사람이 승리하고 게임이 종료되며 9칸이 모두 차서 더 이상 표시를 할 수 없는 경우에는 무승부로 게임이 종료됩니다.
할 일이 없어 한가한 머쓱이는 두 사람이 하는 게임인 틱택토를 다음과 같이 혼자서 하려고 합니다.
틱택토는 단순한 규칙으로 게임이 금방 끝나기에 머쓱이는 한 게임이 종료되면 다시 3x3 빈칸을 그린 뒤 다시 게임을 반복했습니다. 그렇게 틱택토 수 십 판을 했더니 머쓱이는 게임 도중에 다음과 같이 규칙을 어기는 실수를 했을 수도 있습니다.
게임 도중 게임판을 본 어느 순간 머쓱이는 본인이 실수를 했는지 의문이 생겼습니다. 혼자서 틱택토를 했기에 게임하는 과정을 지켜본 사람이 없어 이를 알 수는 없습니다. 그러나 게임판만 봤을 때 실제로 틱택토 규칙을 지켜서 진행했을 때 나올 수 있는 상황인지는 판단할 수 있을 것 같고 문제가 없다면 게임을 이어서 하려고 합니다.
머쓱이가 혼자서 게임을 진행하다 의문이 생긴 틱택토 게임판의 정보를 담고 있는 문자열 배열 board
가 매개변수로 주어질 때, 이 게임판이 규칙을 지켜서 틱택토를 진행했을 때 나올 수 있는 게임 상황이면 1
을 아니라면 0
을 return 하는 solution 함수를 작성해 주세요.
board
의 길이 = board[i]
의 길이 = 3board
의 원소는 모두 "O"
, "X"
, "."
으로만 이루어져 있습니다.board[i][j]
는 i
+ 1행 j
+ 1열에 해당하는 칸의 상태를 나타냅니다."."
은 빈칸을, "O"
와 "X"
는 해당 문자로 칸이 표시되어 있다는 의미입니다.function solution(board) {
const boardLength = 3;
let countO = 0;
let countX = 0;
let bingoO = [0, 0, 0];
let bingoX = [0, 0, 0];
for (let row = 0; row < boardLength; row++) {
// 가로 빙고
if (board[row][0] === board[row][1] && board[row][1] === board[row][2] && board[row][0] !== '.') {
board[row][0] === 'O' ? bingoO[0] += 1 : bingoX[0] += 1;
}
// 세로 빙고
if (board[0][row] === board[1][row] && board[1][row] === board[2][row] && board[0][row] !== '.') {
board[0][row] === 'O' ? bingoO[1] += 1 : bingoX[1] += 1;
}
// O, X 개수
for (let col = 0; col < boardLength; col++) {
const value = board[row][col];
if (value === 'O') {
countO++;
}
if (value === 'X') {
countX++;
}
}
}
// 대각 빙고
if (board[0][0] === board[1][1] && board[1][1] === board[2][2] && board[1][1] !== '.') {
board[1][1] === 'O' ? bingoO[2] += 1 : bingoX[2] += 1;
}
if (board[0][2] === board[1][1] && board[1][1] === board[2][0] && board[1][1] !== '.') {
board[1][1] === 'O' ? bingoO[2] += 1 : bingoX[2] += 1;
}
const totalBingoO = bingoO.reduce((acc, num) => acc += num, 0);
const totalBingoX = bingoX.reduce((acc, num) => acc += num, 0);
// 선공이 후공보다 적거나 후공보다 2개 이상 앞선 경우
if (countO < countX || countO >= countX + 2) {
return 0;
}
// O, X 둘 다 빙고에 성공한 경우
if (totalBingoO > 0 && totalBingoX > 0) {
return 0;
}
// 빙고에 성공한 줄이 2개보다 많은 경우
if (bingoO.filter((num) => num > 1).length > 0 || bingoX.filter((num) => num > 1).length > 0) {
return 0;
}
// O의 승리 상황에서 X의 개수가 O의 개수와 같거나 큰 경우
if (totalBingoO > 0 && countX >= countO) {
return 0;
}
// X의 승리 상황에서 O의 개수가 X의 개수보다 많은 경우
if (totalBingoX && countO > countX) {
return 0;
}
// 그 외의 경우
return 1;
}