[Swift] [74일차] 다트게임_프로그래머스

·2025년 2월 19일
0

SwiftAlgorithm

목록 보기
77/105
post-thumbnail

다트 게임


문제 설명

  1. 다트 3게임에 해당하는 표시를 전달해줄테니 이걸 점수를 계산하라 (ex.1S2D*3T -> 37)
  2. *이 나오면 지금꺼랑 이전꺼에 X2 , #이 나오면 해당 라운드점수를 -로 수정

문제 풀이

  1. 이거
import Foundation

func solution(_ dartResult: String) -> Int {
    var calcu: [Character: Int] = ["S": 1, "D": 2, "T": 3]
    var operator_calcu: [Character: Int] = ["#": -1, "*": 2]
    var cur_score = -1
    var operator_arr = Array(repeating: 1, count: 3)
    var round = [Int]()
    var PRIZE = Set(["#", "*"])
    var answer = 0
    for item in dartResult {
        let LEN = round.count // 현재까지 나온 라운드 수
        if let num = Int(String(item)) {
            cur_score = num
        } else {
            if PRIZE.contains(String(item)) { // #,* 상일 때
                operator_arr[LEN - 1] = operator_calcu[item]!
                if item == "*" {
                    if LEN - 1 > 0 {
                        operator_arr[LEN - 2] *= 2
                    }
                }
            } else { // S , D , T
                round.append(Int(pow(Float(cur_score), Float(calcu[item]!))))
            }
        }
    }
    print(operator_arr)
    print(round)

    for i in 0 ..< 3 {
        print(round[i] * operator_arr[i])
        answer += round[i] * operator_arr[i]
    }
    return answer
}

// print(solution("1S2D*3T"))
print(solution("1D2S#10S"))
// 1S*2T*3S   -> 1 * 2^2  + 2^3 * 2 + 3 = 4+16+3
이거보니까 최대숫자 10일대에 대한 고려가 되지않아서 1, 0 으로 초기화돼서 세번째 라운드 점수가 0이 되어버리는 사태가 발생했다. 이걸 해결하기 위해서는 cur_score 를 문자열로서 붙여줘야할 것 같았다.

먼저 cur_score를 ""로 변경

var cur_score = "" 

그리고 숫자가 확정되는 시기에 cur_score를 다시 리셋해주는 로지긍ㄹ 추가했다. 물론 계산할때도 Int()로 씌워줘서 에러뜨지 않게 수정해줬다.

else { // S , D , T
                round.append(Int(pow(Float(Int(cur_score)!), Float(calcu[item]!))))
                cur_score = ""
            }

최종 제출

import Foundation

func solution(_ dartResult: String) -> Int {
    var calcu: [Character: Int] = ["S": 1, "D": 2, "T": 3]
    var operator_calcu: [Character: Int] = ["#": -1, "*": 2]
    var cur_score = "" as String
    var operator_arr = Array(repeating: 1, count: 3)
    var round = [Int]()
    var PRIZE = Set(["#", "*"])
    var answer = 0
    for item in dartResult {
        let LEN = round.count // 현재까지 나온 라운드 수
        if let num = Int(String(item)) {
            cur_score += String(num)
        } else {
            if PRIZE.contains(String(item)) { // #,* 상일 때
                operator_arr[LEN - 1] = operator_calcu[item]!
                if item == "*" {
                    if LEN - 1 > 0 {
                        operator_arr[LEN - 2] *= 2
                    }
                }
            } else { // S , D , T
                round.append(Int(pow(Float(Int(cur_score)!), Float(calcu[item]!))))
                cur_score = ""
            }
        }
    }


    for i in 0 ..< 3 {

        answer += round[i] * operator_arr[i]
    }
    return answer
}

채점 결과

정확성: 100.0
합계: 100.0 / 100.0


타인의 코드

스스로 코드가 좀 난잡해진것 같다고 느꼈고, 기존에 없었던 import foundation까지 작성해서 pow()를 사용했는데, 이걸 사용하지 않고는 어떻게 진행했을까도 궁금해서 모범코드들을 좀 살펴보았다.

func solution(_ dartResult:String) -> Int {
        let numberList = dartResult.split(whereSeparator: {$0.isLetter || $0 == "#" || $0 == "*"})
        let letterList = dartResult.split(whereSeparator: {$0.isNumber})
        var totalScore = 0
        for (i, (number, letter)) in zip(numberList, letterList).enumerated() {
            var score = 0
            if let number = Int(number) {
                score = letter.contains("D") ? number * number : letter.contains("T") ? number * number * number : number
            }
            if letter.contains("*") {
                score *= 2
            } else if letter.contains("#") {
                score = -score
            }
            if i != 2 {
                if letterList[i + 1].contains("*") {
                    score *= 2
                }
            }
            totalScore += score
        }
        return totalScore
}

난잡한 코드는 여기서 어떻게 다른가 ?

	let numberList = dartResult.split(whereSeparator: {$0.isLetter || $0 == "#" || $0 == "*"})
	let letterList = dartResult.split(whereSeparator: {$0.isNumber})

보시다시피 split을 사용했는데, 나는 이게 split하게 되면 원래 마크가 사라지는 것을 걱정했는데, 여기서는 그것대신에

어떻게 pow를 사용하지 않고 풀었나?

최대제곱이 세제곱이라 그냥 number * number * number 까지는 정직하게 작성을 해준 것을 확인했다.

 if let number = Int(number) {
                score = letter.contains("D") ? number * number : letter.contains("T") ? number * number * number : number
            }

예를들어 1D2S#10S가 들어왔을 때는 다음과 같이 정리가 되는 것이다.

["1", "2", "10"]
["D", "S#", "S"]

숫자+S,D,T / #,* 로 구분하려했었는데, 그게 아니라 이렇게 쪼개주면 깔끔하게 상이 없는 곳도 처리가 쉬워진다는 것이다.


profile
기억보단 기록을

0개의 댓글