// rows * columns의 행렬이 있음
// x1 y1부터 x2 y2까지 해당하는 테두리를 시계방향으로 회전
// 쿼리를 수행한 후 제일 최솟값을 리턴
const rotation = ([x1, y1, x2, y2], arr) => {
x1--; y1--; x2--; y2--; // 0이 아닌 1이 시작점이니까 1씩 감소
const newArr = arr.map((row) => [...row]);
let min = arr[x1][y1]; // 최솟값 초기화
for(let i = y1; i < y2; i++){
newArr[x1][i+1] = arr[x1][i]; // 오른쪽으로 회전
if(arr[x1][i] < min) min = arr[x1][i];
}
for(let i = x1; i < x2; i++){
newArr[i+1][y2] = arr[i][y2]; // 아래로 회전
if(arr[i][y2] < min) min = arr[i][y2];
}
for(let i = y2; i > y1; i--){
newArr[x2][i-1] = arr[x2][i]; // 왼쪽으로 회전
if(arr[x2][i] < min) min = arr[x2][i];
}
for(let i = x2; i > x1; i--){
newArr[i-1][y1] = arr[i][y1];
if(arr[i][y1] < min) min = arr[i][y1];
}
return [newArr, min]
}
function solution(rows, columns, queries) {
let arr = [];
const answer = [];
let count = 1;
// 행렬을 만든다.
for(let x = 0; x < rows; x++){
const row = [];
for(let y = 0; y < columns; y++){
row.push(count++);
}
arr.push(row);
}
for(let i = 0; i < queries.length; i ++){
const [rotateArr, minVal] = rotation(queries[i], arr);
arr = rotateArr.map((row) => [...row]);
answer.push(minVal);
}
return answer;
}
function solution(rows, columns, queries) {
const answer = [];
let arr = Array.from(new Array(rows + 1), () =>
new Array(columns + 1).fill(0)
);
// 숫자 채우기
for (let i = 1; i <= rows; i++) {
for (let j = 1; j <= columns; j++) {
arr[i][j] = (i - 1) * columns + j;
}
}
for (let tc = 0; tc < queries.length; tc++) {
const [x1, y1, x2, y2] = queries[tc];
const stack = [];
// 맨 위 직사각형 고르기 x1은 행 고정, y1이 y2 직전까지 1씩 증가
for (let i = y1; i < y2; i++) stack.push(arr[x1][i]);
// 오른쪽 직사각형 고르기 y2는 고정, x1이 x2 직전까지 1씩 증가
for (let i = x1; i < x2; i++) stack.push(arr[i][y2]);
// 아래쪽 직사각형 고르기 x2는 고정, y2가 y1 직전까지 1씩 감소
for (let i = y2; i > y1; i--) stack.push(arr[x2][i]);
// 왼쪽 직사각형 고르기y1는 고정, x2가 x1 직전까지 1씩 감소
for (let i = x2; i > x1; i--) stack.push(arr[i][y1]);
// 정답 찾기
answer.push(Math.min(...stack));
const temp = stack.pop();
stack.unshift(temp);
for (let i = y1; i < y2; i++) arr[x1][i] = stack.shift();
for (let i = x1; i < x2; i++) arr[i][y2] = stack.shift();
for (let i = y2; i > y1; i--) arr[x2][i] = stack.shift();
for (let i = x2; i > x1; i--) arr[i][y1] = stack.shift();
}
return answer;
}
function solution(rows, columns, queries) {
//행렬에서 직사각형 모양의 범위를 여러번 선택해서 테두리부분을 시계방향으로 한칸씩 회전
//(x1,y1, x2, y2)는 직사각형범위 x가 행, y가 렬
// 쿼리를 인덱스값에 매칭이 되도록 1씩 빼준다.
const indexQueries=queries.map(query=>query.map(v=>v-1));
// 돌아야하는 board도 만들어준다.
const board= Array.from({length:rows} ,(_,i)=>Array.from({length:columns}, (_,idx)=>(i*columns)+(idx+1)));
const result =[];
for(let a of indexQueries){
// 어떻게 돌리냐?temp에 자기값을 넣고 앞에것을 땡겨온다.
//돌면서 값을 넣어줄 numbers
const numbers=new Set();
const [x1,y1, x2,y2]=a;
// 우선 시작값을 넣어준다.
let temp=[board[x1][y1]];
for(let i=y1+1; i<=y2; i++ ){
//앞에값을 빼오고 , 현재값은 넣어준다.
const pre=temp.shift();
numbers.add(pre);
temp.push(board[x1][i]);
//현재 자리에 할당
board[x1][i]=pre;
}
for(let i=x1+1; i<=x2; i++){
const pre=temp.shift();
numbers.add(pre);
temp.push(board[i][y2]);
board[i][y2]=pre
}
for(let i=y2-1; i>=y1; i--){
const pre= temp.shift();
numbers.add(pre);
temp.push(board[x2][i]);
board[x2][i]=pre;
}
for(let i=x2-1; i>=x1; i--){
const pre=temp.shift();
numbers.add(pre);
temp.push(board[i][y1]);
board[i][y1]=pre;
}
result.push(Math.min(...numbers))
}
return result
}
function cycle(board, query) {
const newBoard = board.map(row => [...row]); // 배열의 깊은복사
let [x1, y1, x2, y2] = query;
x1--;
y1--;
x2--;
y2--;
let minValue = board[x1][y1]; // 초기화
for (let y = y1; y < y2; y++) {
newBoard[x1][y + 1] = board[x1][y]
if (board[x1][y] < minValue) minValue = board[x1][y]
}
for (let x = x1; x < x2; x++) {
newBoard[x + 1][y2] = board[x][y2]
if (board[x][y2] < minValue) minValue = board[x][y2]
}
for (let y = y2; y > y1; y--) {
newBoard[x2][y - 1] = board[x2][y]
if (board[x2][y] < minValue) minValue = board[x2][y]
}
for (let x = x2; x > x1; x--) {
newBoard[x - 1][y1] = board[x][y1]
if (board[x][y1] < minValue) minValue = board[x][y1]
}
return [newBoard, minValue]; // 회전 후의 행렬과 회전한 원소들 중 최소값을 반환
}
function solution(rows, columns, queries) {
// 초기 행렬 생성
let board = Array
.from(Array(rows), () => new Array(columns).fill(0))
.map((row, rowIdx) => row.map((_, col) => rowIdx * columns + (col + 1) ))
const result = [];
queries.forEach((query) => {
const [newBoard, minValue] = cycle(board, query);
result.push(minValue);
board = newBoard.map(row => [...row]); // 회전 후의 행렬로 재할당(배열의 깊은 복사)해줍니다.
});
return result;
}
function solution(rows, columns, queries) {
const answer = [];
const d = [[0, 1], [1, 0], [0, -1], [-1, 0]];
const board = new Array(rows + 1).fill()
.map((_, i) => new Array(columns + 1).fill().map((_, j) => (i-1) * (columns) + j));
for(let [y1, x1, y2, x2] of queries){
let minValue = Infinity;
const dequeue = [];
const s = [[y1, x1], [y1, x2], [y2, x2], [y2, x1]];
let cnt = 0;
// 시계로 돌면서 원소를 배열에 담아줍니다.
for(let [dy, dx] of d){
let [ny, nx] = s[cnt];
let [ey, ex] = s[(cnt + 1) % 4];
while(ny !== ey || nx !== ex){
dequeue.push(board[ny][nx]);
minValue = Math.min(minValue, board[ny][nx]);
[ny, nx] = [ny + dy, nx + dx];
}
cnt++;
}
// 끝에 있는 원소를 빼내고 앞에다가 넣어줍니다.
dequeue.unshift(dequeue.pop());
cnt = 0;
let idx = 0;
// 다시 시계로 돌면서 배열의 원소를 넣어줍니다.
for(let [dy, dx] of d){
let [ny, nx] = s[cnt];
let [ey, ex] = s[(cnt + 1) % 4];
while(ny !== ey || nx !== ex){
board[ny][nx] = dequeue[idx++];
[ny, nx] = [ny + dy, nx + dx];
}
cnt++;
}
answer.push(minValue);
}
return answer;
}
function solution(rows, columns, queries) {
/* 접근 방법
1. 테두리를 4가지 방식으로 돌면서 min값 비교하여 넣기
2. min값 비교 -> 시계방향으로 회전시켜주기 -> 다음영역의 값 가지고있기
*/
const answer = [];
let board = Array.from({length: rows+1}, () => new Array(columns +1));
for(let i =1; i< rows+1 ; i++){
for(let j = 1; j < columns +1; j++){
board[i][j] = ((i-1)* columns + j );
}
}
queries.forEach(query => {
let [startX, startY, endX, endY] = query;
let min = rows * columns; // 최소값을 미리 초기화
let r = startX;
let c = startY;
//현재 값
let current = board[startX][startY];
let tmp = 0;
// 왼쪽 -> 오른쪽
for(let i = startY; i < endY ; i++){
if(current < min) min = current;
tmp = board[r][++c]; // 다음 영역의 값 저장
board[r][c] = current; // board 값 시계방향으로 옮기기
current = tmp; //다음 영역의 값을 current에 저장해서 다시 반복
}
// 위 -> 아래
for(let i = startX; i < endX; i++){
if(current < min) min = current;
tmp = board[++r][c];
board[r][c] = current;
current = tmp;
}
// 오른쪽 -> 왼쪽
for(let i = startY; i < endY; i++){
if(current < min) min = current;
tmp = board[r][--c];
board[r][c] = current;
current = tmp;
}
// 아래 -> 위
for(let i = startX; i < endX; i++){
if(current < min) min = current;
tmp = board[--r][c];
board[r][c] = current;
current = tmp;
}
answer.push(min);
})
return answer
}