Algorithm/프로그래머스

[프로그래머스>LV3] 외벽점검(Kotlin)

RIEN😚 2023. 4. 1. 12:51
728x90
반응형
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

1. 문제

빠른 공사 진행을 위해 점검 시간을 1시간으로 제한했습니다.

친구들이 1시간 동안 이동할 수 있는 거리는 제각각이기 때문에, 최소한의 친구들을 투입해 취약 지점을 점검하고 나머지 친그들은 내부 공사를 돕도록 하려고 합니다.

 

[입력]

  • 외벽의 길이 n
  • 취약 지점의 위치가 담긴 배열 weak
  • 각 친구가 1시간 동안 이동할 수 있는 거리가 담긴 배열 dist

[결과]

취약 지점을 점검하기 위해 보내야 하는 친구 수의 최솟값을 return

 

2. 풀이

문제를 먼저 보고 어떻게 풀어야 할까 고민을 오래한 문제가 아닐까 합니다. 😭

🌹 결론은 완전탐색으로 모든 경우를 확인해주면 풀 수 있는 문제입니다.ㅎㅎ

 

모든 경우를 탐색하기 위해서 처음으로 필요한 사항은 친구들을 투입하는 순서가 정해져 있지 않기 때문에

친구들을 투입할 수 있는 모든 가능한 순서들을 먼저 찾아낼 필요가 있습니다.

 

Python이었다면 라이브러리를 사용하면 되었지만, kotlin에서는 찾지 못해 결국 직접 구현하게 되었어요.😭

private fun <T> List<T>.permutations(k: Int): List<List<T>> {
    val result = mutableListOf<List<T>>()
    fun solve(k: Int, acc: MutableList<T>, visited: BooleanArray) {
        if (k == 0) {
            result.add(acc.toList())
            return
        }
        for ((index, i) in this.withIndex()) {
            if (visited[index].not()) {
                visited[index] = true
                acc.add(i)
                solve(k-1, acc, visited)
                acc.removeLast()
                visited[index] = false
            }
        }
    }

    val n = this.size
    solve(k, mutableListOf(), BooleanArray(n))
    return result.toList()
}

 

실제 사용하는 쪽에서는 간단하게 사용할 수 있도록 몇 개의 원소로 순열을 만들지 결정하는 k 값만 전달하면 되도록

메서드를 정의하였습니다. 🤗👍🏻

 

위 메서드를 사용해, 투입순서 배열은 👇🏻아래와 같이 받아올 수 있습니다.

val friendsNum = dist.size
val distPermu = dist.toList().permutations(friendsNum)

 

그 다음은 취약지점을 나타내는 weak 배열을 가공해 주어야 합니다.

🌹 외벽이 원형이기 때문에 마지막 지점에서 다시 처음지점까지 이동할 수 있도록 배열을 확장하는 방식으로 구현하였습니다.
val weakNum = weak.size
// 마지막 지점과 첫 지점을 다시 연결하도록 처리
val fullWeak = (weak + weak.map { it + n }).toList()

 

이제 이 fullWeak 배열을 이용해, 각 취약지점을 시작으로 하는 경우에서 친구들을 투입해 점검을 진행할 때,

몇 명의 친구가 필요한지 계산하여 최소값을 구하면 됩니다.🔥

 

그 외의 로직은 코드에 주석으로 적어두었습니다.

3. 코드

Kotlin
import kotlin.math.min

class Solution {
    fun solution(n: Int, weak: IntArray, dist: IntArray): Int {
        val friendsNum = dist.size
        val distPermu = dist.toList().permutations(friendsNum)
        
        var answer = friendsNum + 1

        val weakNum = weak.size
        val fullWeak = (weak + weak.map { it + n }).toList()
        // 각 취약지점을 시작점으로 지정해서 점검을 시작
        for (i in 0 until weakNum) {
            val repairs = fullWeak.subList(i, i + weakNum)
            // 모든 투입 가능한 순서를 탐색
            for (friend in distPermu) {
                var result = 1 // 투입한 친구의 수
                var friendIndex = 0 // 현재 투입중인 친구의 index
                // 현재 투입중인 친구의 위치
                var currentPos = repairs.first() + friend[friendIndex]
                
                // 취약지점을 순차적으로 점검할 수 있는지 검사
                for (z in 1 until weakNum) {
                    // 현재 투입중인 친구로는 해당 취약지점까지 이동할 수 없는 경우
                    if (repairs[z] > currentPos) {
                        // 새로운 친구 추가
                        result++
                        friendIndex++
                        // 더이상 투입할 수 있는 친구가 없는 경우
                        if (friendIndex >= friendsNum) break
                        // 투입중인 친구의 위치 변경
                        currentPos = repairs[z] + friend[friendIndex]
                    }
                }
                answer = min(answer, result)
            }
        }
        
        if (answer > friendsNum) return -1
        return answer
    }
    
    private fun <T> List<T>.permutations(k: Int): List<List<T>> {
        val result = mutableListOf<List<T>>()
        fun solve(k: Int, acc: MutableList<T>, visited: BooleanArray) {
            if (k == 0) {
                result.add(acc.toList())
                return
            }
            for ((index, i) in this.withIndex()) {
                if (visited[index].not()) {
                    visited[index] = true
                    acc.add(i)
                    solve(k-1, acc, visited)
                    acc.removeLast()
                    visited[index] = false
                }
            }
        }

        val n = this.size
        solve(k, mutableListOf(), BooleanArray(n))
        return result.toList()
    }
}
반응형