백준 10994번
ALGORITHM ·예시와 같이 규칙성을 통해, 별을 찍어야 할 위치를 지정해 그려주면 되는 간단한 문제였습니다. 하지만, 처음에 문제에서 규칙성을 찾고 문제를 해결하는 데에 몇 가지 어려운 점이 있었습니다.
*********
* *
* ***** *
* * * *
* * * * *
* * * *
* ***** *
* *
*********
첫 번째는 반복을 최대한 줄이는 방법이었습니다. 위의 형태에서 좌우, 상하 대칭인 점을 이용해, 가능한 적은 양의 연산을 하려고 했습니다. 여기서 필요했던 것이 아래 별들의 ‘전체의 길이’와 ‘절반까지의 길이’였습니다. 처음에 이 두 값이 필요하다는 것을 제대로 인지하지 못했고, 이로 인해 결론적으로 같은 계산을 하면 되는 상황들을 자꾸 다시 계산하는 문제가 생겼었습니다.
const count = +input[0];
// 처음에 주어진 값
const halfLength = count * 2 - 1;
// 절반의 값
const totalLength = 1 + (count - 1) * 4;
// 전체 길이의 값
두 번째 어려웠던 점은 규칙성을 적용하는 방식이였습니다. 문제를 풀면서 처음부터 한 줄마다 배열을 만들고, 그 안에서도 순회를 돌며 별을 채우는 방식을 사용하고자 했었습니다.
[["*", " ", "*"][("*", " ", "*")]];
// 각 줄마다의 별을 각 index마다 그려주고 이를 합쳐주고자 함
그런데 여기서 처음에 규칙성을 적용하고자 할 때 현재 방문한 줄의 index값(i)와 현재 방문한 정확한 지표의 index값(j)를 어떤 식으로 이어서 적용해야하는지 어려웠었는데, 오히려 i와 j의 값을 다른 계산없이 1:1로 비교를 해주면 된다는 것을 알게 됐습니다.
이를 통해, 아래와 같은 코드를 짤 수 있었습니다.
const resultArray = [];
// 결과가 모두 들어오는 배열
for (let i = 0; i < halfLength; i++) {
// 절반만큼만 순회하고, 나머지 절반은 순회동안 채워줌
const newLine = [];
// 현재 방문한 줄의 배열
// 현재 방문한 줄의 짝수, 홀수 여부에 따라 다른 규칙을 적용
// totalLength - 1 - j의 값을 통해 현재 방문한 곳의 반대편도 같은 값을 넣어줌
// i와 j의 비교만으로도 어떤 값을 넣을 지 지정이 가능함
if (!(i % 2)) {
for (let j = 0; j < halfLength; j++) {
if (!(j % 2)) {
newLine[j] = "*";
newLine[totalLength - 1 - j] = "*";
} else {
const marker = j < i ? " " : "*";
newLine[j] = marker;
newLine[totalLength - 1 - j] = marker;
}
}
} else {
for (let j = 0; j < halfLength; j++) {
if (!(j % 2)) {
const marker = j < i ? "*" : " ";
newLine[j] = marker;
newLine[totalLength - 1 - j] = marker;
} else {
newLine[j] = " ";
newLine[totalLength - 1 - j] = " ";
}
}
}
resultArray[i] = newLine;
resultArray[totalLength - 1 - i] = newLine;
}
const result = resultArray.map((v) => v.join("")).join("\n");
console.log(result);
이 문제를 풀면서 비록 쉬운 난이도의 문제여도, 정확하게 제게 필요한 값과 규칙성을 정리해놓지 못하면 풀이에 상당히 오랜 시간이 걸릴 수 있다는 것을 배울 수 있었습니다.