본문 바로가기
  • 개발하는 곰돌이
Algorithm/BOJ

[Kotlin] 백준 25240 : 가희와 파일 탐색기 2

by 개발하는 곰돌이 2023. 12. 30.

문제 링크

 

25240번: 가희와 파일 탐색기 2

Q개의 질문에 대해, 연산이 성공하면 1을 실패하면 0을 출력해 주세요. 각 질문에 대한 답은 한 줄에 하나씩 출력해 주세요.

www.acmicpc.net


문제 해설

리눅스의 파일 권한과 관련된 문제. 관련 지식이 있다면 어렵지 않게 풀 수 있다.

 

우선 각 권한을 2진수로 바꿔보자.

\begin{align*}
000 &\to 권한 없음\\
001 &\to 실행 가능\\
010 &\to 수정 가능\\
011 &\to 실행 및 수정 가능\\
100 &\to 읽기 가능\\
101 &\to 읽기 및 실행 가능\\
110 &\to 읽기 및 수정 가능\\
111 &\to 읽기, 수정, 실행 모두 가능
\end{align*} 

여기서 \(2^2\)에 해당하는 비트는 읽기 권한을, \(2^1\)에 해당하는 비트는 수정 권한을, \(2^0\)에 해당하는 비트는 실행 권한을 나타낸다는 것을 알 수 있다.

 

유저의 권한그룹이 갖는 권한과 유저가 수행하려는 작업에 해당하는 숫자를 AND 연산해서 그 결과가 수행하려는 작업에 해당하는 숫자라면 해당 작업을 수행할 수 있다는 뜻이 된다.

 

이제 구현을 해보자.

 

각 유저는 유저의 이름에 해당하는 그룹에 포함되고, 추가적으로 입력으로 주어지는 그룹이 더 있다면 해당 그룹에도 포함된다.

val userGroup = HashMap<String, Set<String>>()
repeat(u) {
    StringTokenizer(readLine()).apply {
        val user = nextToken()
        val group = HashSet<String>().apply { add(user) }
        if (hasMoreTokens()) StringTokenizer(nextToken(), ",").apply { while (hasMoreTokens()) group.add(nextToken()) }
        userGroup[user] = group
    }
}

각 파일의 정보를 Map에 저장해준다. 이 때 각 파일별로 부여된 권한과 소유자, 소유 그룹에 대한 정보를 갖는 File 클래스도 작성해준다.

val files = HashMap<String, File>()
repeat(f) { _ ->
    StringTokenizer(readLine()).apply { files[nextToken()] = File(nextToken().run { IntArray(3) { get(it) - '0' } }, nextToken(), nextToken()) }
}
private class File(val mode: IntArray, val owner: String, val group: String)

마지막으로 파일에 수행하려는 작업의 성공 여부를 판별해주면 된다.

 

작업을 하려는 유저가 소유자라면 mode의 0번째 요소, 소유자가 아니지만 소유그룹에 포함된다면 1번째 요소, 둘 다 아니라면 2번째 요소를 가져와서 수행하려는 작업에 해당하는 숫자와 AND 연산을 해서 성공 여부를 판별해주면 된다.

repeat(readLine().toInt()) {
    StringTokenizer(readLine()).apply {
        val user = nextToken()
        val fileName = nextToken()
        val command = nextToken()
        val file = files[fileName]!!
        val mode = file.mode.let { if (file.owner == user) it[0] else if (userGroup[user]!!.contains(file.group)) it[1] else it[2] }
        val success = when (command) {
            "R" -> mode and 4 == 4
            "W" -> mode and 2 == 2
            "X" -> mode and 1 == 1
            else -> false
        }
        bw.write(if (success) "1\n" else "0\n")
    }
}

Code

import java.util.StringTokenizer

fun main() = with(System.`in`.bufferedReader()) {
    val bw = System.out.bufferedWriter()
    val (u, f) = readLine().split(' ').map { it.toInt() }
    val userGroup = HashMap<String, Set<String>>()
    repeat(u) {
        StringTokenizer(readLine()).apply {
            val user = nextToken()
            val group = HashSet<String>().apply { add(user) }
            if (hasMoreTokens()) StringTokenizer(nextToken(), ",").apply { while (hasMoreTokens()) group.add(nextToken()) }
            userGroup[user] = group
        }
    }
    val files = HashMap<String, File>()
    repeat(f) { _ ->
        StringTokenizer(readLine()).apply { files[nextToken()] = File(nextToken().run { IntArray(3) { get(it) - '0' } }, nextToken(), nextToken()) }
    }
    repeat(readLine().toInt()) {
        StringTokenizer(readLine()).apply {
            val user = nextToken()
            val fileName = nextToken()
            val command = nextToken()
            val file = files[fileName]!!
            val mode = file.mode.let { if (file.owner == user) it[0] else if (userGroup[user]!!.contains(file.group)) it[1] else it[2] }
            val success = when (command) {
                "R" -> mode and 4 == 4
                "W" -> mode and 2 == 2
                "X" -> mode and 1 == 1
                else -> false
            }
            bw.write(if (success) "1\n" else "0\n")
        }
    }
    bw.close()
}

private class File(val mode: IntArray, val owner: String, val group: String)

'Algorithm > BOJ' 카테고리의 다른 글

[Kotlin] 백준 13199 : 치킨 먹고 싶다  (0) 2024.03.25
[Kotlin] 백준 3107 : IPv6  (0) 2024.02.20
[Kotlin] 백준 11082 : 소수를 분수로  (0) 2023.12.11
[Kotlin] 백준 1850 : 최대공약수  (2) 2023.11.11
[Kotlin] 백준 30036 : INK  (0) 2023.10.25

댓글