[Swift] [32일차] N진수 게임

·2025년 1월 8일
0

SwiftAlgorithm

목록 보기
35/105
post-thumbnail

programmers-n진수 게임

문제 설명

  1. 숫자를 한명씩 돌아가면서 말하는구조, 여기서 특이한점은 11 이라면 이걸 2명이서 나눠서 말하는 구조
  2. 꼭 10진수만있는게 아니라 주어진 진수에 맞게 수행하면됨
  3. t번 말할때까지 그 숫자 하나씩 다 뭉쳐서 이제 길이가t가 됐을때 끝 ! 그걸 출력하면 정답

예를들어

전체 숫자: 0, 1, 10, 11, 100, 101, 110, 111
한 자리씩 나눔: 0, 1, 1, 0, 1, 1, 1, 0, ...
사람별 순서: [튜브(1번), 다른 사람(2번)] 
튜브가 말해야 하는 숫자: 0, 1, 1, 1 (1번친구 추적하면 0 , 1 , 1 ,1 말했음 )
결과 : "0111"

문제 접근

  1. 10진법으로 반복문을 시작하면서 하나씩 올려주면서 해당 진수 처리해주면 될 것 같기도 ?
  2. 번갈아가는거만 카운팅잘해주기

문제풀이

처음에는 enumerated()를 통해서 idx도 같이 추출을 하면서, 거기서 m을 한 것으로 순서를 체킹해줬는데, 이게 길이가 1인 경우에는 계속 한사람만 말하게 되더라! 그래서 counting_num이라는 거를 만들어줘서 while문밖의 전역변수로 관리해줬다.

    while tube_arr.count < t { // 길이가 t완성되면 끝 !
        let saying_num = String(current_num, radix: n) // 현재 불러야하는 것

        for (idx, value) in saying_num.enumerated() {

//            print(counting % m)
            if counting % m == p - 1 {
//                print(saying_num)
                tube_arr.append(String(value))
            }
            counting += 1
        }

        current_num += 1
    }

다음 제출코드

여기에서 문제는 0111나와야하는데, 01110이 나오는 문제가 있었다. 분명히
while tube_arr.count < t 로 제한조건을 걸어줬는데 왜 이렇게 됐지? 해서 디버깅한 결과, 이게 for문 안에서 남은게 있으면 더 체킹을 하고 있더라! 그래서 안에서 조건에따라 t길이가 충족되면 바로 break해주도록 수정을 해줬다.

func solution(_ n: Int, _ t: Int, _ m: Int, _ p: Int) -> String {
    var current_num = 0
    var tube_arr = [String]()
    var counting = 0
    while tube_arr.count < t { // 길이가 t완성되면 끝 !
        let saying_num = String(current_num, radix: n) // 현재 불러야하는 것

        for (idx, value) in saying_num.enumerated() {

//            print(counting % m)
            if counting % m == p - 1 {
//                print(saying_num)
                tube_arr.append(String(value))
            }
            counting += 1
        }

        current_num += 1
    }

    return tube_arr.reduce("") { $0 + $1 }.uppercased() // t길이를 string으로 바꿔주기 !
}

최종 제출 코드

func solution(_ n: Int, _ t: Int, _ m: Int, _ p: Int) -> String {
    var current_num = 0
    var tube_arr = [String]()
    var counting = 0
    while tube_arr.count < t { // 길이가 t완성되면 끝 !
        let saying_num = String(current_num, radix: n) // 현재 불러야하는 것

        for (value) in saying_num {
            if tube_arr.count == t {
                break
            }
//            print(counting % m)
            if counting % m == p - 1 {
//                print(saying_num)
                tube_arr.append(String(value))
            }
            counting += 1
        }

        current_num += 1
    }

    return tube_arr.reduce("") { $0 + $1 }.uppercased() // t길이를 string으로 바꿔주기 !
}

채점 결과

정확성: 100.0
합계: 100.0 / 100.0
생각보다 쉽게 풀렸던 것 같다. String(num,radix:바꾸고싶은 진수)사용하면 숫자를 쉽게 바꿀 수 있어서 무리없이 풀 수 있었던 것 같다.


타인의 코드

func solution(_ n: Int, _ t: Int, _ m: Int, _ p: Int) -> String {
    let count = t*m
    var values: [String] = []
    var number = 0
    while values.count < count {
        values += String(number, radix: n).compactMap({ String($0).uppercased() })
        number += 1
    }
    return stride(from: p - 1, to: count, by: m).reduce("", { $0 + values[$1] })
}

values 배열의 길이를 직관적인 t로 하지않고, m으로해서 사람수까지 거른다음에 stride활용해주는게 새로운 접근이라 신기했다.
특히 이부분 stride(from: p - 1, to: count, by: m) 좀 더 알아보자면 ...
범위안에서 반복처리를 해주는 함수라고 생각하시면 될 것 같다.
역순서 배열을 만들 때 사용했던 것인데, p-1 순서부터 시작해서, 카운트까지 m주기로 깡총뛰면서 체킹하는거니까 m순번 도는게 깔끔하게 가능하다. 항상 %로 인덱스 계산하는게 왜인지모르게 나한텐 어려운데, 이런방식으로 트라이 해보는것도 좋을 듯 !

profile
기억보단 기록을

0개의 댓글