Uknow's Lab.
article thumbnail

https://www.acmicpc.net/problem/14891

 

14891번: 톱니바퀴

총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴

www.acmicpc.net

 

난이도 : 골드 5
태그 : 구현, 시뮬레이션

 


설명

구현 문제로써,  문제의 지문을 읽고 그대로 구현하여 풀었던 문제입니다.

 

 

각 톱니바퀴(gear라는 이름으로 변수명을 지었습니다) 는 LinkedList<Char>를 이용하여 구현하였고,

4개의 톱니가 존재하므로 길이가 4인 배열을 생성 및 초기화 하였습니다.

val gear = Array(4) { LinkedList<Char>() }

 

 

입력값 저장

for (i in 0 until 4) {
    readLine()!!.forEach {
        gear[i].add(it)
    }
}

4개의 톱니(gear)에 입력값을 각각 저장합니다.

각 톱니는 링크드 리스트를 사용하여 12시 값 부터 시계 방향으로 총 8개의 값을 받으며,

오른쪽의 경우 리스트의 2번째 인덱스가, 왼쪽의 경우 리스트의 6번째 인덱스가 해당 값을 가지게 됩니다.

 

 

그림으로 표현하자면, 위와 같이 표현할 수 있습니다.

 

 


각 톱니바퀴의 회전 처리

val n = readLine()!!.toInt()

for (i in 0 until n) {
    val input = readLine()!!.split(" ")
    val gearIdx = input[0].toInt() - 1
    val direction = input[1].toInt() // 1 : 시계방향, -1 : 반시계방향

    val isRotate = arrayOf(false, false, false, false)
    val flags = arrayOf(0, 0, 0, 0)
    flags[gearIdx] = direction
    isRotate[gearIdx] = true


    for (j in gearIdx until 3) {
        if (gear[j][2] != gear[j + 1][6]) {
            isRotate[j + 1] = true
            flags[j + 1] = flags[j] * -1
        } else {
            break
        }
    }

    for (j in gearIdx downTo 1) {
        if (gear[j][6] != gear[j - 1][2]) {
            isRotate[j - 1] = true
            flags[j - 1] = flags[j] * -1
        } else {
            break
        }
    }

    for (j in 0 until 4) {
        if (isRotate[j]) {
            when (flags[j]) {
                1 -> {
                    gear[j].addFirst(gear[j].removeLast())
                }

                -1 -> {
                    gear[j].addLast(gear[j].removeFirst())
                }
            }
        }
    }
}

각 톱니바퀴의 회전을 처리하는 부분입니다. 하나씩 살펴보도록 하겠습니다.

 

 

 

 

val input = readLine()!!.split(" ")
val gearIdx = input[0].toInt() - 1
val direction = input[1].toInt() // 1 : 시계방향, -1 : 반시계방향

val isRotate = arrayOf(false, false, false, false)
val flags = arrayOf(0, 0, 0, 0)
flags[gearIdx] = direction
isRotate[gearIdx] = true

먼저, 사용되는 변수는 위와 같습니다.

 

gearIdx는 몇 번째 기어인지를,

direction은 방향을 담는 변수입니다. ( 1: 시계방향, -1: 반시계방향 )

 

isRotate는 회전이 되었는가를 담을 변수이며,

flags는 각 톱니바퀴가 회전하는 방향을 담을 변수입니다.

 

direction은 input값으로 받은 기어의 회전 방향을,

flags는 각 기어의 회전 방향을 담으니 혼동 없으시길 바랍니다.

 

 

for (j in gearIdx until 3) {
    if (gear[j][2] != gear[j + 1][6]) {
        isRotate[j + 1] = true
        flags[j + 1] = flags[j] * -1
    } else {
        break
    }
}

for (j in gearIdx downTo 1) {
    if (gear[j][6] != gear[j - 1][2]) {
        isRotate[j - 1] = true
        flags[j - 1] = flags[j] * -1
    } else {
        break
    }
}

 

그 후, 선택된 기어를 기준으로 좌우 방향으로 반복문을 돌립니다.

 

오른쪽 방향으로는 현재 타겟 기어의 오른쪽(idx = 2)와 다음 타겟 기어의 왼쪽(idx = 6)을 비교하여

같은 극일땐 회전하지 않도록, 서로 다른 극일땐 회전하도록 isRotate 변수의 값을 조정합니다.

 

회전 방향을 담는 flags는 이전 기어의 반대 방향이니 -1을 곱하여 부호를 반대로 지정해주었습니다.

 

왼쪽 방향의 반복문도 오른쪽 방향의 반복문과 같습니다.

현재 타겟 기어의 왼쪽(idx = 6)과 다음 타겟 기어의 오른쪽(idx = 2)를 비교하여

같은 극일땐 회전하지 않도록, 다른 극일땐 회전하게끔 isRotate와 flags의 값을 조정합니다.

 

 

for (j in 0 until 4) {
    if (isRotate[j]) {
        when (flags[j]) {
            1 -> {
                gear[j].addFirst(gear[j].removeLast())
            }

            -1 -> {
                gear[j].addLast(gear[j].removeFirst())
            }
        }
    }
}

이후 회전이 될 기어(isRotate가 true)에 한하여 기어를 회전하면 됩니다.

 

리스트의 마지막 값을 빼서 처음에 두면 시계 방향으로,

리스트의 첫째 값을 빼서 마지막에 추가하면 반시계 방향으로 회전한 것 처럼 보이겠죠?

 

 

 

 

var score = 0

for (i in 0 until 4) {
    if (gear[i][0] == '1') score += (2.0.pow(i)).toInt()
}

println(score)

마지막으로 점수 계산입니다.

각 기어의 12시 값 (idx = 0)의 값이 N극 ( = '1) 일때 점수를 부여하면 되는데요.

1번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 1점
2번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 2점
3번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 4점
4번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 8점

 2의 idx 제곱이기에 2.0.pow(i)로 간단히 구할 수 있었습니다.

 

 


후기

구현 / 시뮬레이션 태그 문제였던 만큼, 문제의 지문을 잘 읽고 그대로 구현하면 풀 수 있던 문제였던 것 같습니다.

코틀린으로 도전해보는 첫 골드 문제였는데, 실버에 비해 갑자기 급상승한듯한 난이도에 당황했다가,

천천히 지문을 잘 읽고 풀어보니 생각보다 할만했던 문제였습니다.

 

골드 4, 3, 2, 1 문제들이 벌써 두렵긴 하지만 열심히 공부하면 풀 수 있겠죠 허허....

profile

Uknow's Lab.

@유노 Uknow

인생은 Byte와 Double 사이 Char다. 아무말이나 해봤습니다.