iOS 공부하는 감자

[1차] 비밀지도 본문

알고리즘

[1차] 비밀지도

DongTaTo 2022. 1. 15. 15:12
반응형

비밀지도

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

  1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.
  2. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
  3. "지도 1"과 "지도 2"는 각각 정수 배열로 암호화되어 있다.
  4. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.

입력 형식

입력으로 지도의 한 변 크기 n 과 2개의 정수 배열 arr1, arr2가 들어온다.

  • 1 ≦ n ≦ 16
  • arr1, arr2는 길이 n인 정수 배열로 주어진다.
  • 정수 배열의 각 원소 x를 이진수로 변환했을 때의 길이는 n 이하이다. 즉, 0 ≦ x ≦ 2n - 1을 만족한다.

출력 형식

원래의 비밀지도를 해독하여 '#', 공백으로 구성된 문자열 배열로 출력하라.

입출력 예제

매개변수값

n 5
arr1 [9, 20, 28, 18, 11]
arr2 [30, 1, 21, 17, 28]
출력 ["#####","# # #", "### #", "# ##", "#####"]

매개변수값

n 6
arr1 [46, 33, 33 ,22, 31, 50]
arr2 [27 ,56, 19, 14, 14, 10]
출력 ["######", "### #", "## ##", " #### ", " #####", "### # "]

 

 


내 풀이

func addZero(binary: String, num: Int) -> String {
    var result: String  = binary
    for _ in 0..<(num-binary.count) {
        result = "0"+result
    }
    return result
}

func solution(_ n:Int, _ arr1:[Int], _ arr2:[Int]) -> [String] {
    let map1: [[String.Element]] = arr1.map({addZero(binary: String($0, radix: 2), num: n).map({$0})})
    let map2: [[String.Element]] = arr2.map({addZero(binary: String($0, radix: 2), num: n).map({$0})})
    
    var result: [[String]] = Array(repeating: Array(repeating: "", count: n), count: n)
    
    for i in 0..<n{
        for j in 0..<n{
            if map1[i][j] == "1" || map2[i][j] == "1"{
                result[i][j] = "#"
            }else {
                result[i][j] = " "
            }
        }
    }
    
    return result.map({$0.joined()})
}
  • 매개변수로 들어온 각 배열의 숫자를 2진수로 변환하고, 각 숫자를 담은 2차원 배열로 저장
  • 지도 크기에 맞게 빈 2차원 배열 생성
  • 두 배열의 index를 순환하며 둘중 하나라도 벽이 있으면 2에서 생성ㅇ한 배열에 "#"(벽)을 채우고, 아니면 공백을 채움
  • joined로 2차원 배열을 1차원으로 변환하여 return

 

다른사람 풀이1

func solution(_ n:Int, _ arr1:[Int], _ arr2:[Int]) -> [String] {
    return (0..<n).map { String(String(arr1[$0]|arr2[$0]|2<<(n - 1), radix: 2).map { $0 == "1" ? "#" : " " }[1...n]) }
}
  1. (0..<n)을 map 고차함수로 순환 (index값)
  2. 순환되는 index를 사용하여 arr1[index] | arr2[index] | 2<<(n-1) 비트연산을 수행  2<<(n-1)은 한 변의 길이만큼 2진수의 길이를 맞춰주기 위함.. 
  3. 2에서 나온 OR 비트연산 수행 결과를 String(String, raidx: Int) 를 사용하여 2진수로 변환
  4. 변환되어 나온 2진수 문자열에 map을 사용하여 3항 연산자 $0 == "1" ? "#" : " " 를 통해 문자열 값 변환 (여기까지 진행되면 각 라인별로 OR연산이 수행된 2진수 값을 배열로 가지게됨
  5. 각 라인별 2진수 배열에 [1...n] 범위를 map 고차함수의 return값으로 넘겨줌 ( 배열 범위를 1...n으로 잡는 이유는 (2)단계를 수행할 때 2<<(n-1)을 통해 한 변의 길이보다 1칸 더 많은 배열이 생성되었기 때문 )

 

 

 

다른사람 풀이2

func solution(_ n:Int, _ arr1:[Int], _ arr2:[Int]) -> [String] {
    var answer: [String] = []
    for i in 0..<n{
        var data = UInt16(arr1[i]) | UInt16(arr2[i])
        answer.append("")
        for _ in 0..<n{
            if data & 0b00000001 == 1{
                answer[i] = "#" + answer[i]
            }else{
                answer[i] = " " + answer[i]
            }
            data = data >> 1
        }
    }
    return answer
}

 

 

 

 

다른사람 풀이3

func solution(_ n:Int, _ arr1:[Int], _ arr2:[Int]) -> [String] {

    return (0..<n).map {
        let binary = String(arr1[$0] | arr2[$0], radix: 2)
        let padded = String(repeating: "0", count: n - binary.count) + binary
        return padded.reduce("") { $0 + ($1 == "0" ? " " : "#") }
    }
}

 

 

 

 

 

처음부터 비트 연산을 수행하라고 나온 문제였다.
문법 공부할 때 중요하게 보지 않아서 생각을 못했었는데 따로 한번 더 찾아봐야겠다!

 

 

반응형

'알고리즘' 카테고리의 다른 글

최소 직사각형  (0) 2022.01.16
나머지가 1이 되는 수 찾기  (0) 2022.01.16
2016년  (0) 2022.01.13
체육복  (0) 2022.01.12
모의고사  (0) 2022.01.11