[코드트리 조별과제 4주차 코딩테스트 연습] 구간 칠하기 (흰검 칠하기) 문제 풀이 with 자바스크립트(Javascript) & 자바(Java)

Re_Go·2024년 8월 11일
0

코딩테스트연습

목록 보기
104/106
post-thumbnail

1. 첫번째 문제 풀이(2024-08-10)

솔직히 이 문제는 제가 여태 풀었던 코딩 문제 중에 역대급으로 어려운 문제이자 제가 이 문제를 풀면서 "아... 코테 때려칠까?" 라는 생각을 가지게 만들게 해준 문제였습니다. 그 만큼 xp도 역대급으로 높았던 문제였고, 그래서 풀어냈을때의 그 짜릿한 쾌감은... 진짜 어려웠던 만큼 역대급으로 높았지 않나 싶습니다.

아무튼 개념 설명은 이 곳을 한 번 참고해 보시면 좋을 것 같고, 그림 설명으로 코드의 흐름을 한 번 보여드리도록 하겠습니다.

거의 마지막에 W 타일이 하나가 추가됬는데 제가 깜빡하고 계산을 잘못해서.... 아무튼 애교로 봐주십쇼 ㅎㅎ

아무튼 이런 알고리즘으로 해당 코드는 동작하는데, 이때 주의할 점은 꼭 최소값 최대값을 구할 때 -1를 해주어야 한다는 것입니다. 그 이유는 타일을 셀 때 서 있는 타일부터 세기 때문이고요. (전 이것 때문에 몇 시간을 해매다 어느 귀하신 분 덕분에 해결할 수 있었습니다 ㅜㅜ)

for문을 돌리면서 범위에 대해서도 해당 포지션이 넘어갈 때 break로 for문을 끝내야 합니다.

물론 다른 분들은 넉넉히 배열을 한 십 만개에서 이십 만개를 만드셨다는데 저는 그렇게 배열을 만드는 법은 알고 있긴 한데 왠지 오기가 생겨서... 그래서 그냥 딱 정해진 만큼 배열을 만들고 범위가 넘어가는 포지션은 과감히 break로 빼버리는 선택을 했습니다.

그럼 그렇게 여섯 시간을 쌩고생 해서 겨우 풀은 문제의 JS 코드를 소개해 드리겠습니다!!

  1. JS 버전
const fs = require('fs');
const input = fs.readFileSync('/dev/stdin').toString().trim().split("\n");

const [lines, orderArr] = [input.shift(), input.map(arr => arr.split(" "))];

// 배열의 최소, 최대값을 구할 변수들을 선언
let min = 0;
let max = 0;
let num = 0;

// 배열의 최소 범위와 최대 범위를 계산하는 구간, 
orderArr.forEach(order => {
    let temp = 0;
    if (order[1] === 'R') temp = parseInt(order[0]) - 1;
    else temp = -(parseInt(order[0] - 1));

    num += temp;
    if (num < min) min = num;
    if (num > max) max = num;
});

// size는 최대값에 최소값을 빼고 1로 보정함. 만약 최소값이 음수면 그만큼 사이즈는 넓어지고, 양수라면 그만큼 정상적으로 빼지는 만큼 배열 보정이 가능함.
const size = max - min + 1;

// 배열들 준비
const accumulator = Array(size).fill(0);
const blackArr = Array(size).fill(0);
const whiteArr = Array(size).fill(0);
const colorArr = Array(size).fill('');

// 초기 position을 최소값의 절대값으로 바꿔 안전성을 보장
let position = Math.abs(min);

// for문을 돌림
for (let order of orderArr) {
  	// steps는 각 오더의 첫번째(걸음 수) 수
    const steps = parseInt(order[0]);
  	// 오더가 R(오른쪽) 이면 그림 설명대로 진행
    if (order[1] === 'R') {
        for (let i = 0; i < steps; i++) {
            accumulator[position]++;
            blackArr[position]++;
            colorArr[position] = 'B';
	
  	// 중간에 검은 타일과 흰 타일의 해당 포지션의 값이 각각 2 이상이면 컬러 타일의 해당 포지션을 G로 바꿔줌
            if (whiteArr[position] >= 2 && blackArr[position] >= 2) colorArr[position] = 'G';
            position++;
			// position은 절대값이므로 음수일 리가 없는데, 만약 이 값이 음수이거나 배열의 길이를 벗어나 커진 경우, 즉 범위를 벗어난 경우라면 for문을 즉시 종료
            if (position < 0 || position > accumulator.length) break;

        }
        position--; // R 명령 후 position 조정
    }

    if (order[1] === 'L') {
        for (let i = 0; i < steps; i++) {
            accumulator[position]++;
            whiteArr[position]++;
            colorArr[position] = 'W';

            if (whiteArr[position] >= 2 && blackArr[position] >= 2) colorArr[position] = 'G';
            position--;

            if (position < 0 || position > accumulator.length) break;
        }
        position++; // L 명령 후 position 조정
    }
}

