백준 15662 - 톱니바퀴 (2)

Updated:

Java

15662 번 - 톱니바퀴 (2)

문제

접근 방법

톱니바퀴 하나를 Deque을 사용하고, List<Deque>을 통해 전체 톱니바퀴를 구현하였다.

톱니바퀴의 양옆을 비교하는 방식은 다음과 같다.

  • 왼쪽 비교
    현재 톱니바퀴의 Deque에 뒤에서 1개를 뺀다. 왼쪽 톱니바퀴의 Deque에 앞에서 2개를 뺀다.

    현재 톱니바퀴 Deque의 Last와 왼쪽 톱니바퀴 First가 다른지 확인

  • 오른쪽 비교 현재 톱니바퀴의 Deque에 앞에서 2개를 뺀다. 왼쪽 톱니바퀴의 Deque에 뒤에서 1개를 뺀다.

    현재 톱니바퀴 Deque의 First와 왼쪽 톱니바퀴 Last가 다른지 확인

코드

import java.util.*;
import java.io.*;

public class Main {
	static int n, result;
	static List<Deque<Integer>> gear;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	StringTokenizer stk;
    	n = stoi(br.readLine());	// 톱니바퀴의 개수

    	// 톱니바퀴 상태 입력
    	String str;
    	gear = new ArrayList<>();
    	// 톱니바퀴 개수만큼 입력 받는다.
    	for(int i = 0; i < n; i++) {
    		str = br.readLine();
    		gear.add(new ArrayDeque<Integer>());
    		// 톱니는 8개
    		for(int j = 0; j < 8; j++) {
    			gear.get(i).add(str.charAt(j) - '0');
    		}
    	}

    	// 톱니바퀴 회전
    	int k = stoi(br.readLine());
    	int idx, dir;
    	for(int i = 0; i < k; i++) {
    		stk = new StringTokenizer(br.readLine());
    		idx = stoi(stk.nextToken()) - 1; // 돌릴 톱니바퀴의 순서
    		dir = stoi(stk.nextToken());	// 방향, 1 : 시계방향 / -1 : 반시계 방향

    		turnGear(idx,dir, false, false);
    	}

    	for(Deque<Integer> oneGear : gear) {
    		if(oneGear.peekFirst() == 1)
    			result++;
    	}

    	System.out.println(result);
    	br.close();
	}

	private static void turnGear(int idx, int dir, boolean leftTurned, boolean rightTurned) {
		Stack<Integer> temp = new Stack<>();
		int tempL;
		boolean leftDiff = false, rightDiff = false;
		// 현재 기어의 오른쪽을 확인한다.
		if(idx != n - 1 && !rightTurned) {
			temp.add(gear.get(idx).pollFirst());
			temp.add(gear.get(idx).pollFirst());
			tempL = gear.get(idx + 1).pollLast();

			if(gear.get(idx).peekFirst() != gear.get(idx + 1).peekLast())
				rightDiff = true;

			gear.get(idx).addFirst(temp.pop());
			gear.get(idx).addFirst(temp.pop());
			gear.get(idx + 1).addLast(tempL);
		}

		// 현재 기어의 왼쪽을 확인한다.
		if(idx != 0 && !leftTurned) {
			temp.add(gear.get(idx - 1).pollFirst());
			temp.add(gear.get(idx - 1).pollFirst());
			tempL = gear.get(idx).pollLast();

			if(gear.get(idx - 1).peekFirst() != gear.get(idx).peekLast())
				leftDiff = true;

			gear.get(idx - 1).addFirst(temp.pop());
			gear.get(idx - 1).addFirst(temp.pop());
			gear.get(idx).addLast(tempL);
		}

		turnOneGear(idx, dir);

		// 왼쪽 기어가 돌아가면
		if(leftDiff) {
			turnGear(idx - 1, reverse(dir), false, true);
		}
		// 오른쪽 기어가 돌아가면
		if(rightDiff) {
			turnGear(idx + 1, reverse(dir), true, false);
		}
	}
	// 방향을 바꾼다.
	private static int reverse(int dir) {
		if(dir == 1)
			return -1;
		else
			return 1;
	}
	// 기어 하나를 돌린다.
	private static void turnOneGear(int idx, int dir) {
		int temp;
		if(dir == 1) { // 시계 방향
			temp = gear.get(idx).pollLast();
			gear.get(idx).addFirst(temp);
		}
		else {	// 반시계 방향
			temp = gear.get(idx).pollFirst();
			gear.get(idx).addLast(temp);
		}
	}

	static int stoi(String str) {
    	return Integer.parseInt(str);
    }
}

총평

후기

개선할 점