범위에 맞는 소용돌이를 구하고 숫자의 자릿수를 고려하여 공백을 삽입 후 출력하는 문제이다.
출력할 숫자를 담을 (r2 - r1 +1 ) * (c2 - c1 + 1)
크기의 2차원 배열을 만들고 소용돌이를 1부터 하나씩 숫자를 키워가며 해당 위치가 배열에 담길 위치인지 확인하며 배열에 담았다.
소용돌이를 탐색하기 위한 규칙으로는 우, 상, 좌, 하 방향으로 1->2, 2->3, 3->5, 5->7, 7->10, 10->13... 방향을 꺽고 직진할 칸 수를 늘려가는 규칙을 사용했다. (우,상), (좌,하)로 이동한 후 직진해야 할 칸 수가 늘어난다. 1, 1, 2, 2, 3, 3, 4, 4, ... 으로 직진할 칸수가 정해진다.
배열에 필요한 숫자를 모두 저장했는지 확인하기 위해 배열에 숫자를 저장할 때마다 개수를 세어 배열의 크기와 비교하였다.
숫자를 예쁘게 출력하기 위해 배열의 수들 중 자릿수가 가장 큰 수를 찾아야 하는데 이는 어짜피 가장 큰 수 이므로 이또한 배열에 수를 저장할 때 판단하여 따로 저장해두었다.
가장 큰 수의 자릿수를 계산하기 위해 수를 문자열로 바꾼 후 문자열의 길이를 측정하였고
각 행마다 새로운 문자열을 만들어 각 수의 자릿수와 가장 큰 수의 문자열과 비교하여 필요한 공백을 추가했다.
만든 문자열을 하나씩 출력하며 소용돌이를 예쁘게 출력할 수 있다.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int r1, c1, r2, c2;
int maxVal = 0;
vector<vector<int>> nums;
int max(int a, int b) { return a > b ? a : b; }
void makeSpiral(){
int x = 0;
int y = 0;
vector<int> dx = {0, -1, 0, 1};
vector<int> dy = {1, 0, -1, 0};
int val = 1;
int cnt = 1;
int dist = 1;
if (r1 <= x && x <= r2 && c1 <= y && y <= c2){
nums[x-r1][y-c1] = val; // nums[][] = 1;
++cnt;
}
int maxCnt = (r2 - r1 +1 ) * (c2 - c1 + 1);
while (cnt <= maxCnt){
for (int i=0; i<4; i++){
if (i == 2) dist++;
for (int d=0; d<dist; d++){
x += dx[i];
y += dy[i];
++val;
if (r1 <= x && x <= r2 && c1 <= y && y <= c2){
nums[x-r1][y-c1] = val;
maxVal = max(val, maxVal);
cnt++;
}
}
}
dist++;
}
}
int main() {
cin >> r1 >> c1 >> r2 >> c2;
nums.assign(r2 - r1 + 1, vector<int>(c2 - c1 + 1, 0));
makeSpiral();
int maxLen = to_string(maxVal).length();
vector<string> answer;
for (int i=0; i<r2-r1+1; i++){
string line="";
for (int j=0; j<c2-c1+1; j++){
string temp = to_string(nums[i][j]);
for (int blank=0; blank < maxLen - temp.length(); blank++){
line += " ";
}
line += temp + " ";
}
answer.push_back(line);
}
for (auto ans : answer){
cout << ans << "\n";
}
return 0;
}
큰 도움이 되었습니다, 감사합니다.