// 결과 계산을 위한 result 배열
let result = [0, 0, 0];

// 이하 그림 설명과 같음
for (let i = 0; i < colorArr.length; i++) {
    if (colorArr[i] === 'W') result[0]++;
    if (colorArr[i] === 'B') result[1]++;
    if (colorArr[i] === 'G') result[2]++;
}

// join으로 배열의 요소를 공백으로 묶어서 양쪽 공백 제거 후 결과 출력 
console.log(result.join(' ').trim());
  1. 자바 버전
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 입력 읽기
        int lines = Integer.parseInt(scanner.nextLine().trim());
        List<String[]> orderArr = new ArrayList<>();

        for (int i = 0; i < lines; i++) {
            orderArr.add(scanner.nextLine().trim().split(" "));
        }

        int min = 0;
        int max = 0;
        int num = 0;

        // Min과 Max를 정확히 계산하여 배열의 크기를 맞춤
        for (String[] order : orderArr) {
            int steps = Integer.parseInt(order[0]);
            int temp = 0;

            if ("R".equals(order[1])) {
                temp = steps - 1;
            } else if ("L".equals(order[1])) {
                temp = -(steps - 1);
            }

            num += temp;
            if (num < min) min = num;
            if (num > max) max = num;
        }

        // 범위 설정: 음수 값을 보정하는 offset 사용
        int size = max - min + 1;

        int[] accumulator = new int[size];
        int[] blackArr = new int[size];
        int[] whiteArr = new int[size];
        char[] colorArr = new char[size];
        Arrays.fill(colorArr, ' ');

        // 초기 position을 offset으로 설정하여 항상 양수 인덱스를 사용
        int position = Math.abs(min);

        for (String[] order : orderArr) {
            int steps = Integer.parseInt(order[0]);

            if ("R".equals(order[1])) {
                for (int i = 0; i < steps; i++) {
                    accumulator[position]++;
                    blackArr[position]++;
                    colorArr[position] = 'B';

                    if (whiteArr[position] >= 2 && blackArr[position] >= 2) {
                        colorArr[position] = 'G';
                    }
                    position++;

                    if (position < 0 || position >= accumulator.length) break;
                }
                position--; // R 명령 후 position 조정
            }

            if ("L".equals(order[1])) {
                for (int i = 0; i < steps; i++) {
                    accumulator[position]++;
                    whiteArr[position]++;
                    colorArr[position] = 'W';

                    if (whiteArr[position] >= 2 && blackArr[position] >= 2) {
                        colorArr[position] = 'G';
                    }
                    position--;

                    if (position < 0 || position >= accumulator.length) break;
                }
                position++; // L 명령 후 position 조정
            }
        }

        // 결과 계산
        int[] result = new int[3]; // W, B, G 카운트
        for (int i = 0; i < colorArr.length; i++) {
            if (colorArr[i] == 'W') result[0]++;
            if (colorArr[i] == 'B') result[1]++;
            if (colorArr[i] == 'G') result[2]++;
        }

        // 결과 출력
        System.out.println(result[0] + " " + result[1] + " " + result[2]);
    }
}

2. 자바와 자바스크립트 풀이 차이점

뭐... 이번 주간 문제들은 알고리즘 푸는 방식이다보니 다르고 자시고간에 문제 그 자체를 푸느라 차이점을 못느꼈습니다. 하하... 풀어야죠뭐.... 하하....

이번에 기초 과정을 완료해서 얻은 배지까지 하나 하나 모일때마다 뿌듯하다는 생각이 들었습니다. (물론 남은 무료 기간이 얼마 남지 않았다는 걸 알게 되니까 슬퍼진다는...

그리고 이번 주는 국비 학원에서 꽤나 바빠서 코테에 신경을 쓰지 못했죠... (문제가 점점 어려워 져서 생각이 많아지는 것도 한 몫 한 듯...)

그래도 포기 하지 말고 화이팅!

profile
인생은 본인의 삶을 곱씹어보는 R과 타인의 삶을 배워 나아가는 L의 연속이다.

0개의 댓글